feat: implement nhentai login and refactor large pieces of code in the process
This commit is contained in:
parent
6d82b16d5c
commit
389df67605
|
@ -1,2 +1,3 @@
|
||||||
|
node_modules
|
||||||
dist
|
dist
|
||||||
frontend
|
frontend
|
||||||
|
|
|
@ -13,5 +13,13 @@
|
||||||
"no-shadow": "warn",
|
"no-shadow": "warn",
|
||||||
"no-magic-numbers": ["warn", { "ignore": [0, 1, -1] }],
|
"no-magic-numbers": ["warn", { "ignore": [0, 1, -1] }],
|
||||||
"no-param-reassign": "warn"
|
"no-param-reassign": "warn"
|
||||||
}
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["src/renderer/**/*.*"],
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "module"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
29
src/main.ts
29
src/main.ts
|
@ -1,22 +1,41 @@
|
||||||
import { app, BrowserWindow } from 'electron';
|
import { app, BrowserWindow } from 'electron';
|
||||||
|
import os from 'os';
|
||||||
|
|
||||||
import './main/controllers/api';
|
import './main/controllers/api';
|
||||||
import './main/services/database';
|
import './main/services/database';
|
||||||
import session from './main/services/session';
|
import * as session from './main/services/session';
|
||||||
|
import BrowserWindowConstructorOptions = Electron.BrowserWindowConstructorOptions;
|
||||||
|
|
||||||
let mainWindow: Electron.BrowserWindow;
|
let mainWindow: Electron.BrowserWindow;
|
||||||
|
|
||||||
async function createWindow(): Promise<void> {
|
async function createWindow(): Promise<void> {
|
||||||
session.init();
|
session.setHeaders();
|
||||||
|
|
||||||
// Create the browser window.
|
// universal options
|
||||||
mainWindow = new BrowserWindow({
|
let options: BrowserWindowConstructorOptions = {
|
||||||
width: 1600,
|
width: 1600,
|
||||||
height: 900,
|
height: 900,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// platform specifics
|
||||||
|
switch (os.platform()) {
|
||||||
|
case 'win32':
|
||||||
|
options = {
|
||||||
|
...options,
|
||||||
|
...{
|
||||||
|
icon: 'resources/icon.ico',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the browser window.
|
||||||
|
mainWindow = new BrowserWindow(options);
|
||||||
|
|
||||||
// and load the index.html of the app.
|
// and load the index.html of the app.
|
||||||
await mainWindow.loadFile('index.html');
|
await mainWindow.loadFile('index.html');
|
||||||
|
|
|
@ -1,13 +1,32 @@
|
||||||
import { ipcMain } from 'electron';
|
import { ipcMain } from 'electron';
|
||||||
import nhentai from './../services/nhentai-crawler';
|
import { isLoggedIn, login } from '../services/nhentai-crawler';
|
||||||
|
|
||||||
ipcMain.on(IpcChannels.Credentials, (event: IpcEvent, args: ICredentials) => {
|
const ipcServer: IIpcServer = {
|
||||||
nhentai
|
answer: (channel: IpcChannels, handler: (data?: any) => Promise<any>): void => {
|
||||||
.login(args.name, args.password)
|
ipcMain.on(channel, (event: IpcEvent, payload: IIpcPayload) => {
|
||||||
.then(() => {
|
handler(payload.data)
|
||||||
console.log('success');
|
.then((result: any) => {
|
||||||
})
|
const response: IIpcResponse = {
|
||||||
.catch(() => {
|
success: true,
|
||||||
console.log('fail');
|
data: result,
|
||||||
|
};
|
||||||
|
event.reply(channel, response);
|
||||||
|
})
|
||||||
|
.catch((reason: any) => {
|
||||||
|
const response: IIpcResponse = {
|
||||||
|
success: false,
|
||||||
|
error: reason.toString(),
|
||||||
|
};
|
||||||
|
event.reply(channel, response);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
ipcServer.answer(IpcChannels.LOGIN, (credentials: ICredentials) => {
|
||||||
|
return login(credentials.name, credentials.password);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcServer.answer(IpcChannels.LOGGED_IN, () => {
|
||||||
|
return isLoggedIn();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { Connection, createConnection } from 'typeorm';
|
import { Connection, createConnection } from 'typeorm';
|
||||||
|
|
||||||
export let library: Connection;
|
export const enum Databases {
|
||||||
|
LIBRARY = 'library',
|
||||||
function init(): void {
|
|
||||||
initConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function initConnection(): void {
|
const connections: {
|
||||||
// createConnection method will automatically read connection options
|
[key in Databases]?: Connection;
|
||||||
// from your ormconfig file or environment variables
|
} = {};
|
||||||
createConnection('library')
|
|
||||||
.then((c: Connection) => {
|
export function getConnection(database: Databases): Promise<Connection> {
|
||||||
library = c;
|
if (connections[database] === undefined) {
|
||||||
})
|
return createConnection(database).then((connection: Connection) => {
|
||||||
.catch((reason: any) => {
|
connections[database] = connection;
|
||||||
throw reason;
|
return connection;
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve(connections[database]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
import { RequestInit, Response } from 'node-fetch';
|
import { RequestInit, Response } from 'node-fetch';
|
||||||
import RenaiError, { Errors } from '../../types/error';
|
import { Errors, RenaiError } from '../../types/error';
|
||||||
import fetch from './web-crawler';
|
import { fetch } from './web-crawler';
|
||||||
|
|
||||||
const url = 'https://nhentai.net/';
|
const domain = 'nhentai.net';
|
||||||
|
const url = `https://${domain}/`;
|
||||||
|
|
||||||
const paths = {
|
const paths = {
|
||||||
books: 'g/',
|
books: 'g/',
|
||||||
|
@ -25,33 +26,6 @@ interface ILoginAuth {
|
||||||
|
|
||||||
interface ILoginParams extends ILoginMeta, ILoginAuth {}
|
interface ILoginParams extends ILoginMeta, ILoginAuth {}
|
||||||
|
|
||||||
function login(name: string, password: string): Promise<void> {
|
|
||||||
return getLoginMeta()
|
|
||||||
.then((meta: ILoginMeta) => {
|
|
||||||
const loginParams: ILoginParams = {
|
|
||||||
...meta,
|
|
||||||
...{
|
|
||||||
// tslint:disable-next-line: object-literal-sort-keys
|
|
||||||
username_or_email: name,
|
|
||||||
password,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return postNHentai(paths.login, {
|
|
||||||
body: encodeURI(
|
|
||||||
Object.keys(loginParams)
|
|
||||||
.map((key: keyof ILoginParams) => `${key}=${loginParams[key]}`)
|
|
||||||
.join('&')
|
|
||||||
),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(() => {})
|
|
||||||
.catch(() => Promise.reject(new RenaiError(Errors.ELOGINFAIL)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNHentai(path: string): Promise<Document> {
|
function getNHentai(path: string): Promise<Document> {
|
||||||
return fetch(`${url}${path}`)
|
return fetch(`${url}${path}`)
|
||||||
.then((res: Response) => {
|
.then((res: Response) => {
|
||||||
|
@ -63,8 +37,21 @@ function getNHentai(path: string): Promise<Document> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function postNHentai(path: string, init: RequestInit = {}): Promise<Response> {
|
function postNHentai(path: string, requestInit: RequestInit = {}): Promise<Response> {
|
||||||
return fetch(`${url}${path}`, { ...init, ...{ method: 'post' } });
|
const postUrl = `${url}${path}`;
|
||||||
|
return fetch(postUrl, {
|
||||||
|
...requestInit,
|
||||||
|
...{
|
||||||
|
headers: {
|
||||||
|
...requestInit.headers,
|
||||||
|
...{
|
||||||
|
Host: domain,
|
||||||
|
Referer: postUrl,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
method: 'post',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLoginMeta(): Promise<ILoginMeta> {
|
function getLoginMeta(): Promise<ILoginMeta> {
|
||||||
|
@ -93,6 +80,36 @@ function getLoginMeta(): Promise<ILoginMeta> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export function isLoggedIn(): Promise<boolean> {
|
||||||
login,
|
return fetch(`${url}${paths.favorites}`, { redirect: 'manual' }).then((res: Response) => {
|
||||||
};
|
return res.status === HttpCode.OK;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function login(name: string, password: string): Promise<void> {
|
||||||
|
return getLoginMeta()
|
||||||
|
.then((meta: ILoginMeta) => {
|
||||||
|
const loginParams: ILoginParams = {
|
||||||
|
...meta,
|
||||||
|
...{
|
||||||
|
// tslint:disable-next-line: object-literal-sort-keys
|
||||||
|
username_or_email: name,
|
||||||
|
password,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return postNHentai(paths.login, {
|
||||||
|
body: encodeURI(
|
||||||
|
Object.keys(loginParams)
|
||||||
|
.map((key: keyof ILoginParams) => `${key}=${loginParams[key]}`)
|
||||||
|
.join('&')
|
||||||
|
),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
redirect: 'manual',
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {})
|
||||||
|
.catch(() => Promise.reject(new RenaiError(Errors.ELOGINFAIL)));
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { session } from 'electron';
|
import { session } from 'electron';
|
||||||
import OnHeadersReceivedDetails = Electron.OnHeadersReceivedDetails;
|
import OnHeadersReceivedDetails = Electron.OnHeadersReceivedDetails;
|
||||||
|
|
||||||
function init(): void {
|
export function setHeaders(): void {
|
||||||
// these headers only work on webrequests, file:// protocol is handled via meta tags in index.html
|
// these headers only work on web requests, file:// protocol is handled via meta tags in index.html
|
||||||
session.defaultSession.webRequest.onHeadersReceived(
|
session.defaultSession.webRequest.onHeadersReceived(
|
||||||
(details: OnHeadersReceivedDetails, callback: (response: {}) => void) => {
|
(details: OnHeadersReceivedDetails, callback: (response: {}) => void) => {
|
||||||
callback({
|
callback({
|
||||||
|
@ -14,5 +14,3 @@ function init(): void {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { init };
|
|
||||||
|
|
|
@ -1,27 +1,55 @@
|
||||||
|
import { CookieJar } from 'jsdom';
|
||||||
import nodeFetch, { RequestInit, Response } from 'node-fetch';
|
import nodeFetch, { RequestInit, Response } from 'node-fetch';
|
||||||
import { Cookie, CookieJar } from 'tough-cookie';
|
import { Errors, RenaiError } from '../../types/error';
|
||||||
|
import { load, save, StoreKeys } from './store';
|
||||||
|
|
||||||
const cookieJar: CookieJar = new CookieJar();
|
export let cookieJar: CookieJar = new CookieJar();
|
||||||
|
|
||||||
function fetch(url: string, init: RequestInit = {}): Promise<Response> {
|
let error: Error;
|
||||||
const headers: HeadersInit = {};
|
|
||||||
cookieJar.getCookiesSync(url).forEach((cookie: Cookie) => {
|
function init(): void {
|
||||||
headers[cookie.key] = cookie.value;
|
load(StoreKeys.COOKIES)
|
||||||
});
|
.then((cookies: any) => {
|
||||||
|
if (cookies !== undefined) {
|
||||||
|
cookieJar = CookieJar.deserializeSync(cookies);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((reason: any) => {
|
||||||
|
error = new RenaiError(Errors.EINITFAIL, reason);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetch(url: string, requestInit: RequestInit = {}): Promise<Response> {
|
||||||
|
if (error !== undefined) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
const cookiedInit = {
|
const cookiedInit = {
|
||||||
...init,
|
...requestInit,
|
||||||
...{ headers: { ...init.headers, ...headers } },
|
...{
|
||||||
|
headers: {
|
||||||
|
...requestInit.headers,
|
||||||
|
...{
|
||||||
|
Cookie: cookieJar.getCookieStringSync(url),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
return nodeFetch(url, cookiedInit).then((res: Response) => {
|
return nodeFetch(url, cookiedInit).then((res: Response) => {
|
||||||
setCookies(res.headers.raw()['set-cookie'], url);
|
setCookies(res.headers.raw()['set-cookie'], url).catch((reason: any) => {
|
||||||
|
error = new Error(reason);
|
||||||
|
});
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCookies(header: string[], url: string): void {
|
function setCookies(header: string[], url: string): Promise<void> {
|
||||||
header.forEach((cookie: string) => {
|
if (header) {
|
||||||
cookieJar.setCookieSync(cookie, url);
|
header.forEach((cookie: string) => {
|
||||||
});
|
cookieJar.setCookieSync(cookie, url);
|
||||||
|
});
|
||||||
|
return save(StoreKeys.COOKIES, cookieJar.serializeSync());
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
export default fetch;
|
init();
|
||||||
|
|
|
@ -1,16 +1,7 @@
|
||||||
|
{Divide,NhentaiLogin;}
|
||||||
<script>
|
<script>
|
||||||
import Bttn from 'atoms/Bttn.svelte';
|
|
||||||
import Divide from 'molecules/Divide.svelte';
|
import Divide from 'molecules/Divide.svelte';
|
||||||
import api from 'services/api';
|
import NhentaiLogin from 'polymers/NhentaiLogin.svelte';
|
||||||
|
|
||||||
let form = {
|
|
||||||
name: '',
|
|
||||||
password: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
function handleClick() {
|
|
||||||
api.sendCredentials(form);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -57,18 +48,7 @@
|
||||||
<main>
|
<main>
|
||||||
<Divide>
|
<Divide>
|
||||||
<div slot="1">
|
<div slot="1">
|
||||||
<h1>Login</h1>
|
<NhentaiLogin></NhentaiLogin>
|
||||||
<form>
|
|
||||||
<label>
|
|
||||||
<span>Username/Email</span>
|
|
||||||
<input bind:value="{form.name}" />
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
<span>Password</span>
|
|
||||||
<input bind:value="{form.password}" type="password" />
|
|
||||||
</label>
|
|
||||||
<Bttn on:click="{handleClick}">submit</Bttn>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<div slot="2">
|
<div slot="2">
|
||||||
<Divide mode="v">
|
<Divide mode="v">
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte/internal';
|
||||||
|
import { t } from 'services/utils';
|
||||||
|
import Bttn from 'atoms/Bttn.svelte';
|
||||||
|
import { loggedIn } from 'services/store';
|
||||||
|
|
||||||
|
let form = {
|
||||||
|
name: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
loggedIn.fetchLogin(form).catch((reason) => {
|
||||||
|
console.log(reason);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
loggedIn.fetchIsLoggedIn();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
||||||
|
|
||||||
|
<div class="nhentai-login">
|
||||||
|
{#if $loggedIn}
|
||||||
|
<div>logged in!</div>
|
||||||
|
{:else}
|
||||||
|
<form class="nhentai-login">
|
||||||
|
<label>
|
||||||
|
<span>{ t('Username/Email') }</span>
|
||||||
|
<input bind:value="{form.name}" />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>{ t('Password') }</span>
|
||||||
|
<input bind:value="{form.password}" type="password" />
|
||||||
|
</label>
|
||||||
|
<Bttn on:click="{handleClick}">submit</Bttn>
|
||||||
|
</form>
|
||||||
|
{/if}
|
||||||
|
</div>
|
|
@ -1,9 +1,31 @@
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
|
import IpcMessageEvent = Electron.IpcMessageEvent;
|
||||||
|
|
||||||
function sendCredentials(credentials: ICredentials): void {
|
const ipcClient: IIpcClient = {
|
||||||
ipcRenderer.send(IpcChannels.Credentials, credentials);
|
ask: (channel: IpcChannels, data?: any): Promise<any> => {
|
||||||
|
const payload: IIpcPayload = {
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve: (value?: any) => void, reject: (reason?: any) => void): void => {
|
||||||
|
const listener = (event: IpcMessageEvent, response: IIpcResponse): void => {
|
||||||
|
if (response.success) {
|
||||||
|
resolve(response.data);
|
||||||
|
} else {
|
||||||
|
reject(response.error);
|
||||||
|
}
|
||||||
|
ipcRenderer.removeListener(channel, listener);
|
||||||
|
};
|
||||||
|
ipcRenderer.send(channel, payload);
|
||||||
|
ipcRenderer.on(channel, listener);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function login(credentials: ICredentials): Promise<void> {
|
||||||
|
return ipcClient.ask(IpcChannels.LOGIN, credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export function isLoggedIn(): Promise<boolean> {
|
||||||
sendCredentials,
|
return ipcClient.ask(IpcChannels.LOGGED_IN);
|
||||||
};
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
import * as api from './api';
|
||||||
|
|
||||||
|
const { subscribe, set } = writable<boolean>(false);
|
||||||
|
|
||||||
|
export const loggedIn = {
|
||||||
|
subscribe,
|
||||||
|
fetchIsLoggedIn(): Promise<void> {
|
||||||
|
return api.isLoggedIn().then((isLoggedIn: boolean) => {
|
||||||
|
set(isLoggedIn);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fetchLogin(credentials: ICredentials): Promise<void> {
|
||||||
|
return api.login(credentials).then(() => {
|
||||||
|
return this.fetchIsLoggedIn();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
|
@ -11,3 +11,8 @@ export function s(styles: object): string {
|
||||||
.map((key: keyof object) => `${key}:${styles[key]}`)
|
.map((key: keyof object) => `${key}:${styles[key]}`)
|
||||||
.join(';');
|
.join(';');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function t(text: string): string {
|
||||||
|
// If you want to implement frontend translation, begin here.
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
|
@ -2,16 +2,18 @@ export const enum Errors {
|
||||||
ERROR = 'ERROR',
|
ERROR = 'ERROR',
|
||||||
ENOLOGIN = 'ENOLOGIN',
|
ENOLOGIN = 'ENOLOGIN',
|
||||||
ELOGINFAIL = 'ELOGINFAIL',
|
ELOGINFAIL = 'ELOGINFAIL',
|
||||||
|
EINITFAIL = 'EINITFAIL',
|
||||||
}
|
}
|
||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
[Errors.ERROR]: 'error',
|
[Errors.ERROR]: 'generic error',
|
||||||
[Errors.ENOLOGIN]: 'no login form found',
|
[Errors.ENOLOGIN]: 'no login form found',
|
||||||
[Errors.ELOGINFAIL]: 'login failed',
|
[Errors.ELOGINFAIL]: 'login failed',
|
||||||
|
[Errors.EINITFAIL]: 'initialization failed',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class RenaiError extends Error {
|
export class RenaiError extends Error {
|
||||||
constructor(eno: Errors = Errors.ERROR, msg: string = '') {
|
constructor(eno: Errors = Errors.ERROR, msg: string = '') {
|
||||||
super(`Error ${eno}: ${messages[eno]}.${msg ? ` ${msg}` : ''}`);
|
super(`${messages[eno]}.${msg ? ` ${msg}` : ''}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
const enum HttpCode {
|
||||||
|
// 100
|
||||||
|
'CONTINUE' = 100,
|
||||||
|
'SWITCHING_PROTOCOLS' = 101,
|
||||||
|
'PROCESSING' = 102,
|
||||||
|
|
||||||
|
// 200
|
||||||
|
'OK' = 200,
|
||||||
|
'CREATED' = 201,
|
||||||
|
'ACCEPTED' = 202,
|
||||||
|
'NON_AUTHORITATIVE_INFORMATION' = 203,
|
||||||
|
'NO_CONTENT' = 204,
|
||||||
|
'RESET_CONTENT' = 205,
|
||||||
|
'PARTIAL_CONTENT' = 206,
|
||||||
|
'MULTI_STATUS' = 207,
|
||||||
|
|
||||||
|
// 300
|
||||||
|
'MULTIPLE_CHOICES' = 300,
|
||||||
|
'MOVED_PERMANENTLY' = 301,
|
||||||
|
'MOVED_TEMPORARILY' = 302,
|
||||||
|
'SEE_OTHER' = 303,
|
||||||
|
'NOT_MODIFIED' = 304,
|
||||||
|
'USE_PROXY' = 305,
|
||||||
|
'TEMPORARY_REDIRECT' = 307,
|
||||||
|
'PERMANENT_REDIRECT' = 308,
|
||||||
|
|
||||||
|
// 400
|
||||||
|
'BAD_REQUEST' = 400,
|
||||||
|
'UNAUTHORIZED' = 401,
|
||||||
|
'PAYMENT_REQUIRED' = 402,
|
||||||
|
'FORBIDDEN' = 403,
|
||||||
|
'NOT_FOUND' = 404,
|
||||||
|
'METHOD_NOT_ALLOWED' = 405,
|
||||||
|
'NOT_ACCEPTABLE' = 406,
|
||||||
|
'PROXY_AUTHENTICATION_REQUIRED' = 407,
|
||||||
|
'REQUEST_TIMEOUT' = 408,
|
||||||
|
'CONFLICT' = 409,
|
||||||
|
'GONE' = 410,
|
||||||
|
'LENGTH_REQUIRED' = 411,
|
||||||
|
'PRECONDITION_FAILED' = 412,
|
||||||
|
'REQUEST_TOO_LONG' = 413,
|
||||||
|
'REQUEST_URI_TOO_LONG' = 414,
|
||||||
|
'UNSUPPORTED_MEDIA_TYPE' = 415,
|
||||||
|
'REQUESTED_RANGE_NOT_SATISFIABLE' = 416,
|
||||||
|
'EXPECTATION_FAILED' = 417,
|
||||||
|
'IM_A_TEAPOT' = 418,
|
||||||
|
'INSUFFICIENT_SPACE_ON_RESOURCE' = 419,
|
||||||
|
'METHOD_FAILURE' = 420, // nice
|
||||||
|
'UNPROCESSABLE_ENTITY' = 422,
|
||||||
|
'LOCKED' = 423,
|
||||||
|
'FAILED_DEPENDENCY' = 424,
|
||||||
|
'PRECONDITION_REQUIRED' = 428,
|
||||||
|
'TOO_MANY_REQUESTS' = 429,
|
||||||
|
'REQUEST_HEADER_FIELDS_TOO_LARGE' = 431,
|
||||||
|
|
||||||
|
// 500
|
||||||
|
'INTERNAL_SERVER_ERROR' = 500,
|
||||||
|
'NOT_IMPLEMENTED' = 501,
|
||||||
|
'BAD_GATEWAY' = 502,
|
||||||
|
'SERVICE_UNAVAILABLE' = 503,
|
||||||
|
'GATEWAY_TIMEOUT' = 504,
|
||||||
|
'HTTP_VERSION_NOT_SUPPORTED' = 505,
|
||||||
|
'INSUFFICIENT_STORAGE' = 507,
|
||||||
|
'NETWORK_AUTHENTICATION_REQUIRED' = 511,
|
||||||
|
}
|
|
@ -1,8 +1,27 @@
|
||||||
const enum IpcChannels {
|
const enum IpcChannels {
|
||||||
Credentials = 'CREDENTIALS',
|
LOGIN = 'LOGIN',
|
||||||
|
LOGGED_IN = 'LOGGED_IN',
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IIpcPayload {
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IIpcResponse {
|
||||||
|
success: boolean;
|
||||||
|
data?: any;
|
||||||
|
error?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ICredentials {
|
interface ICredentials {
|
||||||
name: string;
|
name: string;
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IIpcClient {
|
||||||
|
ask: (channel: IpcChannels, data?: any) => Promise<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IIpcServer {
|
||||||
|
answer: (channel: IpcChannels, handler: (data?: any) => Promise<any>) => void;
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
"no-empty": [true, "allow-empty-functions"],
|
"no-empty": [true, "allow-empty-functions"],
|
||||||
"no-magic-numbers": true,
|
"no-magic-numbers": true,
|
||||||
"no-parameter-reassignment": true,
|
"no-parameter-reassignment": true,
|
||||||
"arrow-return-shorthand": true
|
"arrow-return-shorthand": true,
|
||||||
|
"no-default-export": true
|
||||||
},
|
},
|
||||||
"jsRules": true
|
"jsRules": true
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,15 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.mjs$/,
|
||||||
|
include: /node_modules/,
|
||||||
|
type: 'javascript/auto',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.js', '.ts'],
|
extensions: ['.js', '.ts', '.mjs'],
|
||||||
alias: {
|
alias: {
|
||||||
atoms: path.resolve(__dirname, 'src/renderer/components/1-atoms'),
|
atoms: path.resolve(__dirname, 'src/renderer/components/1-atoms'),
|
||||||
molecules: path.resolve(__dirname, 'src/renderer/components/2-molecules'),
|
molecules: path.resolve(__dirname, 'src/renderer/components/2-molecules'),
|
||||||
|
|
Loading…
Reference in New Issue