Upgrade wms-core and add eslint

This commit is contained in:
Alice Gaudon 2020-10-05 13:38:03 +02:00
parent d91110fb67
commit a8bad1c8c1
11 changed files with 181 additions and 40 deletions

114
.eslintrc.json Normal file
View File

@ -0,0 +1,114 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"parserOptions": {
"project": [
"./tsconfig.json",
"./tsconfig.test.json",
"./tsconfig.frontend.json"
]
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"indent": [
"error",
4,
{
"SwitchCase": 1
}
],
"no-trailing-spaces": "error",
"max-len": [
"error",
{
"code": 120,
"ignoreStrings": true,
"ignoreTemplateLiterals": true,
"ignoreRegExpLiterals": true
}
],
"semi": "off",
"@typescript-eslint/semi": [
"error"
],
"no-extra-semi": "error",
"eol-last": "error",
"comma-dangle": "off",
"@typescript-eslint/comma-dangle": [
"error",
{
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "always-multiline",
"enums": "always-multiline",
"generics": "always-multiline",
"tuples": "always-multiline"
}
],
"no-extra-parens": "off",
"@typescript-eslint/no-extra-parens": [
"error"
],
"no-nested-ternary": "error",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/explicit-module-boundary-types": "error",
"@typescript-eslint/no-unnecessary-condition": "error",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_"
}
],
"@typescript-eslint/no-non-null-assertion": "error",
"no-useless-return": "error",
"no-useless-constructor": "off",
"@typescript-eslint/no-useless-constructor": [
"error"
],
"no-return-await": "off",
"@typescript-eslint/return-await": [
"error",
"always"
],
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/no-floating-promises": "error"
},
"ignorePatterns": [
"jest.config.js",
"webpack.config.js",
"dist/**/*",
"public/**/*",
"config/**/*"
],
"overrides": [
{
"files": [
"test/**/*"
],
"rules": {
"max-len": [
"error",
{
"code": 120,
"ignoreTemplateLiterals": true,
"ignoreRegExpLiterals": true,
"ignoreStrings": true
}
]
}
}
]
}

View File

@ -8,13 +8,13 @@ export default class PersistentWebsocket {
) { ) {
} }
public run() { public run(): void {
this.webSocket = new WebSocket(this.url); const _webSocket = this.webSocket = new WebSocket(this.url);
this.webSocket.addEventListener('open', (e) => { this.webSocket.addEventListener('open', () => {
console.debug('Websocket connected'); console.debug('Websocket connected');
}); });
this.webSocket.addEventListener('message', (e) => { this.webSocket.addEventListener('message', (e) => {
this.handler(this.webSocket!, e); this.handler(_webSocket, e);
}); });
this.webSocket.addEventListener('error', (e) => { this.webSocket.addEventListener('error', (e) => {
console.error('Websocket error', e); console.error('Websocket error', e);
@ -29,7 +29,7 @@ export default class PersistentWebsocket {
}); });
} }
public send(data: string) { public send(data: string): void {
if (!this.webSocket) throw new Error('WebSocket not connected'); if (!this.webSocket) throw new Error('WebSocket not connected');
this.webSocket.send(data); this.webSocket.send(data);

View File

@ -1,7 +1,9 @@
/* /*
* For labels to update their state (css selectors based on the value attribute) * For labels to update their state (css selectors based on the value attribute)
*/ */
export function updateInputs() { import {ValidationError} from "wms-core/db/Validator";
export function updateInputs(): void {
document.querySelectorAll<HTMLInputElement | HTMLTextAreaElement>('input, textarea').forEach(el => { document.querySelectorAll<HTMLInputElement | HTMLTextAreaElement>('input, textarea').forEach(el => {
if (!el.dataset.inputSetup) { if (!el.dataset.inputSetup) {
el.dataset.inputSetup = 'true'; el.dataset.inputSetup = 'true';
@ -19,7 +21,10 @@ document.addEventListener('DOMContentLoaded', () => {
updateInputs(); updateInputs();
}); });
export function applyFormMessages(formElement: HTMLFormElement, messages: { [p: string]: any }) { export function applyFormMessages(
formElement: HTMLFormElement,
messages: { [p: string]: ValidationError<unknown> },
): void {
for (const fieldName of Object.keys(messages)) { for (const fieldName of Object.keys(messages)) {
const field = formElement.querySelector('#field-' + fieldName); const field = formElement.querySelector('#field-' + fieldName);
if (!field) continue; if (!field) continue;
@ -27,14 +32,12 @@ export function applyFormMessages(formElement: HTMLFormElement, messages: { [p:
let parent = field.parentElement; let parent = field.parentElement;
while (parent && !parent.classList.contains('form-field')) parent = parent.parentElement; while (parent && !parent.classList.contains('form-field')) parent = parent.parentElement;
if (field) { let err = field.querySelector('.error');
let err = field.querySelector('.error'); if (!err) {
if (!err) { err = document.createElement('div');
err = document.createElement('div'); err.classList.add('error');
err.classList.add('error'); parent?.insertBefore(err, parent.querySelector('.hint') || parent);
parent?.insertBefore(err, parent.querySelector('.hint') || parent);
}
err.innerHTML = `<i data-feather="x-circle"></i> ${messages[fieldName].message}`;
} }
err.innerHTML = `<i data-feather="x-circle"></i> ${messages[fieldName].message}`;
} }
} }

View File

@ -1,4 +1,4 @@
export function updateTooltips() { export function updateTooltips(): void {
console.debug('Updating tooltips'); console.debug('Updating tooltips');
const elements = document.querySelectorAll<HTMLElement>('.tip, .dropdown'); const elements = document.querySelectorAll<HTMLElement>('.tip, .dropdown');

View File

@ -9,9 +9,12 @@
"scripts": { "scripts": {
"test": "jest --verbose --runInBand", "test": "jest --verbose --runInBand",
"dist-webpack": "webpack --mode production", "dist-webpack": "webpack --mode production",
"dist": "(test ! -d dist || rm -r dist) && tsc && npm run dist-webpack", "dist": "yarn compile && yarn dist-webpack",
"clean": "(test ! -d dist || rm -r dist)",
"compile": "yarn clean && tsc && mv dist/src/* dist/",
"dev": "concurrently -k -n \"Typescript,Node,Webpack,Maildev\" -p \"[{name}]\" -c \"blue,green,red,yellow\" \"tsc --watch\" \"nodemon\" \"webpack --watch --mode development\" \"maildev\"", "dev": "concurrently -k -n \"Typescript,Node,Webpack,Maildev\" -p \"[{name}]\" -c \"blue,green,red,yellow\" \"tsc --watch\" \"nodemon\" \"webpack --watch --mode development\" \"maildev\"",
"start": "yarn dist && node dist/main.js" "start": "yarn dist && node dist/main.js",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.9.0", "@babel/core": "^7.9.0",
@ -28,9 +31,12 @@
"@types/nodemailer": "^6.4.0", "@types/nodemailer": "^6.4.0",
"@types/nunjucks": "^3.1.3", "@types/nunjucks": "^3.1.3",
"@types/ws": "^7.2.6", "@types/ws": "^7.2.6",
"@typescript-eslint/eslint-plugin": "^4.3.0",
"@typescript-eslint/parser": "^4.3.0",
"babel-loader": "^8.1.0", "babel-loader": "^8.1.0",
"concurrently": "^5.1.0", "concurrently": "^5.1.0",
"css-loader": "^4.2.2", "css-loader": "^4.2.2",
"eslint": "^7.10.0",
"feather-icons": "^4.28.0", "feather-icons": "^4.28.0",
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"imagemin": "^7.0.1", "imagemin": "^7.0.1",
@ -55,6 +61,6 @@
"dependencies": { "dependencies": {
"config": "^3.3.1", "config": "^3.3.1",
"express": "^4.17.1", "express": "^4.17.1",
"wms-core": "^0.21.7" "wms-core": "^0.22.0-rc.24"
} }
} }

View File

@ -1,6 +1,5 @@
import Application from "wms-core/Application"; import Application from "wms-core/Application";
import {Type} from "wms-core/Utils"; import Migration, {MigrationType} from "wms-core/db/Migration";
import Migration from "wms-core/db/Migration";
import CreateMigrationsTable from "wms-core/migrations/CreateMigrationsTable"; import CreateMigrationsTable from "wms-core/migrations/CreateMigrationsTable";
import CreateLogsTable from "wms-core/migrations/CreateLogsTable"; import CreateLogsTable from "wms-core/migrations/CreateLogsTable";
import ExpressAppComponent from "wms-core/components/ExpressAppComponent"; import ExpressAppComponent from "wms-core/components/ExpressAppComponent";
@ -18,16 +17,17 @@ import CsrfProtectionComponent from "wms-core/components/CsrfProtectionComponent
import WebSocketServerComponent from "wms-core/components/WebSocketServerComponent"; import WebSocketServerComponent from "wms-core/components/WebSocketServerComponent";
import HomeController from "./controllers/HomeController"; import HomeController from "./controllers/HomeController";
import AutoUpdateComponent from "wms-core/components/AutoUpdateComponent"; import AutoUpdateComponent from "wms-core/components/AutoUpdateComponent";
import packageJson = require('../package.json');
export default class App extends Application { export default class App extends Application {
private readonly port: number; public constructor(
private readonly addr: string,
constructor(port: number) { private readonly port: number,
super(require('../package.json').version); ) {
this.port = port; super(packageJson.version);
} }
protected getMigrations(): Type<Migration>[] { protected getMigrations(): MigrationType<Migration>[] {
return [ return [
CreateMigrationsTable, CreateMigrationsTable,
CreateLogsTable, CreateLogsTable,
@ -44,7 +44,7 @@ export default class App extends Application {
const redisComponent = new RedisComponent(); const redisComponent = new RedisComponent();
const mysqlComponent = new MysqlComponent(); const mysqlComponent = new MysqlComponent();
const expressAppComponent = new ExpressAppComponent(this.port); const expressAppComponent = new ExpressAppComponent(this.addr, this.port);
this.use(expressAppComponent); this.use(expressAppComponent);
this.use(new NunjucksComponent()); this.use(new NunjucksComponent());
this.use(new LogRequestsComponent()); this.use(new LogRequestsComponent());
@ -79,9 +79,10 @@ export default class App extends Application {
} }
private registerWebSocketListeners() { private registerWebSocketListeners() {
// WebSocket listeners
} }
private registerControllers() { private registerControllers() {
this.use(new HomeController()); this.use(new HomeController());
} }
} }

View File

@ -2,24 +2,24 @@ import Controller from "wms-core/Controller";
import {Request, Response} from "express"; import {Request, Response} from "express";
export default class HomeController extends Controller { export default class HomeController extends Controller {
routes(): void { public routes(): void {
this.get('/', this.getHome, 'home'); this.get('/', this.getHome, 'home');
this.get('/about', this.getAbout, 'about'); this.get('/about', this.getAbout, 'about');
this.get('/back', this.goBack, 'about'); this.get('/back', this.goBack, 'about');
} }
private async getHome(req: Request, res: Response) { protected async getHome(req: Request, res: Response): Promise<void> {
res.render('home'); res.render('home');
} }
private async getAbout(req: Request, res: Response) { protected async getAbout(req: Request, res: Response): Promise<void> {
res.render('about'); res.render('about');
} }
/** /**
* This is to test and assert that wms-core extended types are available * This is to test and assert that wms-core extended types are available
*/ */
private async goBack(req: Request, res: Response) { protected async goBack(req: Request, res: Response): Promise<void> {
res.redirectBack(); res.redirectBack();
} }
} }

View File

@ -1,7 +1,9 @@
import {delimiter} from "path";
// Load config from specified path or default + wms-core/config (default defaults) // Load config from specified path or default + wms-core/config (default defaults)
process.env['NODE_CONFIG_DIR'] = process.env['NODE_CONFIG_DIR'] =
__dirname + '/../node_modules/wms-core/config/' __dirname + '/../node_modules/wms-core/config/'
+ require('path').delimiter + delimiter
+ (process.env['NODE_CONFIG_DIR'] || __dirname + '/../config/'); + (process.env['NODE_CONFIG_DIR'] || __dirname + '/../config/');
import Logger from "wms-core/Logger"; import Logger from "wms-core/Logger";
@ -11,8 +13,8 @@ import config from "config";
(async () => { (async () => {
Logger.debug('Config path:', process.env['NODE_CONFIG_DIR']); Logger.debug('Config path:', process.env['NODE_CONFIG_DIR']);
const app = new App(config.get<number>('port')); const app = new App(config.get<string>('listen_addr'), config.get<number>('port'));
await app.start(); await app.start();
})().catch(err => { })().catch(err => {
Logger.error(err); Logger.error(err);
}); });

View File

@ -2,4 +2,4 @@ describe('Write your tests', () => {
test('Remove this when you have some tests', () => { test('Remove this when you have some tests', () => {
expect(false).toBe(true); expect(false).toBe(true);
}); });
}); });

View File

@ -11,10 +11,11 @@
], ],
"typeRoots": [ "typeRoots": [
"./node_modules/@types" "./node_modules/@types"
] ],
"resolveJsonModule": true
}, },
"include": [ "include": [
"src/**/*", "src/**/*",
"node_modules/wms-core/types" "node_modules/wms-core/types"
] ]
} }

14
tsconfig.test.json Normal file
View File

@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"typeRoots": [
"node_modules/@types",
"src/types",
"test/types"
]
},
"include": [
"src/types/**/*",
"test/**/*"
]
}