From 79d704083aea9f78165867b5ecc01c077b12fc7f Mon Sep 17 00:00:00 2001 From: Alice Gaudon Date: Fri, 25 Sep 2020 23:42:15 +0200 Subject: [PATCH] Add many eslint rules and fix all linting issues --- .eslintrc.json | 95 +- jest.config.js | 7 +- src/Application.ts | 47 +- src/ApplicationComponent.ts | 20 +- src/CacheProvider.ts | 2 +- src/Controller.ts | 78 +- src/Extendable.ts | 2 +- src/FileUploadMiddleware.ts | 4 +- src/HttpError.ts | 40 +- src/Logger.ts | 102 +- src/Mail.ts | 28 +- src/Mails.ts | 4 +- src/Middleware.ts | 5 + src/Pagination.ts | 4 +- src/SecurityError.ts | 2 +- src/Throttler.ts | 39 +- src/Utils.ts | 22 +- src/WebSocketListener.ts | 8 +- src/auth/AuthComponent.ts | 6 +- src/auth/AuthController.ts | 8 +- src/auth/AuthGuard.ts | 32 +- src/auth/AuthProof.ts | 9 +- src/auth/MailController.ts | 6 +- .../magic_link/MagicLinkAuthController.ts | 58 +- src/auth/magic_link/MagicLinkController.ts | 37 +- .../magic_link/MagicLinkWebSocketListener.ts | 30 +- .../AddApprovedFieldToUsersTable.ts | 2 +- src/auth/migrations/CreateMagicLinksTable.ts | 2 +- src/auth/migrations/DropNameFromUsers.ts | 4 +- .../migrations/FixUserMainEmailRelation.ts | 8 +- src/auth/models/MagicLink.ts | 45 +- src/auth/models/User.ts | 5 +- src/auth/models/UserApprovedComponent.ts | 5 +- src/auth/models/UserEmail.ts | 2 +- src/components/AutoUpdateComponent.ts | 23 +- src/components/CsrfProtectionComponent.ts | 25 +- src/components/ExpressAppComponent.ts | 12 +- src/components/FormHelperComponent.ts | 12 +- src/components/LogRequestsComponent.ts | 56 +- src/components/MailComponent.ts | 4 +- src/components/MaintenanceComponent.ts | 4 +- src/components/MysqlComponent.ts | 4 +- src/components/NunjucksComponent.ts | 10 +- src/components/RedirectBackComponent.ts | 19 +- src/components/RedisComponent.ts | 19 +- .../ServeStaticDirectoryComponent.ts | 9 +- src/components/SessionComponent.ts | 35 +- src/components/WebSocketServerComponent.ts | 13 +- src/db/Migration.ts | 9 +- src/db/Model.ts | 114 +- src/db/ModelComponent.ts | 27 +- src/db/ModelFactory.ts | 50 +- src/db/ModelQuery.ts | 167 +- src/db/ModelRelation.ts | 80 +- src/db/MysqlConnectionManager.ts | 109 +- src/db/Validator.ts | 208 +- src/helpers/BackendController.ts | 17 +- src/migrations/CreateLogsTable.ts | 2 +- src/migrations/CreateMigrationsTable.ts | 5 +- src/models/Log.ts | 14 +- src/types/Express.d.ts | 14 +- test/CsrfProtectionComponent.test.ts | 8 +- test/Model.test.ts | 76 +- test/ModelQuery.test.ts | 8 +- test/_app.ts | 47 +- test/_mail_server.ts | 14 +- test/_migrations.ts | 2 +- test/types/maildev.d.ts | 216 ++ test/views/test/csrf.njk | 2 +- tsconfig.json | 2 - tsconfig.test.json | 14 + tsconfig.tsbuildinfo | 3132 ----------------- views/auth/auth.njk | 6 +- views/backend/accounts_approval.njk | 4 +- views/macros.njk | 4 +- 75 files changed, 1400 insertions(+), 3964 deletions(-) create mode 100644 test/types/maildev.d.ts create mode 100644 tsconfig.test.json delete mode 100644 tsconfig.tsbuildinfo diff --git a/.eslintrc.json b/.eslintrc.json index 1847c57..dc9bc7f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,15 +4,106 @@ "plugins": [ "@typescript-eslint" ], + "parserOptions": { + "project": [ + "./tsconfig.json", + "./tsconfig.test.json" + ] + }, "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended" ], "rules": { - "@typescript-eslint/no-inferrable-types": 0 + "indent": [ + "error", + 4, + { + "SwitchCase": 1 + } + ], + "no-trailing-spaces": "error", + "max-len": [ + "error", + { + "code": 120, + "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" + } + ] }, "ignorePatterns": [ "jest.config.js", - "dist/**/*" + "dist/**/*", + "config/**/*" + ], + "overrides": [ + { + "files": [ + "test/**/*" + ], + "rules": { + "max-len": [ + "error", + { + "code": 120, + "ignoreTemplateLiterals": true, + "ignoreRegExpLiterals": true, + "ignoreStrings": true + } + ] + } + } ] } \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index b61dffa..ccf1d63 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,4 +1,9 @@ module.exports = { + globals: { + 'ts-jest': { + tsconfig: 'tsconfig.test.json', + } + }, transform: { "^.+\\.ts$": "ts-jest" }, @@ -10,5 +15,5 @@ module.exports = { testMatch: [ '**/test/**/*.test.ts' ], - testEnvironment: 'node' + testEnvironment: 'node', }; \ No newline at end of file diff --git a/src/Application.ts b/src/Application.ts index d823e8c..6385db1 100644 --- a/src/Application.ts +++ b/src/Application.ts @@ -6,7 +6,7 @@ import WebSocketListener from "./WebSocketListener"; import ApplicationComponent from "./ApplicationComponent"; import Controller from "./Controller"; import MysqlConnectionManager from "./db/MysqlConnectionManager"; -import Migration from "./db/Migration"; +import Migration, {MigrationType} from "./db/Migration"; import {Type} from "./Utils"; import LogRequestsComponent from "./components/LogRequestsComponent"; import {ValidationBag} from "./db/Validator"; @@ -19,7 +19,7 @@ import RedisComponent from "./components/RedisComponent"; import Extendable from "./Extendable"; import TemplateError = lib.TemplateError; -export default abstract class Application implements Extendable { +export default abstract class Application implements Extendable> { private readonly version: string; private readonly ignoreCommandLine: boolean; private readonly controllers: Controller[] = []; @@ -34,11 +34,11 @@ export default abstract class Application implements Extendable[]; + protected abstract getMigrations(): MigrationType[]; protected abstract async init(): Promise; - protected use(thing: Controller | WebSocketListener | ApplicationComponent) { + protected use(thing: Controller | WebSocketListener | ApplicationComponent): void { if (thing instanceof Controller) { thing.setApp(this); this.controllers.push(thing); @@ -88,7 +88,7 @@ export default abstract class Application implements Extendable { + app.use((err: unknown, req: Request, res: Response, next: NextFunction) => { if (res.headersSent) return next(err); if (err instanceof ValidationBag) { @@ -104,17 +104,18 @@ export default abstract class Application implements Extendable { res.status(401); - res.send('Error: ' + err.getMessages()) + res.send('Error: ' + err.getMessages()); }, html: () => { - req.flash('validation', err.getMessages()); + req.flash('validation', err.getMessages().toString()); res.redirectBack(); }, }); return; } - let errorID: string = LogRequestsComponent.logRequest(req, res, err, '500 Internal Error', err instanceof BadRequestError || err instanceof ServiceUnavailableHttpError); + const errorId: string = LogRequestsComponent.logRequest(req, res, err, '500 Internal Error', + err instanceof BadRequestError || err instanceof ServiceUnavailableHttpError); let httpError: HttpError; @@ -123,7 +124,7 @@ export default abstract class Application implements Extendable { @@ -142,12 +143,12 @@ export default abstract class Application implements Extendable { - res.type('txt').send(`${httpError.errorCode} - ${httpError.message}\n\n${httpError.instructions}\n\nError ID: ${errorID}`); - } + res.type('txt').send(`${httpError.errorCode} - ${httpError.message}\n\n${httpError.instructions}\n\nError ID: ${errorId}`); + }, }); }); @@ -262,18 +263,20 @@ export default abstract class Application implements Extendable(type: Type): C { - const component = this.components.find(component => component.constructor === type); - if (!component) throw new Error(`This app doesn't have a ${type.name} component.`); - return component as C; + public as>(type: Type): C { + const module = this.components.find(component => component.constructor === type) || + Object.values(this.webSocketListeners).find(listener => listener.constructor === type); + if (!module) throw new Error(`This app doesn't have a ${type.name} component.`); + return module as C; } - public asOptional(type: Type): C | null { - const component = this.components.find(component => component.constructor === type); - return component ? component as C : null; + public asOptional>(type: Type): C | null { + const module = this.components.find(component => component.constructor === type) || + Object.values(this.webSocketListeners).find(listener => listener.constructor === type); + return module ? module as C : null; } } diff --git a/src/ApplicationComponent.ts b/src/ApplicationComponent.ts index dd46b47..61f036f 100644 --- a/src/ApplicationComponent.ts +++ b/src/ApplicationComponent.ts @@ -1,10 +1,10 @@ import {Express, Router} from "express"; import Logger from "./Logger"; -import {sleep, Type} from "./Utils"; +import {sleep} from "./Utils"; import Application from "./Application"; import config from "config"; import SecurityError from "./SecurityError"; -import Middleware from "./Middleware"; +import Middleware, {MiddlewareType} from "./Middleware"; export default abstract class ApplicationComponent { private currentRouter?: Router; @@ -28,16 +28,16 @@ export default abstract class ApplicationComponent { err = null; } catch (e) { err = e; - Logger.error(err, `${name} failed to prepare; retrying in 5s...`) + Logger.error(err, `${name} failed to prepare; retrying in 5s...`); await sleep(5000); } } while (err); Logger.info(`${name} ready!`); } - protected async close(thingName: string, thing: any, fn: Function): Promise { + protected async close(thingName: string, fn: (callback: (err?: Error | null) => void) => void): Promise { try { - await new Promise((resolve, reject) => fn.call(thing, (err: any) => { + await new Promise((resolve, reject) => fn((err?: Error | null) => { if (err) reject(err); else resolve(); })); @@ -48,13 +48,13 @@ export default abstract class ApplicationComponent { } } - protected checkSecurityConfigField(field: string) { + protected checkSecurityConfigField(field: string): void { if (!config.has(field) || config.get(field) === 'default') { throw new SecurityError(`${field} field not configured.`); } } - protected use(middleware: Type): void { + protected use(middleware: MiddlewareType): void { if (!this.currentRouter) throw new Error('Cannot call this method outside init() and handle().'); const instance = new middleware(this.getApp()); @@ -67,10 +67,6 @@ export default abstract class ApplicationComponent { }); } - protected getCurrentRouter(): Router | null { - return this.currentRouter || null; - } - public setCurrentRouter(router: Router | null): void { this.currentRouter = router || undefined; } @@ -80,7 +76,7 @@ export default abstract class ApplicationComponent { return this.app; } - public setApp(app: Application) { + public setApp(app: Application): void { this.app = app; } } diff --git a/src/CacheProvider.ts b/src/CacheProvider.ts index fad5b74..5331868 100644 --- a/src/CacheProvider.ts +++ b/src/CacheProvider.ts @@ -11,4 +11,4 @@ export default interface CacheProvider { * @param ttl in ms */ remember(key: string, value: string, ttl: number): Promise; -} \ No newline at end of file +} diff --git a/src/Controller.ts b/src/Controller.ts index 5e33e13..686fcfb 100644 --- a/src/Controller.ts +++ b/src/Controller.ts @@ -6,14 +6,18 @@ import Validator, {ValidationBag} from "./db/Validator"; import FileUploadMiddleware from "./FileUploadMiddleware"; import * as querystring from "querystring"; import {ParsedUrlQueryInput} from "querystring"; -import Middleware from "./Middleware"; -import {Type} from "./Utils"; +import Middleware, {MiddlewareType} from "./Middleware"; import Application from "./Application"; export default abstract class Controller { - private static readonly routes: { [p: string]: string } = {}; + private static readonly routes: { [p: string]: string | undefined } = {}; - public static route(route: string, params: RouteParams = [], query: ParsedUrlQueryInput = {}, absolute: boolean = false): string { + public static route( + route: string, + params: RouteParams = [], + query: ParsedUrlQueryInput = {}, + absolute: boolean = false, + ): string { let path = this.routes[route]; if (path === undefined) throw new Error(`Unknown route for name ${route}.`); @@ -29,10 +33,8 @@ export default abstract class Controller { } path = path.replace(/\/+/g, '/'); } else { - for (const key in params) { - if (params.hasOwnProperty(key)) { - path = path.replace(new RegExp(`:${key}\\??`), params[key]); - } + for (const key of Object.keys(params)) { + path = path.replace(new RegExp(`:${key}\\??`), params[key]); } } @@ -64,10 +66,7 @@ export default abstract class Controller { public abstract routes(): void; - public setupRoutes(): { - mainRouter: Router, - fileUploadFormRouter: Router - } { + public setupRoutes(): { mainRouter: Router, fileUploadFormRouter: Router } { this.routes(); return { mainRouter: this.router, @@ -75,23 +74,43 @@ export default abstract class Controller { }; } - protected use(handler: RequestHandler) { + protected use(handler: RequestHandler): void { this.router.use(handler); } - protected get(path: PathParams, handler: RequestHandler, routeName?: string, ...middlewares: (Type)[]) { + protected get( + path: PathParams, + handler: RequestHandler, + routeName?: string, + ...middlewares: (MiddlewareType)[] + ): void { this.handle('get', path, handler, routeName, ...middlewares); } - protected post(path: PathParams, handler: RequestHandler, routeName?: string, ...middlewares: (Type)[]) { + protected post( + path: PathParams, + handler: RequestHandler, + routeName?: string, + ...middlewares: (MiddlewareType)[] + ): void { this.handle('post', path, handler, routeName, ...middlewares); } - protected put(path: PathParams, handler: RequestHandler, routeName?: string, ...middlewares: (Type)[]) { + protected put( + path: PathParams, + handler: RequestHandler, + routeName?: string, + ...middlewares: (MiddlewareType)[] + ): void { this.handle('put', path, handler, routeName, ...middlewares); } - protected delete(path: PathParams, handler: RequestHandler, routeName?: string, ...middlewares: (Type)[]) { + protected delete( + path: PathParams, + handler: RequestHandler, + routeName?: string, + ...middlewares: (MiddlewareType)[] + ): void { this.handle('delete', path, handler, routeName, ...middlewares); } @@ -100,7 +119,7 @@ export default abstract class Controller { path: PathParams, handler: RequestHandler, routeName?: string, - ...middlewares: (Type)[] + ...middlewares: (MiddlewareType)[] ): void { this.registerRoutes(path, handler, routeName); for (const middleware of middlewares) { @@ -152,18 +171,19 @@ export default abstract class Controller { } } - protected async validate(validationMap: { [p: string]: Validator }, body: any): Promise { + protected async validate( + validationMap: { [p: string]: Validator }, + body: { [p: string]: unknown }, + ): Promise { const bag = new ValidationBag(); - for (const p in validationMap) { - if (validationMap.hasOwnProperty(p)) { - try { - await validationMap[p].execute(p, body[p], false); - } catch (e) { - if (e instanceof ValidationBag) { - bag.addBag(e); - } else throw e; - } + for (const p of Object.keys(validationMap)) { + try { + await validationMap[p].execute(p, body[p], false); + } catch (e) { + if (e instanceof ValidationBag) { + bag.addBag(e); + } else throw e; } } @@ -175,7 +195,7 @@ export default abstract class Controller { return this.app; } - public setApp(app: Application) { + public setApp(app: Application): void { this.app = app; } } diff --git a/src/Extendable.ts b/src/Extendable.ts index 25bce64..2ebfa98 100644 --- a/src/Extendable.ts +++ b/src/Extendable.ts @@ -4,4 +4,4 @@ export default interface Extendable { as(type: Type): C; asOptional(type: Type): C | null; -} \ No newline at end of file +} diff --git a/src/FileUploadMiddleware.ts b/src/FileUploadMiddleware.ts index d474b1c..ba4946e 100644 --- a/src/FileUploadMiddleware.ts +++ b/src/FileUploadMiddleware.ts @@ -11,7 +11,7 @@ export default abstract class FileUploadMiddleware extends Middleware { public async handle(req: Request, res: Response, next: NextFunction): Promise { const form = this.makeForm(); try { - await new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { form.parse(req, (err, fields, files) => { if (err) { reject(err); @@ -32,4 +32,4 @@ export default abstract class FileUploadMiddleware extends Middleware { } next(); } -} \ No newline at end of file +} diff --git a/src/HttpError.ts b/src/HttpError.ts index e76ace4..4de4d95 100644 --- a/src/HttpError.ts +++ b/src/HttpError.ts @@ -8,7 +8,7 @@ export abstract class HttpError extends WrappingError { this.instructions = instructions; } - get name(): string { + public get name(): string { return this.constructor.name; } @@ -18,87 +18,83 @@ export abstract class HttpError extends WrappingError { export class BadRequestError extends HttpError { public readonly url: string; - constructor(message: string, instructions: string, url: string, cause?: Error) { + public constructor(message: string, instructions: string, url: string, cause?: Error) { super(message, instructions, cause); this.url = url; } - get errorCode(): number { + public get errorCode(): number { return 400; } } export class UnauthorizedHttpError extends BadRequestError { - constructor(message: string, url: string, cause?: Error) { + public constructor(message: string, url: string, cause?: Error) { super(message, '', url, cause); } - get errorCode(): number { + public get errorCode(): number { return 401; } } export class ForbiddenHttpError extends BadRequestError { - constructor(thing: string, url: string, cause?: Error) { + public constructor(thing: string, url: string, cause?: Error) { super( `You don't have access to this ${thing}.`, `${url} doesn't belong to *you*.`, url, - cause + cause, ); } - get errorCode(): number { + public get errorCode(): number { return 403; } } export class NotFoundHttpError extends BadRequestError { - constructor(thing: string, url: string, cause?: Error) { + public constructor(thing: string, url: string, cause?: Error) { super( `${thing.charAt(0).toUpperCase()}${thing.substr(1)} not found.`, `${url} doesn't exist or was deleted.`, url, - cause + cause, ); } - get errorCode(): number { + public get errorCode(): number { return 404; } } export class TooManyRequestsHttpError extends BadRequestError { - constructor(retryIn: number, cause?: Error) { + public constructor(retryIn: number, cause?: Error) { super( `You're making too many requests!`, `We need some rest. Please retry in ${Math.floor(retryIn / 1000)} seconds.`, '', - cause + cause, ); } - get errorCode(): number { + public get errorCode(): number { return 429; } } export class ServerError extends HttpError { - constructor(message: string, cause?: Error) { + public constructor(message: string, cause?: Error) { super(message, `Maybe you should contact us; see instructions below.`, cause); } - get errorCode(): number { + public get errorCode(): number { return 500; } } export class ServiceUnavailableHttpError extends ServerError { - constructor(message: string, cause?: Error) { - super(message, cause); - } - - get errorCode(): number { + public get errorCode(): number { return 503; } -} \ No newline at end of file +} diff --git a/src/Logger.ts b/src/Logger.ts index 022cae0..e7897ce 100644 --- a/src/Logger.ts +++ b/src/Logger.ts @@ -1,17 +1,31 @@ import config from "config"; import {v4 as uuid} from "uuid"; import Log from "./models/Log"; -import {bufferToUUID} from "./Utils"; +import {bufferToUuid} from "./Utils"; +import ModelFactory from "./db/ModelFactory"; +export enum LogLevel { + ERROR, + WARN, + INFO, + DEBUG, + DEV, +} + +export type LogLevelKeys = keyof typeof LogLevel; + +/** + * TODO: make logger not static + */ export default class Logger { - private static logLevel: LogLevelKeys = config.get('log.level'); - private static dbLogLevel: LogLevelKeys = config.get('log.db_level'); + private static logLevel: LogLevel = LogLevel[config.get('log.level')]; + private static dbLogLevel: LogLevel = LogLevel[config.get('log.db_level')]; private static verboseMode: boolean = config.get('log.verbose'); - public static verbose() { + public static verbose(): void { this.verboseMode = true; - this.logLevel = LogLevel[LogLevel[this.logLevel] + 1] || this.logLevel; - this.dbLogLevel = LogLevel[LogLevel[this.dbLogLevel] + 1] || this.dbLogLevel; + if (LogLevel[this.logLevel + 1]) this.logLevel++; + if (LogLevel[this.dbLogLevel + 1]) this.dbLogLevel++; Logger.info('Verbose mode'); } @@ -19,46 +33,45 @@ export default class Logger { return this.verboseMode; } - public static silentError(error: Error, ...message: any[]): string { - return this.log('ERROR', message, error, true) || ''; + public static silentError(error: Error, ...message: unknown[]): string { + return this.log(LogLevel.ERROR, message, error, true) || ''; } - public static error(error: Error, ...message: any[]): string { - return this.log('ERROR', message, error) || ''; + public static error(error: Error, ...message: unknown[]): string { + return this.log(LogLevel.ERROR, message, error) || ''; } - public static warn(...message: any[]) { - this.log('WARN', message); + public static warn(...message: unknown[]): void { + this.log(LogLevel.WARN, message); } - public static info(...message: any[]) { - this.log('INFO', message); + public static info(...message: unknown[]): void { + this.log(LogLevel.INFO, message); } - public static debug(...message: any[]) { - this.log('DEBUG', message); + public static debug(...message: unknown[]): void { + this.log(LogLevel.DEBUG, message); } - public static dev(...message: any[]) { - this.log('DEV', message); + public static dev(...message: unknown[]): void { + this.log(LogLevel.DEV, message); } - private static log(level: LogLevelKeys, message: any[], error?: Error, silent: boolean = false): string | null { - const levelIndex = LogLevel[level]; - if (levelIndex <= LogLevel[this.logLevel]) { + private static log(level: LogLevel, message: unknown[], error?: Error, silent: boolean = false): string | null { + if (level <= this.logLevel) { if (error) { - if (levelIndex > LogLevel.ERROR) this.warn(`Wrong log level ${level} with attached error.`); + if (level > LogLevel.ERROR) this.warn(`Wrong log level ${level} with attached error.`); } else { - if (levelIndex <= LogLevel.ERROR) this.warn(`No error attached with log level ${level}.`); + if (level <= LogLevel.ERROR) this.warn(`No error attached with log level ${level}.`); } const computedMsg = message.map(v => { if (typeof v === 'string') { return v; } else { - return JSON.stringify(v, (key: string, value: any) => { - if (value instanceof Object) { - if (value.type === 'Buffer') { + return JSON.stringify(v, (key: string, value: string | unknown[] | Record) => { + if (!Array.isArray(value) && value instanceof Object) { + if (value.type === 'Buffer' && typeof value.data === 'string') { return `Buffer<${Buffer.from(value.data).toString('hex')}>`; } else if (value !== v) { return `[object Object]`; @@ -72,65 +85,56 @@ export default class Logger { } }).join(' '); - const shouldSaveToDB = levelIndex <= LogLevel[this.dbLogLevel]; + const shouldSaveToDB = level <= this.dbLogLevel; let output = `[${level}] `; const pad = output.length; - const logID = Buffer.alloc(16); - uuid({}, logID); - let strLogID = bufferToUUID(logID); - if (shouldSaveToDB) output += `${strLogID} - `; + const logId = Buffer.alloc(16); + uuid({}, logId); + const strLogId = bufferToUuid(logId); + if (shouldSaveToDB) output += `${strLogId} - `; output += computedMsg.replace(/\n/g, '\n' + ' '.repeat(pad)); switch (level) { - case "ERROR": + case LogLevel.ERROR: if (silent || !error) { console.error(output); } else { console.error(output, error); } break; - case "WARN": + case LogLevel.WARN: console.warn(output); break; - case "INFO": + case LogLevel.INFO: console.info(output); break; - case "DEBUG": - case "DEV": + case LogLevel.DEBUG: + case LogLevel.DEV: console.debug(output); break; } - if (shouldSaveToDB) { + if (shouldSaveToDB && ModelFactory.has(Log)) { const log = Log.create({}); log.setLevel(level); log.message = computedMsg; log.setError(error); - log.setLogID(logID); + log.setLogId(logId); log.save().catch(err => { if (!silent && err.message.indexOf('ECONNREFUSED') < 0) { console.error({save_err: err, error}); } }); } - return strLogID; + return strLogId; } return null; } private constructor() { + // disable constructor } } - -export enum LogLevel { - ERROR, - WARN, - INFO, - DEBUG, - DEV, -} - -export type LogLevelKeys = keyof typeof LogLevel; diff --git a/src/Mail.ts b/src/Mail.ts index 21b30da..b9f8aee 100644 --- a/src/Mail.ts +++ b/src/Mail.ts @@ -7,9 +7,10 @@ import {WrappingError} from "./Utils"; import mjml2html from "mjml"; import Logger from "./Logger"; import Controller from "./Controller"; +import {ParsedUrlQueryInput} from "querystring"; export default class Mail { - private static transporter: Transporter; + private static transporter?: Transporter; private static getTransporter(): Transporter { if (!this.transporter) throw new MailError('Mail system was not prepared.'); @@ -26,8 +27,8 @@ export default class Mail { pass: config.get('mail.password'), }, tls: { - rejectUnauthorized: !config.get('mail.allow_invalid_tls') - } + rejectUnauthorized: !config.get('mail.allow_invalid_tls'), + }, }); try { @@ -40,11 +41,11 @@ export default class Mail { Logger.info(`Mail ready to be distributed via ${config.get('mail.host')}:${config.get('mail.port')}`); } - public static end() { + public static end(): void { if (this.transporter) this.transporter.close(); } - public static parse(template: string, data: any, textOnly: boolean): string { + public static parse(template: string, data: { [p: string]: unknown }, textOnly: boolean): string { data.text = textOnly; const nunjucksResult = nunjucks.render(template, data); if (textOnly) return nunjucksResult; @@ -60,9 +61,9 @@ export default class Mail { private readonly template: MailTemplate; private readonly options: Options = {}; - private readonly data: { [p: string]: any }; + private readonly data: ParsedUrlQueryInput; - constructor(template: MailTemplate, data: { [p: string]: any } = {}) { + public constructor(template: MailTemplate, data: ParsedUrlQueryInput = {}) { this.template = template; this.data = data; this.options.subject = this.template.getSubject(data); @@ -97,7 +98,8 @@ export default class Mail { // Set data this.data.mail_subject = this.options.subject; this.data.mail_to = this.options.to; - this.data.mail_link = config.get('base_url') + Controller.route('mail', [this.template.template], this.data); + this.data.mail_link = config.get('base_url') + + Controller.route('mail', [this.template.template], this.data); this.data.app = config.get('app'); // Log @@ -117,9 +119,9 @@ export default class Mail { export class MailTemplate { private readonly _template: string; - private readonly subject: (data: any) => string; + private readonly subject: (data: { [p: string]: unknown }) => string; - constructor(template: string, subject: (data: any) => string) { + public constructor(template: string, subject: (data: { [p: string]: unknown }) => string) { this._template = template; this.subject = subject; } @@ -128,13 +130,13 @@ export class MailTemplate { return this._template; } - public getSubject(data: any): string { + public getSubject(data: { [p: string]: unknown }): string { return `${config.get('app.name')} - ${this.subject(data)}`; } } class MailError extends WrappingError { - constructor(message: string = 'An error occurred while sending mail.', cause?: Error) { + public constructor(message: string = 'An error occurred while sending mail.', cause?: Error) { super(message, cause); } -} \ No newline at end of file +} diff --git a/src/Mails.ts b/src/Mails.ts index 9a4635c..6dfb707 100644 --- a/src/Mails.ts +++ b/src/Mails.ts @@ -3,12 +3,12 @@ import {MailTemplate} from "./Mail"; export const MAGIC_LINK_MAIL = new MailTemplate( 'magic_link', - data => data.type === 'register' ? 'Registration' : 'Login magic link' + data => data.type === 'register' ? 'Registration' : 'Login magic link', ); export const ACCOUNT_REVIEW_NOTICE_MAIL_TEMPLATE: MailTemplate = new MailTemplate( 'account_review_notice', - data => `Your account was ${data.approved ? 'approved' : 'rejected'}.` + data => `Your account was ${data.approved ? 'approved' : 'rejected'}.`, ); export const PENDING_ACCOUNT_REVIEW_MAIL_TEMPLATE: MailTemplate = new MailTemplate( diff --git a/src/Middleware.ts b/src/Middleware.ts index 344dbac..e3bc0be 100644 --- a/src/Middleware.ts +++ b/src/Middleware.ts @@ -1,6 +1,7 @@ import {RequestHandler} from "express"; import {NextFunction, Request, Response} from "express-serve-static-core"; import Application from "./Application"; +import {Type} from "./Utils"; export default abstract class Middleware { public constructor( @@ -26,3 +27,7 @@ export default abstract class Middleware { }; } } + +export interface MiddlewareType extends Type { + new(app: Application): M; +} diff --git a/src/Pagination.ts b/src/Pagination.ts index 1cb0539..50055d9 100644 --- a/src/Pagination.ts +++ b/src/Pagination.ts @@ -6,7 +6,7 @@ export default class Pagination { public readonly perPage: number; public readonly totalCount: number; - constructor(models: T[], page: number, perPage: number, totalCount: number) { + public constructor(models: T[], page: number, perPage: number, totalCount: number) { this.models = models; this.page = page; this.perPage = perPage; @@ -21,4 +21,4 @@ export default class Pagination { return this.models.length >= this.perPage && this.page * this.perPage < this.totalCount; } -} \ No newline at end of file +} diff --git a/src/SecurityError.ts b/src/SecurityError.ts index 0122dcc..832c734 100644 --- a/src/SecurityError.ts +++ b/src/SecurityError.ts @@ -5,4 +5,4 @@ export default class SecurityError implements Error { public constructor(message: string) { this.message = message; } -} \ No newline at end of file +} diff --git a/src/Throttler.ts b/src/Throttler.ts index 5235ace..a1c592a 100644 --- a/src/Throttler.ts +++ b/src/Throttler.ts @@ -1,7 +1,7 @@ import {TooManyRequestsHttpError} from "./HttpError"; export default class Throttler { - private static readonly throttles: { [throttleName: string]: Throttle } = {}; + private static readonly throttles: Record = {}; /** * Throttle function; will throw a TooManyRequestsHttpError when the threshold is reached. @@ -16,13 +16,21 @@ export default class Throttler { * @param holdPeriod time in ms after each call before the threshold begins to decrease. * @param jailPeriod time in ms for which the throttle will throw when it is triggered. */ - public static throttle(action: string, max: number, resetPeriod: number, id: string, holdPeriod: number = 100, jailPeriod: number = 30 * 1000) { + public static throttle( + action: string, + max: number, + resetPeriod: number, + id: string, + holdPeriod: number = 100, + jailPeriod: number = 30 * 1000, + ): void { let throttle = this.throttles[action]; if (!throttle) throttle = this.throttles[action] = new Throttle(max, resetPeriod, holdPeriod, jailPeriod); throttle.trigger(id); } private constructor() { + // Disable constructor } } @@ -31,15 +39,13 @@ class Throttle { private readonly resetPeriod: number; private readonly holdPeriod: number; private readonly jailPeriod: number; - private readonly triggers: { - [id: string]: { - count: number, - lastTrigger?: number, - jailed?: number; - } - } = {}; + private readonly triggers: Record = {}; - constructor(max: number, resetPeriod: number, holdPeriod: number, jailPeriod: number) { + public constructor(max: number, resetPeriod: number, holdPeriod: number, jailPeriod: number) { this.max = max; this.resetPeriod = resetPeriod; this.holdPeriod = holdPeriod; @@ -51,12 +57,10 @@ class Throttle { let trigger = this.triggers[id]; if (!trigger) trigger = this.triggers[id] = {count: 0}; - let currentDate = new Date().getTime(); + const currentDate = new Date().getTime(); - if (trigger.jailed && currentDate - trigger.jailed < this.jailPeriod) { - this.throw((trigger.jailed + this.jailPeriod) - currentDate); - return; - } + if (trigger.jailed && currentDate - trigger.jailed < this.jailPeriod) + return this.throw(trigger.jailed + this.jailPeriod - currentDate); if (trigger.lastTrigger) { let timeDiff = currentDate - trigger.lastTrigger; @@ -71,12 +75,11 @@ class Throttle { if (trigger.count > this.max) { trigger.jailed = currentDate; - this.throw((trigger.jailed + this.jailPeriod) - currentDate); - return; + return this.throw(trigger.jailed + this.jailPeriod - currentDate); } } protected throw(unjailedIn: number) { throw new TooManyRequestsHttpError(unjailedIn); } -} \ No newline at end of file +} diff --git a/src/Utils.ts b/src/Utils.ts index 9316a5d..ad841c0 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -18,7 +18,7 @@ export abstract class WrappingError extends Error { } } - get name(): string { + public get name(): string { return this.constructor.name; } } @@ -28,15 +28,15 @@ export function cryptoRandomDictionary(size: number, dictionary: string): string const output = new Array(size); for (let i = 0; i < size; i++) { - output[i] = dictionary[Math.floor((randomBytes[i] / 255) * dictionary.length)]; + output[i] = dictionary[Math.floor(randomBytes[i] / 255 * dictionary.length)]; } return output.join(''); } -export type Type = { new(...args: any[]): T }; +export type Type = { new(...args: never[]): T }; -export function bufferToUUID(buffer: Buffer): string { +export function bufferToUuid(buffer: Buffer): string { const chars = buffer.toString('hex'); let out = ''; let i = 0; @@ -48,12 +48,12 @@ export function bufferToUUID(buffer: Buffer): string { return out; } -export function getMethods(obj: T): (string)[] { - let properties = new Set() - let currentObj = obj +export function getMethods(obj: T): string[] { + const properties = new Set(); + let currentObj: T | unknown = obj; do { - Object.getOwnPropertyNames(currentObj).map(item => properties.add(item)) - } while ((currentObj = Object.getPrototypeOf(currentObj))) - // @ts-ignore - return [...properties.keys()].filter(item => typeof obj[item] === 'function') + Object.getOwnPropertyNames(currentObj).map(item => properties.add(item)); + currentObj = Object.getPrototypeOf(currentObj); + } while (currentObj); + return [...properties.keys()].filter(item => typeof obj[item] === 'function'); } diff --git a/src/WebSocketListener.ts b/src/WebSocketListener.ts index 2af4cd0..a5c75e8 100644 --- a/src/WebSocketListener.ts +++ b/src/WebSocketListener.ts @@ -15,5 +15,9 @@ export default abstract class WebSocketListener { public abstract path(): string; - public abstract async handle(socket: WebSocket, request: IncomingMessage, session: Express.Session | null): Promise; -} \ No newline at end of file + public abstract async handle( + socket: WebSocket, + request: IncomingMessage, + session: Express.Session | null, + ): Promise; +} diff --git a/src/auth/AuthComponent.ts b/src/auth/AuthComponent.ts index 50f63c9..44509bc 100644 --- a/src/auth/AuthComponent.ts +++ b/src/auth/AuthComponent.ts @@ -31,7 +31,7 @@ export class AuthMiddleware extends Middleware { protected async handle(req: Request, res: Response, next: NextFunction): Promise { this.authGuard = this.app.as(AuthComponent).getAuthGuard(); - const proof = await this.authGuard.isAuthenticated(req.session!); + const proof = await this.authGuard.isAuthenticated(req.getSession()); if (proof) { this.user = await proof.getResource(); res.locals.user = this.user; @@ -76,7 +76,7 @@ export class RequireAuthMiddleware extends Middleware { } // Via session - if (!await authGuard.isAuthenticated(req.session!)) { + if (!await authGuard.isAuthenticated(req.getSession())) { req.flash('error', `You must be logged in to access ${req.url}.`); res.redirect(Controller.route('auth', undefined, { redirect_uri: req.url, @@ -90,7 +90,7 @@ export class RequireAuthMiddleware extends Middleware { export class RequireGuestMiddleware extends Middleware { protected async handle(req: Request, res: Response, next: NextFunction): Promise { - if (await req.as(AuthMiddleware).getAuthGuard().isAuthenticated(req.session!)) { + if (await req.as(AuthMiddleware).getAuthGuard().isAuthenticated(req.getSession())) { res.redirectBack(); return; } diff --git a/src/auth/AuthController.ts b/src/auth/AuthController.ts index 89db190..32fc242 100644 --- a/src/auth/AuthController.ts +++ b/src/auth/AuthController.ts @@ -7,14 +7,14 @@ export default abstract class AuthController extends Controller { return '/auth'; } - public routes() { + public routes(): void { this.get('/', this.getAuth, 'auth', RequireGuestMiddleware); this.post('/', this.postAuth, 'auth', RequireGuestMiddleware); this.get('/check', this.getCheckAuth, 'check_auth'); this.post('/logout', this.postLogout, 'logout', RequireAuthMiddleware); } - protected async getAuth(req: Request, res: Response, next: NextFunction): Promise { + protected async getAuth(req: Request, res: Response, _next: NextFunction): Promise { const registerEmail = req.flash('register_confirm_email'); res.render('auth/auth', { register_confirm_email: registerEmail.length > 0 ? registerEmail[0] : null, @@ -25,11 +25,11 @@ export default abstract class AuthController extends Controller { protected abstract async getCheckAuth(req: Request, res: Response, next: NextFunction): Promise; - protected async postLogout(req: Request, res: Response, next: NextFunction): Promise { + protected async postLogout(req: Request, res: Response, _next: NextFunction): Promise { const proof = await req.as(AuthMiddleware).getAuthGuard().getProof(req); await proof?.revoke(); req.flash('success', 'Successfully logged out.'); res.redirect(req.query.redirect_uri?.toString() || '/'); } -} \ No newline at end of file +} diff --git a/src/auth/AuthGuard.ts b/src/auth/AuthGuard.ts index 6f04542..22623ff 100644 --- a/src/auth/AuthGuard.ts +++ b/src/auth/AuthGuard.ts @@ -11,7 +11,7 @@ import config from "config"; export default abstract class AuthGuard

> { protected abstract async getProofForSession(session: Express.Session): Promise

; - protected async getProofForRequest(req: Request): Promise

{ + protected async getProofForRequest(_req: Request): Promise

{ return null; } @@ -52,7 +52,7 @@ export default abstract class AuthGuard

> { session: Express.Session, proof: P, onLogin?: (user: User) => Promise, - onRegister?: (connection: Connection, user: User) => Promise + onRegister?: (connection: Connection, user: User) => Promise, ): Promise { if (!await proof.isValid()) throw new InvalidAuthProofError(); if (!await proof.isAuthorized()) throw new UnauthorizedAuthProofError(); @@ -63,27 +63,24 @@ export default abstract class AuthGuard

> { if (!user) { const callbacks: RegisterCallback[] = []; - await MysqlConnectionManager.wrapTransaction(async connection => { - user = User.create({}); + user = await MysqlConnectionManager.wrapTransaction(async connection => { + const user = User.create({}); await user.save(connection, c => callbacks.push(c)); if (onRegister) { (await onRegister(connection, user)).forEach(c => callbacks.push(c)); } + return user; }); for (const callback of callbacks) { await callback(); } - if (user) { - if (!user!.isApproved()) { - await new Mail(PENDING_ACCOUNT_REVIEW_MAIL_TEMPLATE, { - username: user!.name, - link: config.get('base_url') + Controller.route('accounts-approval'), - }).send(config.get('app.contact_email')); - } - } else { - throw new Error('Unable to register user.'); + if (!user.isApproved()) { + await new Mail(PENDING_ACCOUNT_REVIEW_MAIL_TEMPLATE, { + username: (await user.mainEmail.get())?.getOrFail('email'), + link: config.get('base_url') + Controller.route('accounts-approval'), + }).send(config.get('app.contact_email')); } } @@ -102,28 +99,25 @@ export default abstract class AuthGuard

> { } export class AuthError extends Error { - constructor(message: string) { - super(message); - } } export class AuthProofError extends AuthError { } export class InvalidAuthProofError extends AuthProofError { - constructor() { + public constructor() { super('Invalid auth proof.'); } } export class UnauthorizedAuthProofError extends AuthProofError { - constructor() { + public constructor() { super('Unauthorized auth proof.'); } } export class PendingApprovalAuthError extends AuthError { - constructor() { + public constructor() { super(`User is not approved.`); } } diff --git a/src/auth/AuthProof.ts b/src/auth/AuthProof.ts index 785745b..960d119 100644 --- a/src/auth/AuthProof.ts +++ b/src/auth/AuthProof.ts @@ -2,8 +2,8 @@ * This class is most commonly used for authentication. It can be more generically used to represent a verification * state of whether a given resource is owned by a session. * - * Any auth system should consider this auth proof valid if and only if both {@code isValid()} and {@code isAuthorized()} - * both return {@code true}. + * Any auth system should consider this auth proof valid if and only if both {@code isValid()} and + * {@code isAuthorized()} both return {@code true}. * * @type The resource type this AuthProof authorizes. */ @@ -34,7 +34,8 @@ export default interface AuthProof { * - {@code isAuthorized} returns {@code false} * - There is no way to re-authorize this proof (i.e. {@code isAuthorized} can never return {@code true} again) * - * Additionally, this method should delete any stored data that could lead to restoration of this AuthProof instance. + * Additionally, this method should delete any stored data that could lead to restoration of this AuthProof + * instance. */ revoke(): Promise; -} \ No newline at end of file +} diff --git a/src/auth/MailController.ts b/src/auth/MailController.ts index a76e521..517bddb 100644 --- a/src/auth/MailController.ts +++ b/src/auth/MailController.ts @@ -3,12 +3,12 @@ import Controller from "../Controller"; import Mail from "../Mail"; export default class MailController extends Controller { - routes(): void { + public routes(): void { this.get("/mail/:template", this.getMail, 'mail'); } - private async getMail(request: Request, response: Response) { + protected async getMail(request: Request, response: Response): Promise { const template = request.params['template']; response.send(Mail.parse(`mails/${template}.mjml.njk`, request.query, false)); } -} \ No newline at end of file +} diff --git a/src/auth/magic_link/MagicLinkAuthController.ts b/src/auth/magic_link/MagicLinkAuthController.ts index 9493cf7..c344e32 100644 --- a/src/auth/magic_link/MagicLinkAuthController.ts +++ b/src/auth/magic_link/MagicLinkAuthController.ts @@ -15,38 +15,40 @@ import User from "../models/User"; export default abstract class MagicLinkAuthController extends AuthController { public static async checkAndAuth(req: Request, res: Response, magicLink: MagicLink): Promise { - if (magicLink.getSessionID() !== req.sessionID!) throw new BadOwnerMagicLink(); + const session = req.getSession(); + if (magicLink.getOrFail('session_id') !== session.id) throw new BadOwnerMagicLink(); if (!await magicLink.isAuthorized()) throw new UnauthorizedMagicLink(); if (!await magicLink.isValid()) throw new InvalidMagicLink(); // Auth try { - return await req.as(AuthMiddleware).getAuthGuard().authenticateOrRegister(req.session!, magicLink, undefined, async (connection, user) => { - const callbacks: RegisterCallback[] = []; + return await req.as(AuthMiddleware).getAuthGuard().authenticateOrRegister( + session, magicLink, undefined, async (connection, user) => { + const callbacks: RegisterCallback[] = []; - const userEmail = UserEmail.create({ - user_id: user.id, - email: magicLink.getEmail(), + const userEmail = UserEmail.create({ + user_id: user.id, + email: magicLink.getOrFail('email'), + }); + await userEmail.save(connection, c => callbacks.push(c)); + user.main_email_id = userEmail.id; + await user.save(connection, c => callbacks.push(c)); + + return callbacks; }); - await userEmail.save(connection, c => callbacks.push(c)); - user.main_email_id = userEmail.id; - await user.save(connection, c => callbacks.push(c)); - - return callbacks; - }); } catch (e) { if (e instanceof PendingApprovalAuthError) { res.format({ json: () => { res.json({ 'status': 'warning', - 'message': `Your account is pending review. You'll receive an email once you're approved.` + 'message': `Your account is pending review. You'll receive an email once you're approved.`, }); }, html: () => { req.flash('warning', `Your account is pending review. You'll receive an email once you're approved.`); res.redirect('/'); - } + }, }); return null; } else { @@ -65,7 +67,8 @@ export default abstract class MagicLinkAuthController extends AuthController { } protected async getAuth(req: Request, res: Response, next: NextFunction): Promise { - const link = await MagicLink.bySessionID(req.sessionID!, [this.loginMagicLinkActionType, this.registerMagicLinkActionType]); + const link = await MagicLink.bySessionId(req.getSession().id, + [this.loginMagicLinkActionType, this.registerMagicLinkActionType]); if (link && await link.isValid()) { res.redirect(Controller.route('magic_link_lobby', undefined, { redirect_uri: req.query.redirect_uri?.toString() || undefined, @@ -76,7 +79,7 @@ export default abstract class MagicLinkAuthController extends AuthController { await super.getAuth(req, res, next); } - protected async postAuth(req: Request, res: Response, next: NextFunction): Promise { + protected async postAuth(req: Request, res: Response, _next: NextFunction): Promise { const email = req.body.email; if (!email) throw new BadRequestError('Email not specified.', 'Please try again.', req.originalUrl); @@ -96,7 +99,7 @@ export default abstract class MagicLinkAuthController extends AuthController { // Register (email link) const geo = geoip.lookup(req.ip); await MagicLinkController.sendMagicLink( - req.sessionID!, + req.getSession().id, isRegistration ? this.registerMagicLinkActionType : this.loginMagicLinkActionType, Controller.route('auth', undefined, { redirect_uri: req.query.redirect_uri?.toString() || undefined, @@ -107,7 +110,7 @@ export default abstract class MagicLinkAuthController extends AuthController { type: isRegistration ? 'register' : 'login', ip: req.ip, geo: geo ? `${geo.city}, ${geo.country}` : 'Unknown location', - } + }, ); res.redirect(Controller.route('magic_link_lobby', undefined, { @@ -125,13 +128,18 @@ export default abstract class MagicLinkAuthController extends AuthController { /** * Check whether a magic link is authorized, and authenticate if yes */ - protected async getCheckAuth(req: Request, res: Response, next: NextFunction): Promise { - const magicLink = await MagicLink.bySessionID(req.sessionID!, [this.loginMagicLinkActionType, this.registerMagicLinkActionType]); + protected async getCheckAuth(req: Request, res: Response, _next: NextFunction): Promise { + const magicLink = await MagicLink.bySessionId(req.getSession().id, + [this.loginMagicLinkActionType, this.registerMagicLinkActionType]); if (!magicLink) { res.format({ json: () => { - throw new BadRequestError('No magic link were found linked with that session.', 'Please retry once you have requested a magic link.', req.originalUrl); + throw new BadRequestError( + 'No magic link were found linked with that session.', + 'Please retry once you have requested a magic link.', + req.originalUrl, + ); }, default: () => { req.flash('warning', 'No magic link found. Please try again.'); @@ -160,19 +168,19 @@ export default abstract class MagicLinkAuthController extends AuthController { } export class BadOwnerMagicLink extends AuthError { - constructor() { + public constructor() { super(`This magic link doesn't belong to this session.`); } } export class UnauthorizedMagicLink extends AuthError { - constructor() { + public constructor() { super(`This magic link is unauthorized.`); } } export class InvalidMagicLink extends AuthError { - constructor() { + public constructor() { super(`This magic link is invalid.`); } -} \ No newline at end of file +} diff --git a/src/auth/magic_link/MagicLinkController.ts b/src/auth/magic_link/MagicLinkController.ts index e55881a..549ac6d 100644 --- a/src/auth/magic_link/MagicLinkController.ts +++ b/src/auth/magic_link/MagicLinkController.ts @@ -6,15 +6,24 @@ import Throttler from "../../Throttler"; import Mail, {MailTemplate} from "../../Mail"; import MagicLink from "../models/MagicLink"; import config from "config"; +import Application from "../../Application"; +import {ParsedUrlQueryInput} from "querystring"; -export default abstract class MagicLinkController extends Controller { - public static async sendMagicLink(sessionID: string, actionType: string, original_url: string, email: string, mailTemplate: MailTemplate, data: object): Promise { - Throttler.throttle('magic_link', 2, MagicLink.validityPeriod(), sessionID, 0, 0); +export default abstract class MagicLinkController extends Controller { + public static async sendMagicLink( + sessionId: string, + actionType: string, + original_url: string, + email: string, + mailTemplate: MailTemplate, + data: ParsedUrlQueryInput, + ): Promise { + Throttler.throttle('magic_link', 2, MagicLink.validityPeriod(), sessionId, 0, 0); Throttler.throttle('magic_link', 1, MagicLink.validityPeriod(), email, 0, 0); - const link = await MagicLink.bySessionID(sessionID, actionType) || + const link = await MagicLink.bySessionId(sessionId, actionType) || MagicLink.create({ - session_id: sessionID, + session_id: sessionId, action_type: actionType, original_url: original_url, }); @@ -34,7 +43,7 @@ export default abstract class MagicLinkController extends Controller { protected readonly magicLinkWebsocketPath: string; - protected constructor(magicLinkWebsocketListener: MagicLinkWebSocketListener) { + protected constructor(magicLinkWebsocketListener: MagicLinkWebSocketListener) { super(); this.magicLinkWebsocketPath = magicLinkWebsocketListener.path(); } @@ -49,14 +58,14 @@ export default abstract class MagicLinkController extends Controller { } protected async getLobby(req: Request, res: Response): Promise { - const link = await MagicLink.bySessionID(req.sessionID!); + const link = await MagicLink.bySessionId(req.getSession().id); if (!link) { throw new NotFoundHttpError('magic link', req.url); } if (!await link.isValid()) { req.flash('error', 'This magic link has expired. Please try again.'); - res.redirect(link.getOriginalURL()); + res.redirect(link.getOrFail('original_url')); return; } @@ -66,8 +75,8 @@ export default abstract class MagicLinkController extends Controller { } res.render('magic_link_lobby', { - email: link.getEmail(), - type: link.getActionType(), + email: link.getOrFail('email'), + type: link.getOrFail('action_type'), validUntil: link.getExpirationDate().getTime(), websocketUrl: config.get('public_websocket_url') + this.magicLinkWebsocketPath, }); @@ -76,7 +85,8 @@ export default abstract class MagicLinkController extends Controller { protected async getMagicLink(req: Request, res: Response): Promise { const id = parseInt(req.query.id); const token = req.query.token; - if (!id || !token) throw new BadRequestError('Need parameters id, token.', 'Please try again.', req.originalUrl); + if (!id || !token) + throw new BadRequestError('Need parameters id, token.', 'Please try again.', req.originalUrl); let success = true; let err; @@ -91,7 +101,8 @@ export default abstract class MagicLinkController extends Controller { // Validation success, authenticate the user magicLink.authorize(); await magicLink.save(); - MagicLinkWebSocketListener.refreshMagicLink(magicLink.getSessionID()); + this.getApp().as>(MagicLinkWebSocketListener) + .refreshMagicLink(magicLink.getOrFail('session_id')); } } @@ -103,4 +114,4 @@ export default abstract class MagicLinkController extends Controller { } protected abstract async performAction(magicLink: MagicLink, req: Request, res: Response): Promise; -} \ No newline at end of file +} diff --git a/src/auth/magic_link/MagicLinkWebSocketListener.ts b/src/auth/magic_link/MagicLinkWebSocketListener.ts index 4ccfab3..d0600d9 100644 --- a/src/auth/magic_link/MagicLinkWebSocketListener.ts +++ b/src/auth/magic_link/MagicLinkWebSocketListener.ts @@ -2,18 +2,19 @@ import WebSocket from "ws"; import {IncomingMessage} from "http"; import WebSocketListener from "../../WebSocketListener"; import MagicLink from "../models/MagicLink"; +import Application from "../../Application"; -export default class MagicLinkWebSocketListener extends WebSocketListener { - private static readonly connections: { [p: string]: (() => void)[] } = {}; +export default class MagicLinkWebSocketListener extends WebSocketListener { + private readonly connections: { [p: string]: (() => void)[] | undefined } = {}; - public static refreshMagicLink(sessionID: string) { - const fs = MagicLinkWebSocketListener.connections[sessionID]; + public refreshMagicLink(sessionId: string): void { + const fs = this.connections[sessionId]; if (fs) { fs.forEach(f => f()); } } - async handle(socket: WebSocket, request: IncomingMessage, session: Express.Session | null): Promise { + public async handle(socket: WebSocket, request: IncomingMessage, session: Express.Session | null): Promise { // Drop if requested without session if (!session) { socket.close(1002, 'Session is required for this request.'); @@ -26,7 +27,7 @@ export default class MagicLinkWebSocketListener extends WebSocketListener { }); // Get magic link - const magicLink = await MagicLink.bySessionID(session.id); + const magicLink = await MagicLink.bySessionId(session.id); // Refresh if immediately applicable if (!magicLink || !await magicLink.isValid() || await magicLink.isAuthorized()) { @@ -47,16 +48,19 @@ export default class MagicLinkWebSocketListener extends WebSocketListener { }; socket.on('close', () => { - MagicLinkWebSocketListener.connections[session.id] = MagicLinkWebSocketListener.connections[session.id].filter(f => f !== f); - if (MagicLinkWebSocketListener.connections[session.id].length === 0) delete MagicLinkWebSocketListener.connections[session.id]; + const connections = this.connections[session.id]; + if (connections) { + this.connections[session.id] = connections.filter(f => f !== f); + if (connections.length === 0) delete this.connections[session.id]; + } }); - if (!MagicLinkWebSocketListener.connections[session.id]) MagicLinkWebSocketListener.connections[session.id] = []; - - MagicLinkWebSocketListener.connections[session.id].push(f); + let connections = this.connections[session.id]; + if (!connections) connections = this.connections[session.id] = []; + connections.push(f); } - path(): string { + public path(): string { return '/magic-link'; } -} \ No newline at end of file +} diff --git a/src/auth/migrations/AddApprovedFieldToUsersTable.ts b/src/auth/migrations/AddApprovedFieldToUsersTable.ts index 57c3fda..fbe7970 100644 --- a/src/auth/migrations/AddApprovedFieldToUsersTable.ts +++ b/src/auth/migrations/AddApprovedFieldToUsersTable.ts @@ -16,4 +16,4 @@ export default class AddApprovedFieldToUsersTable extends Migration { public registerModels(): void { ModelFactory.get(User).addComponent(UserApprovedComponent); } -} \ No newline at end of file +} diff --git a/src/auth/migrations/CreateMagicLinksTable.ts b/src/auth/migrations/CreateMagicLinksTable.ts index 7cc9cb3..3f223de 100644 --- a/src/auth/migrations/CreateMagicLinksTable.ts +++ b/src/auth/migrations/CreateMagicLinksTable.ts @@ -27,4 +27,4 @@ export default class CreateMagicLinksTable extends Migration { ModelFactory.register(MagicLink); } -} \ No newline at end of file +} diff --git a/src/auth/migrations/DropNameFromUsers.ts b/src/auth/migrations/DropNameFromUsers.ts index afb116e..1ff45db 100644 --- a/src/auth/migrations/DropNameFromUsers.ts +++ b/src/auth/migrations/DropNameFromUsers.ts @@ -10,6 +10,4 @@ export default class DropNameFromUsers extends Migration { await this.query('ALTER TABLE users ADD COLUMN name VARCHAR(64)', connection); } - public registerModels(): void { - } -} \ No newline at end of file +} diff --git a/src/auth/migrations/FixUserMainEmailRelation.ts b/src/auth/migrations/FixUserMainEmailRelation.ts index e44ef73..ff6c8d0 100644 --- a/src/auth/migrations/FixUserMainEmailRelation.ts +++ b/src/auth/migrations/FixUserMainEmailRelation.ts @@ -17,13 +17,9 @@ export default class FixUserMainEmailRelation extends Migration { await this.query(`ALTER TABLE user_emails ADD COLUMN main BOOLEAN DEFAULT false`, connection); await this.query(`UPDATE user_emails ue LEFT JOIN users u ON ue.id = u.main_email_id - SET ue.main = true`, connection) + SET ue.main = true`, connection); await this.query(`ALTER TABLE users DROP FOREIGN KEY main_user_email_fk, DROP COLUMN main_email_id`, connection); } - - public registerModels(): void { - } - -} \ No newline at end of file +} diff --git a/src/auth/models/MagicLink.ts b/src/auth/models/MagicLink.ts index 6fa4460..2fcacef 100644 --- a/src/auth/models/MagicLink.ts +++ b/src/auth/models/MagicLink.ts @@ -9,8 +9,8 @@ import UserEmail from "./UserEmail"; import {EMAIL_REGEX} from "../../db/Validator"; export default class MagicLink extends Model implements AuthProof { - public static async bySessionID(sessionID: string, actionType?: string | string[]): Promise { - let query = this.select().where('session_id', sessionID); + public static async bySessionId(sessionId: string, actionType?: string | string[]): Promise { + let query = this.select().where('session_id', sessionId); if (actionType !== undefined) { if (typeof actionType === 'string') { query = query.where('action_type', actionType); @@ -26,10 +26,10 @@ export default class MagicLink extends Model implements AuthProof { } public readonly id?: number = undefined; - private session_id?: string = undefined; + public readonly session_id?: string = undefined; private email?: string = undefined; private token?: string = undefined; - private action_type?: string = undefined; + public readonly action_type?: string = undefined; private original_url?: string = undefined; private generated_at?: Date = undefined; private authorized: boolean = false; @@ -46,9 +46,9 @@ export default class MagicLink extends Model implements AuthProof { public async getResource(): Promise { const email = await UserEmail.select() .with('user') - .where('email', await this.getEmail()) + .where('email', await this.getOrFail('email')) .first(); - return email ? email.user.get() : null; + return email ? await email.user.get() : null; } public async revoke(): Promise { @@ -61,10 +61,10 @@ export default class MagicLink extends Model implements AuthProof { } public async isAuthorized(): Promise { - return this.authorized!; + return this.authorized; } - public authorize() { + public authorize(): void { this.authorized = true; } @@ -85,28 +85,21 @@ export default class MagicLink extends Model implements AuthProof { * @returns {@code null} if the token is valid, an error {@code string} otherwise. */ public async verifyToken(tokenGuess: string): Promise { - if (this.token === undefined || this.generated_at === undefined) return 'This token was not generated.'; // There is no token - if (new Date().getTime() - this.generated_at.getTime() > MagicLink.validityPeriod()) return 'This token has expired.'; // Token has expired - if (!await argon2.verify(this.token, tokenGuess)) return 'This token is invalid.'; + // There is no token + if (this.token === undefined || this.generated_at === undefined) + return 'This token was not generated.'; + + // Token has expired + if (new Date().getTime() - this.generated_at.getTime() > MagicLink.validityPeriod()) + return 'This token has expired.'; + + // Token is invalid + if (!await argon2.verify(this.token, tokenGuess)) + return 'This token is invalid.'; return null; } - public getSessionID(): string { - return this.session_id!; - } - - public getEmail(): string { - return this.email!; - } - - public getActionType(): string { - return this.action_type!; - } - - public getOriginalURL(): string { - return this.original_url!; - } public getExpirationDate(): Date { if (!this.generated_at) return new Date(); diff --git a/src/auth/models/User.ts b/src/auth/models/User.ts index a61e6f3..d2652c4 100644 --- a/src/auth/models/User.ts +++ b/src/auth/models/User.ts @@ -8,7 +8,8 @@ import UserApprovedComponent from "./UserApprovedComponent"; export default class User extends Model { public static isApprovalMode(): boolean { - return config.get('approval_mode') && MysqlConnectionManager.hasMigration(AddApprovedFieldToUsersTable); + return config.get('approval_mode') && + MysqlConnectionManager.hasMigration(AddApprovedFieldToUsersTable); } public readonly id?: number = undefined; @@ -19,7 +20,7 @@ export default class User extends Model { public readonly emails = new ManyModelRelation(this, UserEmail, { localKey: 'id', - foreignKey: 'user_id' + foreignKey: 'user_id', }); public readonly mainEmail = this.emails.cloneReduceToOne().constraint(q => q.where('id', this.main_email_id)); diff --git a/src/auth/models/UserApprovedComponent.ts b/src/auth/models/UserApprovedComponent.ts index 5060fcd..648dfa9 100644 --- a/src/auth/models/UserApprovedComponent.ts +++ b/src/auth/models/UserApprovedComponent.ts @@ -3,7 +3,4 @@ import User from "./User"; export default class UserApprovedComponent extends ModelComponent { public approved: boolean = false; - - protected init(): void { - } -} \ No newline at end of file +} diff --git a/src/auth/models/UserEmail.ts b/src/auth/models/UserEmail.ts index 5d5ca85..e3d58e8 100644 --- a/src/auth/models/UserEmail.ts +++ b/src/auth/models/UserEmail.ts @@ -11,7 +11,7 @@ export default class UserEmail extends Model { public readonly user = new OneModelRelation(this, User, { localKey: 'user_id', - foreignKey: 'id' + foreignKey: 'id', }); protected init(): void { diff --git a/src/components/AutoUpdateComponent.ts b/src/components/AutoUpdateComponent.ts index 10fa90c..6b28e41 100644 --- a/src/components/AutoUpdateComponent.ts +++ b/src/components/AutoUpdateComponent.ts @@ -6,6 +6,11 @@ import {ForbiddenHttpError} from "../HttpError"; import Logger from "../Logger"; export default class AutoUpdateComponent extends ApplicationComponent { + private static async runCommand(command: string): Promise { + Logger.info(`> ${command}`); + Logger.info(child_process.execSync(command).toString()); + } + public async checkSecuritySettings(): Promise { this.checkSecurityConfigField('gitlab_webhook_token'); } @@ -13,7 +18,8 @@ export default class AutoUpdateComponent extends ApplicationComponent { public async init(router: Router): Promise { router.post('/update/push.json', (req, res) => { const token = req.header('X-Gitlab-Token'); - if (!token || token !== config.get('gitlab_webhook_token')) throw new ForbiddenHttpError('Invalid token', req.url); + if (!token || token !== config.get('gitlab_webhook_token')) + throw new ForbiddenHttpError('Invalid token', req.url); this.update(req.body).catch(Logger.error); @@ -23,20 +29,20 @@ export default class AutoUpdateComponent extends ApplicationComponent { }); } - private async update(params: any) { + private async update(params: { [p: string]: unknown }) { Logger.info('Update params:', params); try { Logger.info('Starting auto update...'); // Fetch - await this.runCommand(`git pull`); + await AutoUpdateComponent.runCommand(`git pull`); // Install new dependencies - await this.runCommand(`yarn install --production=false`); + await AutoUpdateComponent.runCommand(`yarn install --production=false`); // Process assets - await this.runCommand(`yarn dist`); + await AutoUpdateComponent.runCommand(`yarn dist`); // Stop app await this.getApp().stop(); @@ -46,9 +52,4 @@ export default class AutoUpdateComponent extends ApplicationComponent { Logger.error(e, 'An error occurred while running the auto update.'); } } - - private async runCommand(command: string): Promise { - Logger.info(`> ${command}`); - Logger.info(child_process.execSync(command).toString()); - } -} \ No newline at end of file +} diff --git a/src/components/CsrfProtectionComponent.ts b/src/components/CsrfProtectionComponent.ts index 467a959..3965c58 100644 --- a/src/components/CsrfProtectionComponent.ts +++ b/src/components/CsrfProtectionComponent.ts @@ -7,14 +7,14 @@ import {AuthMiddleware} from "../auth/AuthComponent"; export default class CsrfProtectionComponent extends ApplicationComponent { private static readonly excluders: ((req: Request) => boolean)[] = []; - public static getCSRFToken(session: Express.Session): string { + public static getCsrfToken(session: Express.Session): string { if (typeof session.csrf !== 'string') { session.csrf = crypto.randomBytes(64).toString('base64'); } return session.csrf; } - public static addExcluder(excluder: (req: Request) => boolean) { + public static addExcluder(excluder: (req: Request) => boolean): void { this.excluders.push(excluder); } @@ -24,22 +24,19 @@ export default class CsrfProtectionComponent extends ApplicationComponent { if (excluder(req)) return next(); } - if (!req.session) { - throw new Error('Session is unavailable.'); - } - - res.locals.getCSRFToken = () => { - return CsrfProtectionComponent.getCSRFToken(req.session!); + const session = req.getSession(); + res.locals.getCsrfToken = () => { + return CsrfProtectionComponent.getCsrfToken(session); }; if (!['GET', 'HEAD', 'OPTIONS'].find(s => s === req.method)) { try { if (!await req.as(AuthMiddleware).getAuthGuard().isAuthenticatedViaRequest(req)) { - if (req.session.csrf === undefined) { + if (session.csrf === undefined) { return next(new InvalidCsrfTokenError(req.baseUrl, `You weren't assigned any CSRF token.`)); } else if (req.body.csrf === undefined) { return next(new InvalidCsrfTokenError(req.baseUrl, `You didn't provide any CSRF token.`)); - } else if (req.session.csrf !== req.body.csrf) { + } else if (session.csrf !== req.body.csrf) { return next(new InvalidCsrfTokenError(req.baseUrl, `Tokens don't match.`)); } } @@ -53,20 +50,20 @@ export default class CsrfProtectionComponent extends ApplicationComponent { } class InvalidCsrfTokenError extends BadRequestError { - constructor(url: string, details: string, cause?: Error) { + public constructor(url: string, details: string, cause?: Error) { super( `Invalid CSRF token`, `${details} We can't process this request. Please try again.`, url, - cause + cause, ); } - get name(): string { + public get name(): string { return 'Invalid CSRF Token'; } - get errorCode(): number { + public get errorCode(): number { return 401; } } diff --git a/src/components/ExpressAppComponent.ts b/src/components/ExpressAppComponent.ts index 58a3d59..90489fb 100644 --- a/src/components/ExpressAppComponent.ts +++ b/src/components/ExpressAppComponent.ts @@ -31,7 +31,7 @@ export default class ExpressAppComponent extends ApplicationComponent { public async init(router: Router): Promise { router.use(express.json({ - type: req => req.headers['content-type']?.match(/^application\/(.+\+)?json$/) + type: req => req.headers['content-type']?.match(/^application\/(.+\+)?json$/), })); router.use(express.urlencoded({ extended: true, @@ -42,7 +42,7 @@ export default class ExpressAppComponent extends ApplicationComponent { router.use((req, res, next) => { req.middlewares = []; - req.as = (type: Type) => { + req.as = (type: Type): M => { const middleware = req.middlewares.find(m => m.constructor === type); if (!middleware) throw new Error('Middleware ' + type.name + ' not present in this request.'); return middleware as M; @@ -52,8 +52,9 @@ export default class ExpressAppComponent extends ApplicationComponent { } public async stop(): Promise { - if (this.server) { - await this.close('Webserver', this.server, this.server.close); + const server = this.server; + if (server) { + await this.close('Webserver', callback => server.close(callback)); } } @@ -63,6 +64,7 @@ export default class ExpressAppComponent extends ApplicationComponent { } public getExpressApp(): Express { - return this.expressApp!; + if (!this.expressApp) throw new Error('Express app not initialized.'); + return this.expressApp; } } diff --git a/src/components/FormHelperComponent.ts b/src/components/FormHelperComponent.ts index 0905aaa..93f0693 100644 --- a/src/components/FormHelperComponent.ts +++ b/src/components/FormHelperComponent.ts @@ -4,11 +4,7 @@ import {Router} from "express"; export default class FormHelperComponent extends ApplicationComponent { public async init(router: Router): Promise { router.use((req, res, next) => { - if (!req.session) { - throw new Error('Session is unavailable.'); - } - - let _validation: any = null; + let _validation: unknown | null; res.locals.validation = () => { if (!_validation) { const v = req.flash('validation'); @@ -16,9 +12,9 @@ export default class FormHelperComponent extends ApplicationComponent { } return _validation; - } + }; - let _previousFormData: any = null; + let _previousFormData: unknown | null = null; res.locals.previousFormData = () => { if (!_previousFormData) { const v = req.flash('previousFormData'); @@ -39,4 +35,4 @@ export default class FormHelperComponent extends ApplicationComponent { next(); }); } -} \ No newline at end of file +} diff --git a/src/components/LogRequestsComponent.ts b/src/components/LogRequestsComponent.ts index c492a48..c6e6ccf 100644 --- a/src/components/LogRequestsComponent.ts +++ b/src/components/LogRequestsComponent.ts @@ -2,29 +2,24 @@ import ApplicationComponent from "../ApplicationComponent"; import onFinished from "on-finished"; import Logger from "../Logger"; import {Request, Response, Router} from "express"; +import {HttpError} from "../HttpError"; export default class LogRequestsComponent extends ApplicationComponent { private static fullRequests: boolean = false; - public static logFullHttpRequests() { + public static logFullHttpRequests(): void { this.fullRequests = true; Logger.info('Http requests will be logged with more details.'); } - public static logRequest(req: Request, res: Response, err: any = null, additionalStr: string = '', silent: boolean = false): string { - if (!LogRequestsComponent.fullRequests) { - let logStr = `${req.method} ${req.originalUrl} - ${res.statusCode}`; - if (err) { - if (silent) { - logStr += ` ${err.errorCode} ${err.name}`; - return Logger.silentError(err, logStr); - } else { - return Logger.error(err, logStr, additionalStr, err); - } - } else { - Logger.info(logStr); - } - } else { + public static logRequest( + req: Request, + res: Response, + err?: unknown, + additionalStr: string = '', + silent: boolean = false, + ): string { + if (LogRequestsComponent.fullRequests) { const requestObj = JSON.stringify({ ip: req.ip, host: req.hostname, @@ -36,16 +31,37 @@ export default class LogRequestsComponent extends ApplicationComponent { body: req.body, files: req.files, cookies: req.cookies, - sessionId: req.sessionID, + sessionId: req.session?.id, result: { - code: res.statusCode - } + code: res.statusCode, + }, }, null, 4); if (err) { - return Logger.error(err, requestObj, err); + if (err instanceof Error) { + return Logger.error(err, requestObj, err); + } else { + return Logger.error(new Error(String(err)), requestObj); + } } else { Logger.info(requestObj); } + } else { + let logStr = `${req.method} ${req.originalUrl} - ${res.statusCode}`; + if (err) { + if (err instanceof Error) { + if (silent) { + if (err instanceof HttpError) logStr += ` ${err.errorCode}`; + logStr += ` ${err.name}`; + return Logger.silentError(err, logStr); + } else { + return Logger.error(err, logStr, additionalStr, err); + } + } else { + return Logger.error(new Error(String(err)), logStr); + } + } else { + Logger.info(logStr); + } } return ''; @@ -61,4 +77,4 @@ export default class LogRequestsComponent extends ApplicationComponent { next(); }); } -} \ No newline at end of file +} diff --git a/src/components/MailComponent.ts b/src/components/MailComponent.ts index 5e903bb..b4d5ed9 100644 --- a/src/components/MailComponent.ts +++ b/src/components/MailComponent.ts @@ -15,7 +15,7 @@ export default class MailComponent extends ApplicationComponent { } } - public async start(app: Express): Promise { + public async start(_app: Express): Promise { await this.prepare('Mail connection', () => Mail.prepare()); } @@ -23,4 +23,4 @@ export default class MailComponent extends ApplicationComponent { Mail.end(); } -} \ No newline at end of file +} diff --git a/src/components/MaintenanceComponent.ts b/src/components/MaintenanceComponent.ts index e6ad250..ebfd8a3 100644 --- a/src/components/MaintenanceComponent.ts +++ b/src/components/MaintenanceComponent.ts @@ -8,7 +8,7 @@ export default class MaintenanceComponent extends ApplicationComponent { private readonly application: Application; private readonly canServe: () => boolean; - constructor(application: Application, canServe: () => boolean) { + public constructor(application: Application, canServe: () => boolean) { super(); this.application = application; this.canServe = canServe; @@ -34,4 +34,4 @@ export default class MaintenanceComponent extends ApplicationComponent { next(); }); } -} \ No newline at end of file +} diff --git a/src/components/MysqlComponent.ts b/src/components/MysqlComponent.ts index b61c6ba..850ff1b 100644 --- a/src/components/MysqlComponent.ts +++ b/src/components/MysqlComponent.ts @@ -3,7 +3,7 @@ import {Express} from "express"; import MysqlConnectionManager from "../db/MysqlConnectionManager"; export default class MysqlComponent extends ApplicationComponent { - public async start(app: Express): Promise { + public async start(_app: Express): Promise { await this.prepare('Mysql connection', () => MysqlConnectionManager.prepare()); } @@ -15,4 +15,4 @@ export default class MysqlComponent extends ApplicationComponent { return MysqlConnectionManager.isReady(); } -} \ No newline at end of file +} diff --git a/src/components/NunjucksComponent.ts b/src/components/NunjucksComponent.ts index 31fd54c..23197f9 100644 --- a/src/components/NunjucksComponent.ts +++ b/src/components/NunjucksComponent.ts @@ -3,9 +3,7 @@ import config from "config"; import {Express, NextFunction, Request, Response, Router} from "express"; import ApplicationComponent from "../ApplicationComponent"; import Controller from "../Controller"; -import {ServerError} from "../HttpError"; import * as querystring from "querystring"; -import {ParsedUrlQueryInput} from "querystring"; import * as util from "util"; import * as path from "path"; import * as fs from "fs"; @@ -42,11 +40,7 @@ export default class NunjucksComponent extends ApplicationComponent { noCache: !config.get('view.cache'), throwOnUndefined: true, }) - .addGlobal('route', (route: string, params?: { [p: string]: string } | [], query?: ParsedUrlQueryInput, absolute?: boolean) => { - const path = Controller.route(route, params, query, absolute); - if (path === null) throw new ServerError(`Route ${route} not found.`); - return path; - }) + .addGlobal('route', Controller.route) .addGlobal('app_version', this.getApp().getVersion()) .addGlobal('core_version', coreVersion) .addGlobal('querystring', querystring) @@ -62,7 +56,7 @@ export default class NunjucksComponent extends ApplicationComponent { app.set('view engine', 'njk'); } - public async init(router: Router): Promise { + public async init(_router: Router): Promise { this.use(NunjucksMiddleware); } diff --git a/src/components/RedirectBackComponent.ts b/src/components/RedirectBackComponent.ts index 75be932..9b08553 100644 --- a/src/components/RedirectBackComponent.ts +++ b/src/components/RedirectBackComponent.ts @@ -11,7 +11,7 @@ export default class RedirectBackComponent extends ApplicationComponent { public async handle(router: Router): Promise { router.use((req, res, next) => { - res.redirectBack = (defaultUrl?: string) => { + res.redirectBack = (defaultUrl?: string): void => { const previousUrl = RedirectBackComponent.getPreviousURL(req, defaultUrl); if (!previousUrl) throw new ServerError(`Couldn't redirect you back.`); res.redirect(previousUrl); @@ -22,12 +22,15 @@ export default class RedirectBackComponent extends ApplicationComponent { }; onFinished(res, (err) => { - if (req.session) { - const contentType = (res.getHeaders())['content-type']; - if (!err && res.statusCode === 200 && (contentType && typeof contentType !== 'number' && contentType.indexOf('text/html') >= 0)) { - req.session!.previousUrl = req.originalUrl; - Logger.debug('Prev url set to', req.session!.previousUrl); - req.session!.save((err) => { + const session = req.session; + if (session) { + const contentType = res.getHeader('content-type'); + if (!err && res.statusCode === 200 && ( + contentType && typeof contentType !== 'number' && contentType.indexOf('text/html') >= 0 + )) { + session.previousUrl = req.originalUrl; + Logger.debug('Prev url set to', session.previousUrl); + session.save((err) => { if (err) { Logger.error(err, 'Error while saving session'); } @@ -39,4 +42,4 @@ export default class RedirectBackComponent extends ApplicationComponent { next(); }); } -} \ No newline at end of file +} diff --git a/src/components/RedisComponent.ts b/src/components/RedisComponent.ts index 30e12fb..996f1eb 100644 --- a/src/components/RedisComponent.ts +++ b/src/components/RedisComponent.ts @@ -13,11 +13,11 @@ export default class RedisComponent extends ApplicationComponent implements Cach private redisClient?: RedisClient; private store?: Store; - public async start(app: Express): Promise { + public async start(_app: Express): Promise { this.redisClient = redis.createClient(config.get('redis.port'), config.get('redis.host'), { password: config.has('redis.password') ? config.get('redis.password') : undefined, }); - this.redisClient.on('error', (err: any) => { + this.redisClient.on('error', (err: Error) => { Logger.error(err, 'An error occurred with redis.'); }); this.store = new RedisStore({ @@ -27,8 +27,9 @@ export default class RedisComponent extends ApplicationComponent implements Cach } public async stop(): Promise { - if (this.redisClient) { - await this.close('Redis connection', this.redisClient, this.redisClient.quit); + const redisClient = this.redisClient; + if (redisClient) { + await this.close('Redis connection', callback => redisClient.quit(callback)); } } @@ -42,7 +43,7 @@ export default class RedisComponent extends ApplicationComponent implements Cach } public async get(key: string, defaultValue?: string): Promise { - return new Promise((resolve, reject) => { + return await new Promise((resolve, reject) => { if (!this.redisClient) { reject(`Redis store was not initialized.`); return; @@ -53,7 +54,7 @@ export default class RedisComponent extends ApplicationComponent implements Cach reject(err); return; } - resolve(val !== null ? val : (defaultValue !== undefined ? defaultValue : null)); + resolve(val || defaultValue || null); }); }); } @@ -63,7 +64,7 @@ export default class RedisComponent extends ApplicationComponent implements Cach } public async forget(key: string): Promise { - return new Promise((resolve, reject) => { + return await new Promise((resolve, reject) => { if (!this.redisClient) { reject(`Redis store was not initialized.`); return; @@ -81,7 +82,7 @@ export default class RedisComponent extends ApplicationComponent implements Cach } public async remember(key: string, value: string, ttl: number): Promise { - return new Promise((resolve, reject) => { + return await new Promise((resolve, reject) => { if (!this.redisClient) { reject(`Redis store was not initialized.`); return; @@ -96,4 +97,4 @@ export default class RedisComponent extends ApplicationComponent implements Cach }); }); } -} \ No newline at end of file +} diff --git a/src/components/ServeStaticDirectoryComponent.ts b/src/components/ServeStaticDirectoryComponent.ts index c2042e3..191ac28 100644 --- a/src/components/ServeStaticDirectoryComponent.ts +++ b/src/components/ServeStaticDirectoryComponent.ts @@ -7,21 +7,18 @@ export default class ServeStaticDirectoryComponent extends ApplicationComponent private readonly root: string; private readonly path?: PathParams; - constructor(root: string, routePath?: PathParams) { + public constructor(root: string, routePath?: PathParams) { super(); this.root = path.join(__dirname, '../../../', root); this.path = routePath; } public async init(router: Router): Promise { - if (typeof this.path !== 'undefined') { + if (this.path) { router.use(this.path, express.static(this.root, {maxAge: 1000 * 3600 * 72})); } else { router.use(express.static(this.root, {maxAge: 1000 * 3600 * 72})); } } - public async stop(): Promise { - } - -} \ No newline at end of file +} diff --git a/src/components/SessionComponent.ts b/src/components/SessionComponent.ts index 964bf35..4aa4c66 100644 --- a/src/components/SessionComponent.ts +++ b/src/components/SessionComponent.ts @@ -14,7 +14,6 @@ export default class SessionComponent extends ApplicationComponent { this.storeComponent = storeComponent; } - public async checkSecuritySettings(): Promise { this.checkSecurityConfigField('session.secret'); if (!config.get('session.cookie.secure')) { @@ -39,17 +38,18 @@ export default class SessionComponent extends ApplicationComponent { router.use(flash()); router.use((req, res, next) => { - if (!req.session) { - throw new Error('Session is unavailable.'); - } + req.getSession = () => { + if (!req.session) throw new Error('Session not initialized.'); + return req.session; + }; - res.locals.session = req.session; + res.locals.session = req.getSession(); - let _flash: any = {}; - res.locals.flash = (key?: string) => { + const _flash: FlashStorage = {}; + res.locals.flash = (key?: string): FlashMessages | unknown[] => { if (key !== undefined) { - if (_flash[key] === undefined) _flash[key] = req.flash(key) || null; - return _flash[key]; + if (_flash[key] === undefined) _flash[key] = req.flash(key); + return _flash[key] || []; } if (_flash._messages === undefined) { @@ -65,4 +65,19 @@ export default class SessionComponent extends ApplicationComponent { next(); }); } -} \ No newline at end of file +} + +export type FlashMessages = { + [k: string]: unknown[] | undefined +}; + +export type DefaultFlashMessages = FlashMessages & { + info?: unknown[] | undefined; + success?: unknown[] | undefined; + warning?: unknown[] | undefined; + error?: unknown[] | undefined; +}; + +type FlashStorage = FlashMessages & { + _messages?: DefaultFlashMessages, +}; diff --git a/src/components/WebSocketServerComponent.ts b/src/components/WebSocketServerComponent.ts index ed5dbca..ff3dff1 100644 --- a/src/components/WebSocketServerComponent.ts +++ b/src/components/WebSocketServerComponent.ts @@ -14,7 +14,7 @@ import NunjucksComponent from "./NunjucksComponent"; export default class WebSocketServerComponent extends ApplicationComponent { private wss?: WebSocket.Server; - constructor( + public constructor( private readonly application: Application, private readonly expressAppComponent: ExpressAppComponent, private readonly storeComponent: RedisComponent, @@ -23,8 +23,8 @@ export default class WebSocketServerComponent extends ApplicationComponent { super(); } - public async start(app: Express): Promise { - const listeners: { [p: string]: WebSocketListener } = this.application.getWebSocketListeners(); + public async start(_app: Express): Promise { + const listeners: { [p: string]: WebSocketListener } = this.application.getWebSocketListeners(); this.wss = new WebSocketServer({ server: this.expressAppComponent.getServer(), }, () => { @@ -78,8 +78,9 @@ export default class WebSocketServerComponent extends ApplicationComponent { } public async stop(): Promise { - if (this.wss) { - await this.close('WebSocket server', this.wss, this.wss.close); + const wss = this.wss; + if (wss) { + await this.close('WebSocket server', callback => wss.close(callback)); } } -} \ No newline at end of file +} diff --git a/src/db/Migration.ts b/src/db/Migration.ts index b52b725..2bd8212 100644 --- a/src/db/Migration.ts +++ b/src/db/Migration.ts @@ -1,5 +1,6 @@ import {Connection} from "mysql"; import MysqlConnectionManager from "./MysqlConnectionManager"; +import {Type} from "../Utils"; export default abstract class Migration { public readonly version: number; @@ -16,9 +17,13 @@ export default abstract class Migration { public abstract async rollback(connection: Connection): Promise; - public abstract registerModels(): void; + public registerModels?(): void; protected async query(queryString: string, connection: Connection): Promise { await MysqlConnectionManager.query(queryString, undefined, connection); } -} \ No newline at end of file +} + +export interface MigrationType extends Type { + new(version: number): M; +} diff --git a/src/db/Model.ts b/src/db/Model.ts index 29ec758..590fd4d 100644 --- a/src/db/Model.ts +++ b/src/db/Model.ts @@ -1,69 +1,75 @@ -import MysqlConnectionManager, {query} from "./MysqlConnectionManager"; +import MysqlConnectionManager, {isQueryVariable, query, QueryVariable} from "./MysqlConnectionManager"; import Validator from "./Validator"; import {Connection} from "mysql"; import ModelComponent from "./ModelComponent"; import {Type} from "../Utils"; -import ModelFactory from "./ModelFactory"; +import ModelFactory, {PrimaryKeyValue} from "./ModelFactory"; import ModelRelation from "./ModelRelation"; -import ModelQuery, {ModelQueryResult, SelectFields} from "./ModelQuery"; +import ModelQuery, {ModelFieldData, ModelQueryResult, SelectFields} from "./ModelQuery"; import {Request} from "express"; import Extendable from "../Extendable"; export default abstract class Model implements Extendable> { public static get table(): string { - return this.name - .replace(/(?:^|\.?)([A-Z])/g, (x, y) => '_' + y.toLowerCase()) - .replace(/^_/, '') - + 's'; + const single = this.name + .replace(/(?:^|\.?)([A-Z])/g, (x, y) => '_' + y.toLowerCase()) + .replace(/^_/, ''); + return single + 's'; } public static getPrimaryKeyFields(): string[] { return ['id']; } - public static create(this: ModelType, data: any): T { + public static create(this: ModelType, data: Pick): M { return ModelFactory.get(this).create(data, true); } - public static select(this: ModelType, ...fields: SelectFields): ModelQuery { + public static select(this: ModelType, ...fields: SelectFields): ModelQuery { return ModelFactory.get(this).select(...fields); } - public static update(this: ModelType, data: { [key: string]: any }): ModelQuery { + public static update(this: ModelType, data: Pick): ModelQuery { return ModelFactory.get(this).update(data); } - public static delete(this: ModelType): ModelQuery { + public static delete(this: ModelType): ModelQuery { return ModelFactory.get(this).delete(); } - public static async getById(this: ModelType, ...id: any): Promise { - return ModelFactory.get(this).getById(...id); + public static async getById(this: ModelType, ...id: PrimaryKeyValue[]): Promise { + return await ModelFactory.get(this).getById(...id); } - public static async paginate(this: ModelType, request: Request, perPage: number = 20, query?: ModelQuery): Promise> { - return ModelFactory.get(this).paginate(request, perPage, query); + public static async paginate( + this: ModelType, + request: Request, + perPage: number = 20, + query?: ModelQuery, + ): Promise> { + return await ModelFactory.get(this).paginate(request, perPage, query); } + protected readonly _factory: ModelFactory; private readonly _components: ModelComponent[] = []; - private readonly _validators: { [key: string]: Validator | undefined } = {}; + private readonly _validators: { [K in keyof this]?: Validator | undefined } = {}; private _exists: boolean; - [key: string]: any; + [key: string]: ModelFieldData; - public constructor(factory: ModelFactory, isNew: boolean) { - if (!factory || !(factory instanceof ModelFactory)) throw new Error('Cannot instantiate model directly.'); + public constructor(factory: ModelFactory, isNew: boolean) { + if (!(factory instanceof ModelFactory)) throw new Error('Cannot instantiate model directly.'); this._factory = factory; - this.init(); + this.init?.(); this._exists = !isNew; } - protected abstract init(): void; + protected init?(): void; - protected setValidation(propertyName: keyof this): Validator { - const validator = new Validator(); - this._validators[propertyName as string] = validator; + protected setValidation(propertyName: K): Validator { + const validator = new Validator(); + this._validators[propertyName] = validator; return validator; } @@ -92,10 +98,10 @@ export default abstract class Model implements Extendable> return null; } - public updateWithData(data: any) { + public updateWithData(data: Pick | Record): void { for (const property of this._properties) { if (data[property] !== undefined) { - this[property] = data[property]; + this[property] = data[property] as this[keyof this & string]; } } } @@ -118,22 +124,24 @@ export default abstract class Model implements Extendable> const needs_full_update = connection ? await this.saveTransaction(connection) : - await MysqlConnectionManager.wrapTransaction(async connection => this.saveTransaction(connection)); + await MysqlConnectionManager.wrapTransaction(async connection => await this.saveTransaction(connection)); const callback = async () => { if (needs_full_update) { - const result = await this._factory.select() - .where('id', this.id!) - .limit(1) - .execute(connection); + const query = this._factory.select(); + for (const field of this._factory.getPrimaryKeyFields()) { + query.where(field, this[field]); + } + query.limit(1); + const result = await query.execute(connection); this.updateWithData(result.results[0]); } await this.afterSave?.(); }; - if (connection) { - postHook!(callback); + if (postHook) { + postHook(callback); } else { await callback(); } @@ -142,19 +150,19 @@ export default abstract class Model implements Extendable> private async saveTransaction(connection: Connection): Promise { // Before save await this.beforeSave?.(connection); - if (!this.exists() && this.hasOwnProperty('created_at')) { + if (!this.exists() && this.hasProperty('created_at')) { this.created_at = new Date(); } - if (this.exists() && this.hasOwnProperty('updated_at')) { + if (this.exists() && this.hasProperty('updated_at')) { this.updated_at = new Date(); } const properties = []; - const values = []; + const values: QueryVariable[] = []; let needsFullUpdate = false; if (this.exists()) { - const data: any = {}; + const data: { [K in keyof this]?: this[K] } = {}; for (const property of this._properties) { const value = this[property]; @@ -170,21 +178,24 @@ export default abstract class Model implements Extendable> } else { const props_holders = []; for (const property of this._properties) { - const value = this[property]; + let value: ModelFieldData = this[property]; if (value === undefined) { needsFullUpdate = true; } else { + if (!isQueryVariable(value)) { + value = value.toString(); + } properties.push(property); props_holders.push('?'); - values.push(value); + values.push(value as QueryVariable); } } const fieldNames = properties.map(f => `\`${f}\``).join(', '); const result = await query(`INSERT INTO ${this.table} (${fieldNames}) VALUES(${props_holders.join(', ')})`, values, connection); - if (this.hasOwnProperty('id')) this.id = result.other.insertId; + if (this.hasProperty('id')) this.id = Number(result.other?.insertId); this._exists = true; } @@ -192,7 +203,7 @@ export default abstract class Model implements Extendable> } public async delete(): Promise { - if (!(await this.exists())) throw new Error('This model instance doesn\'t exist in DB.'); + if (!await this.exists()) throw new Error('This model instance doesn\'t exist in DB.'); const query = this._factory.delete(); for (const indexField of this._factory.getPrimaryKeyFields()) { @@ -204,7 +215,7 @@ export default abstract class Model implements Extendable> public async validate(onlyFormat: boolean = false, connection?: Connection): Promise { return await Promise.all(this._properties.map( - prop => this._validators[prop]?.execute(prop, this[prop], onlyFormat, connection) + prop => this._validators[prop]?.execute(prop, this[prop], onlyFormat, connection), )); } @@ -223,19 +234,30 @@ export default abstract class Model implements Extendable> return this._factory.table; } - private get _properties(): string[] { + private get _properties(): (keyof this & string)[] { return Object.getOwnPropertyNames(this).filter(p => { return !p.startsWith('_') && typeof this[p] !== 'function' && !(this[p] instanceof ModelRelation); }); } + + private hasProperty(key: string | number | symbol): key is keyof this { + return typeof key === 'string' && this._properties.indexOf(key) >= 0; + } + + public getOrFail(k: K): NonNullable { + if (!this[k]) throw new Error(k + ' not initialized.'); + return this[k] as NonNullable; + } } -export interface ModelType extends Type { +export interface ModelType extends Type { table: string; - new(factory: ModelFactory, isNew: boolean): T; + new(factory: ModelFactory, isNew: boolean): M; - getPrimaryKeyFields(): string[]; + getPrimaryKeyFields(): (keyof M & string)[]; + + select(this: ModelType, ...fields: SelectFields): ModelQuery; } diff --git a/src/db/ModelComponent.ts b/src/db/ModelComponent.ts index 6d37763..1784136 100644 --- a/src/db/ModelComponent.ts +++ b/src/db/ModelComponent.ts @@ -1,42 +1,43 @@ import Model from "./Model"; import Validator from "./Validator"; import {getMethods} from "../Utils"; +import {ModelFieldData} from "./ModelQuery"; -export default abstract class ModelComponent { - protected readonly _model: T; - private readonly _validators: { [key: string]: Validator } = {}; +export default abstract class ModelComponent { + protected readonly _model: M; + private readonly _validators: { [K in keyof this]?: Validator } = {}; - [key: string]: any; + [key: string]: ModelFieldData; - public constructor(model: T) { + public constructor(model: M) { this._model = model; } public applyToModel(): void { this.init?.(); + const model = this._model as Model; + for (const property of this._properties) { if (!property.startsWith('_')) { - (this._model as Model)[property] = this[property]; + model[property] = this[property]; } } for (const method of getMethods(this)) { - // @ts-ignore if (!method.startsWith('_') && ['init', 'setValidation'].indexOf(method) < 0 && - this._model[method] === undefined) { - // @ts-ignore - this._model[method] = this[method]; + model[method] === undefined) { + model[method] = this[method]; } } } protected init?(): void; - protected setValidation(propertyName: keyof this): Validator { - const validator = new Validator(); - this._validators[propertyName as string] = validator; + protected setValidation(propertyName: K): Validator { + const validator = new Validator(); + this._validators[propertyName] = validator; return validator; } diff --git a/src/db/ModelFactory.ts b/src/db/ModelFactory.ts index 3e44f51..53551aa 100644 --- a/src/db/ModelFactory.ts +++ b/src/db/ModelFactory.ts @@ -3,33 +3,37 @@ import Model, {ModelType} from "./Model"; import ModelQuery, {ModelQueryResult, SelectFields} from "./ModelQuery"; import {Request} from "express"; -export default class ModelFactory { - private static readonly factories: { [modelType: string]: ModelFactory } = {}; +export default class ModelFactory { + private static readonly factories: { [modelType: string]: ModelFactory | undefined } = {}; - public static register(modelType: ModelType) { + public static register(modelType: ModelType): void { if (this.factories[modelType.name]) throw new Error(`Factory for type ${modelType.name} already defined.`); - this.factories[modelType.name] = new ModelFactory(modelType); + this.factories[modelType.name] = new ModelFactory(modelType) as unknown as ModelFactory; } public static get(modelType: ModelType): ModelFactory { const factory = this.factories[modelType.name]; if (!factory) throw new Error(`No factory registered for ${modelType.name}.`); - return factory; + return factory as unknown as ModelFactory; } - private readonly modelType: ModelType; - private readonly components: ModelComponentFactory[] = []; + public static has(modelType: ModelType): boolean { + return !!this.factories[modelType.name]; + } - protected constructor(modelType: ModelType) { + private readonly modelType: ModelType; + private readonly components: ModelComponentFactory[] = []; + + protected constructor(modelType: ModelType) { this.modelType = modelType; } - public addComponent(modelComponentFactory: ModelComponentFactory) { + public addComponent(modelComponentFactory: ModelComponentFactory): void { this.components.push(modelComponentFactory); } - public create(data: any, isNewModel: boolean): T { - const model = new this.modelType(this, isNewModel); + public create(data: Pick, isNewModel: boolean): M { + const model = new this.modelType(this as unknown as ModelFactory, isNewModel); for (const component of this.components) { model.addComponent(new component(model)); } @@ -41,41 +45,41 @@ export default class ModelFactory { return this.modelType.table; } - public select(...fields: SelectFields): ModelQuery { + public select(...fields: SelectFields): ModelQuery { return ModelQuery.select(this, ...fields); } - public update(data: { [key: string]: any }): ModelQuery { + public update(data: Pick): ModelQuery { return ModelQuery.update(this, data); } - public delete(): ModelQuery { + public delete(): ModelQuery { return ModelQuery.delete(this); } - public getPrimaryKeyFields(): string[] { + public getPrimaryKeyFields(): (keyof M & string)[] { return this.modelType.getPrimaryKeyFields(); } - public getPrimaryKey(modelData: any): any[] { + public getPrimaryKey(modelData: Pick): Pick[keyof M & string][] { return this.getPrimaryKeyFields().map(f => modelData[f]); } - public getPrimaryKeyString(modelData: any): string { + public getPrimaryKeyString(modelData: Pick): string { return this.getPrimaryKey(modelData).join(','); } - public async getById(...id: any): Promise { + public async getById(...id: PrimaryKeyValue[]): Promise { let query = this.select(); const primaryKeyFields = this.getPrimaryKeyFields(); for (let i = 0; i < primaryKeyFields.length; i++) { query = query.where(primaryKeyFields[i], id[i]); } - return query.first(); + return await query.first(); } - public async paginate(request: Request, perPage: number = 20, query?: ModelQuery): Promise> { - let page = request.params.page ? parseInt(request.params.page) : 1; + public async paginate(request: Request, perPage: number = 20, query?: ModelQuery): Promise> { + const page = request.params.page ? parseInt(request.params.page) : 1; if (!query) query = this.select(); if (request.params.sortBy) { const dir = request.params.sortDirection; @@ -87,4 +91,6 @@ export default class ModelFactory { } } -export type ModelComponentFactory = new (model: T) => ModelComponent; +export type ModelComponentFactory = new (model: M) => ModelComponent; + +export type PrimaryKeyValue = string | number | boolean | null | undefined; diff --git a/src/db/ModelQuery.ts b/src/db/ModelQuery.ts index fad6252..bca76f8 100644 --- a/src/db/ModelQuery.ts +++ b/src/db/ModelQuery.ts @@ -1,4 +1,4 @@ -import {query, QueryResult} from "./MysqlConnectionManager"; +import {isQueryVariable, query, QueryResult, QueryVariable} from "./MysqlConnectionManager"; import {Connection} from "mysql"; import Model from "./Model"; import Pagination from "../Pagination"; @@ -12,14 +12,10 @@ export default class ModelQuery implements WhereFieldConsumer 0 ? fields : ['*']); } - public static update(factory: ModelFactory, data: { - [key: string]: any - }): ModelQuery { + public static update(factory: ModelFactory, data: { [K in keyof M]?: M[K] }): ModelQuery { const fields = []; - for (let key in data) { - if (data.hasOwnProperty(key)) { - fields.push(new UpdateFieldValue(inputToFieldOrValue(key, factory.table), data[key], false)); - } + for (const key of Object.keys(data)) { + fields.push(new UpdateFieldValue(inputToFieldOrValue(key, factory.table), data[key], false)); } return new ModelQuery(QueryType.UPDATE, factory, fields); } @@ -41,7 +37,7 @@ export default class ModelQuery implements WhereFieldConsumer implements WhereFieldConsumer | any, test: WhereTest = WhereTest.EQ, operator: WhereOperator = WhereOperator.AND): this { + public where( + field: string, + value: ModelFieldData, + test: WhereTest = WhereTest.EQ, + operator: WhereOperator = WhereOperator.AND, + ): this { this._where.push(new WhereFieldValue(field, value, false, test, operator)); return this; } - public groupWhere(setter: (query: WhereFieldConsumer) => void, operator: WhereOperator = WhereOperator.AND): this { + public groupWhere( + setter: (query: WhereFieldConsumer) => void, + operator: WhereOperator = WhereOperator.AND, + ): this { this._where.push(new WhereFieldValueGroup(this.collectWheres(setter), operator)); return this; } private collectWheres(setter: (query: WhereFieldConsumer) => void): (WhereFieldValue | WhereFieldValueGroup)[] { + // eslint-disable-next-line @typescript-eslint/no-this-alias const query = this; const wheres: (WhereFieldValue | WhereFieldValueGroup)[] = []; setter({ - where(field: string, value: string | Date | ModelQuery | any, test: WhereTest = WhereTest.EQ, operator: WhereOperator = WhereOperator.AND) { + where( + field: string, + value: ModelFieldData, + test: WhereTest = WhereTest.EQ, + operator: WhereOperator = WhereOperator.AND, + ) { wheres.push(new WhereFieldValue(field, value, false, test, operator)); return this; }, - groupWhere(setter: (query: WhereFieldConsumer) => void, operator: WhereOperator = WhereOperator.AND) { - wheres.push(new WhereFieldValueGroup(query.collectWheres(setter), operator)) + groupWhere( + setter: (query: WhereFieldConsumer) => void, + operator: WhereOperator = WhereOperator.AND, + ) { + wheres.push(new WhereFieldValueGroup(query.collectWheres(setter), operator)); return this; - } + }, }); return wheres; } @@ -113,7 +133,7 @@ export default class ModelQuery implements WhereFieldConsumer 1) { if (!this.subRelations[parts[0]]) this.subRelations[parts[0]] = []; - this.subRelations[parts[0]].push(parts.slice(1).join('.')); + this.subRelations[parts[0]]?.push(parts.slice(1).join('.')); } }); return this; @@ -124,7 +144,13 @@ export default class ModelQuery implements WhereFieldConsumer, sortBy: string, direction: SortDirection = 'ASC', raw: boolean = false, limit?: number, offset?: number): this { + public union( + query: ModelQuery, + sortBy: string, direction: SortDirection = 'ASC', + raw: boolean = false, + limit?: number, + offset?: number, + ): this { if (this.type !== QueryType.SELECT) throw new Error('Union queries are only implemented with SELECT.'); this._union = { @@ -150,7 +176,7 @@ export default class ModelQuery implements WhereFieldConsumer { + const fields = this.fields.map(f => { const field = f.toString(); if (field.startsWith('(')) return f; // Skip sub-queries return inputToFieldOrValue(field, this.table); @@ -184,7 +210,7 @@ export default class ModelQuery implements WhereFieldConsumer implements WhereFieldConsumer implements WhereFieldConsumer v instanceof FieldValue) - .flatMap(v => (v).variables) + public get variables(): QueryVariable[] { + const variables: QueryVariable[] = []; + this.fields.filter(v => v instanceof FieldValue) + .flatMap(v => (v as FieldValue).variables) .forEach(v => variables.push(v)); this._where.flatMap(v => this.getVariables(v)) .forEach(v => variables.push(v)); @@ -239,7 +267,7 @@ export default class ModelQuery implements WhereFieldConsumer this.getVariables(v)) : where.variables; @@ -257,33 +285,34 @@ export default class ModelQuery implements WhereFieldConsumer[] } = {}; + const relationMap: { [p: string]: ModelRelation[] } = {}; for (const relation of this.relations) { relationMap[relation] = []; } for (const result of queryResult.results) { - const modelData: any = {}; + const modelData: Record = {}; for (const field of Object.keys(result)) { modelData[field.split('.')[1] || field] = result[field]; } - const model = this.factory.create(modelData, false); + const model = this.factory.create(modelData as Pick, false); models.push(model); models.originalData.push(modelData); - if (this._pivot) { - const pivotData: any = {}; + if (this._pivot && models.pivot) { + const pivotData: Record = {}; for (const field of this._pivot) { pivotData[field] = result[field.split('.')[1]]; } - models.pivot!.push(pivotData); + models.pivot.push(pivotData); } // Eager loading init map for (const relation of this.relations) { if (model[relation] === undefined) throw new Error(`Relation ${relation} doesn't exist on ${model.constructor.name}.`); - relationMap[relation].push(model[relation]); + if (!(model[relation] instanceof ModelRelation)) throw new Error(`Field ${relation} is not a relation on ${model.constructor.name}.`); + relationMap[relation].push(model[relation] as ModelRelation); } } @@ -321,8 +350,9 @@ export default class ModelQuery implements WhereFieldConsumer extends Array { - originalData?: any[]; + originalData?: Record[]; pagination?: Pagination; - pivot?: { [p: string]: any }[]; + pivot?: Record[]; } export enum QueryType { @@ -366,19 +396,30 @@ export enum WhereTest { class FieldValue { protected readonly field: string; - protected value: any; + protected value: ModelFieldData; protected raw: boolean; - constructor(field: string, value: any, raw: boolean) { + public constructor(field: string, value: ModelFieldData, raw: boolean) { this.field = field; this.value = value; this.raw = raw; } public toString(first: boolean = true): string { - const valueStr = (this.raw || this.value === null || this.value instanceof ModelQuery) ? this.value : - (Array.isArray(this.value) ? `(${'?'.repeat(this.value.length).split('').join(',')})` : '?'); - let field = inputToFieldOrValue(this.field); + let valueStr: string; + if (this.value instanceof ModelQuery) { + valueStr = this.value.toString(false); + } else if (this.value === null || this.value === undefined) { + valueStr = 'null'; + } else if (this.raw) { + valueStr = this.value.toString(); + } else { + valueStr = Array.isArray(this.value) ? + `(${'?'.repeat(this.value.length).split('').join(',')})` : + '?'; + } + + const field = inputToFieldOrValue(this.field); return `${first ? '' : ','}${field}${this.test}${valueStr}`; } @@ -386,17 +427,33 @@ class FieldValue { return '='; } - public get variables(): any[] { + public get variables(): QueryVariable[] { if (this.value instanceof ModelQuery) return this.value.variables; - if (this.raw || this.value === null) return []; - if (Array.isArray(this.value)) return this.value; - return [this.value]; + if (this.raw || this.value === null || this.value === undefined) return []; + if (Array.isArray(this.value)) return this.value.map(value => { + if (!isQueryVariable(value)) value = value.toString(); + return value; + }) as QueryVariable[]; + + let value = this.value; + if (!isQueryVariable(value)) value = value.toString(); + return [value as QueryVariable]; } } export class SelectFieldValue extends FieldValue { - public toString(first: boolean = true): string { - return `(${this.value instanceof ModelQuery ? this.value : (this.raw ? this.value : '?')}) AS \`${this.field}\``; + public toString(): string { + let value: string; + if (this.value instanceof ModelQuery) { + value = this.value.toString(true); + } else if (this.value === null || this.value === undefined) { + value = 'null'; + } else { + value = this.raw ? + this.value.toString() : + '?'; + } + return `(${value}) AS \`${this.field}\``; } } @@ -407,7 +464,7 @@ class WhereFieldValue extends FieldValue { private readonly _test: WhereTest; private readonly operator: WhereOperator; - constructor(field: string, value: any, raw: boolean, test: WhereTest, operator: WhereOperator) { + public constructor(field: string, value: ModelFieldData, raw: boolean, test: WhereTest, operator: WhereOperator) { super(field, value, raw); this._test = test; this.operator = operator; @@ -451,7 +508,7 @@ class WhereFieldValueGroup { } export interface WhereFieldConsumer { - where(field: string, value: string | Date | ModelQuery | any, test?: WhereTest, operator?: WhereOperator): this; + where(field: string, value: ModelFieldData, test?: WhereTest, operator?: WhereOperator): this; groupWhere(setter: (query: WhereFieldConsumer) => void, operator?: WhereOperator): this; } @@ -461,9 +518,15 @@ export type SelectFields = (string | SelectFieldValue | UpdateFieldValue)[]; export type SortDirection = 'ASC' | 'DESC'; type ModelQueryUnion = { - query: ModelQuery, + query: ModelQuery, sortBy: string, direction: SortDirection, limit?: number, offset?: number, }; + +export type ModelFieldData = + | QueryVariable + | ModelQuery + | { toString(): string } + | (QueryVariable | { toString(): string })[]; diff --git a/src/db/ModelRelation.ts b/src/db/ModelRelation.ts index 71f68fc..8eb518e 100644 --- a/src/db/ModelRelation.ts +++ b/src/db/ModelRelation.ts @@ -1,4 +1,4 @@ -import ModelQuery, {ModelQueryResult, WhereTest} from "./ModelQuery"; +import ModelQuery, {ModelFieldData, ModelQueryResult, WhereTest} from "./ModelQuery"; import Model, {ModelType} from "./Model"; import ModelFactory from "./ModelFactory"; @@ -34,12 +34,12 @@ export default abstract class ModelRelation): void { - query.where(this.dbProperties.foreignKey, this.getModelID()); + query.where(this.dbProperties.foreignKey, this.getModelId()); } public async get(): Promise { @@ -69,10 +69,13 @@ export default abstract class ModelRelation[], subRelations: string[] = []): Promise> { - const ids = relations.map(r => r.getModelID()) + public async eagerLoad( + relations: ModelRelation[], + subRelations: string[] = [], + ): Promise> { + const ids = relations.map(r => r.getModelId()) .filter(id => id !== null && id !== undefined) - .reduce((array: O[], val) => array.indexOf(val) >= 0 ? array : [...array, val], []); + .reduce((array: ModelFieldData[], val) => array.indexOf(val) >= 0 ? array : [...array, val], []); if (ids.length === 0) return []; const query = this.makeQuery(); @@ -82,7 +85,7 @@ export default abstract class ModelRelation): Promise { - this.cachedModels = models.filter(m => m[this.dbProperties.foreignKey] === this.getModelID()) + this.cachedModels = models.filter(m => m[this.dbProperties.foreignKey] === this.getModelId()) .reduce((array: O[], val) => array.find(v => v.equals(val)) ? array : [...array, val], []); } @@ -122,9 +125,13 @@ export class OneModelRelation extends ModelRel } export class ManyModelRelation extends ModelRelation { - protected readonly paginatedCache: { [perPage: number]: { [pageNumber: number]: ModelQueryResult } } = {}; + protected readonly paginatedCache: { + [perPage: number]: { + [pageNumber: number]: ModelQueryResult | undefined + } | undefined + } = {}; - constructor(model: S, foreignModelType: ModelType, dbProperties: RelationDatabaseProperties) { + public constructor(model: S, foreignModelType: ModelType, dbProperties: RelationDatabaseProperties) { super(model, foreignModelType, dbProperties); } @@ -141,29 +148,29 @@ export class ManyModelRelation extends ModelRe } public async paginate(page: number, perPage: number): Promise> { - if (!this.paginatedCache[perPage]) this.paginatedCache[perPage] = {}; + let cache = this.paginatedCache[perPage]; + if (!cache) cache = this.paginatedCache[perPage] = {}; - const cache = this.paginatedCache[perPage]; - - if (!cache[page]) { + let cachePage = cache[page]; + if (!cachePage) { const query = this.makeQuery(); this.applyRegularConstraints(query); - cache[page] = await query.paginate(page, perPage); + cachePage = cache[page] = await query.paginate(page, perPage); } - return cache[page]; + return cachePage; } } export class ManyThroughModelRelation extends ManyModelRelation { protected readonly dbProperties: PivotRelationDatabaseProperties; - constructor(model: S, foreignModelType: ModelType, dbProperties: PivotRelationDatabaseProperties) { + public constructor(model: S, foreignModelType: ModelType, dbProperties: PivotRelationDatabaseProperties) { super(model, foreignModelType, dbProperties); this.dbProperties = dbProperties; this.constraint(query => query .leftJoin(this.dbProperties.pivotTable, 'pivot') - .on(`pivot.${this.dbProperties.foreignPivotKey}`, `${this.foreignModelType.table}.${this.dbProperties.foreignKey}`) + .on(`pivot.${this.dbProperties.foreignPivotKey}`, `${this.foreignModelType.table}.${this.dbProperties.foreignKey}`), ); } @@ -176,12 +183,15 @@ export class ManyThroughModelRelation extends } protected applyRegularConstraints(query: ModelQuery): void { - query.where(`pivot.${this.dbProperties.localPivotKey}`, this.getModelID()); + query.where(`pivot.${this.dbProperties.localPivotKey}`, this.getModelId()); } - public async eagerLoad(relations: ModelRelation[], subRelations: string[] = []): Promise> { - const ids = relations.map(r => r.getModelID()) - .reduce((array: O[], val) => array.indexOf(val) >= 0 ? array : [...array, val], []); + public async eagerLoad( + relations: ModelRelation[], + subRelations: string[] = [], + ): Promise> { + const ids = relations.map(r => r.getModelId()) + .reduce((array: ModelFieldData[], val) => array.indexOf(val) >= 0 ? array : [...array, val], []); if (ids.length === 0) return []; const query = this.makeQuery(); @@ -192,8 +202,9 @@ export class ManyThroughModelRelation extends } public async populate(models: ModelQueryResult): Promise { - const ids = models.pivot! - .filter(p => p[`pivot.${this.dbProperties.localPivotKey}`] === this.getModelID()) + if (!models.pivot) throw new Error('ModelQueryResult.pivot not loaded.'); + const ids = models.pivot + .filter(p => p[`pivot.${this.dbProperties.localPivotKey}`] === this.getModelId()) .map(p => p[`pivot.${this.dbProperties.foreignPivotKey}`]); this.cachedModels = models.filter(m => ids.indexOf(m[this.dbProperties.foreignKey]) >= 0) .reduce((array: O[], val) => array.find(v => v.equals(val)) ? array : [...array, val], []); @@ -203,7 +214,12 @@ export class ManyThroughModelRelation extends export class RecursiveModelRelation extends ManyModelRelation { private readonly reverse: boolean; - public constructor(model: M, foreignModelType: ModelType, dbProperties: RelationDatabaseProperties, reverse: boolean = false) { + public constructor( + model: M, + foreignModelType: ModelType, + dbProperties: RelationDatabaseProperties, + reverse: boolean = false, + ) { super(model, foreignModelType, dbProperties); this.constraint(query => query.recursive(this.dbProperties, reverse)); this.reverse = reverse; @@ -215,17 +231,19 @@ export class RecursiveModelRelation extends ManyModelRelation): Promise { await super.populate(models); - if (this.cachedModels) { + const cachedModels = this.cachedModels; + if (cachedModels) { let count; do { - count = this.cachedModels.length; - this.cachedModels.push(...models.filter(model => - !this.cachedModels!.find(cached => cached.equals(model)) && - this.cachedModels!.find(cached => cached[this.dbProperties.localKey] === model[this.dbProperties.foreignKey]) + count = cachedModels.length; + cachedModels.push(...models.filter(model => + !cachedModels.find(cached => cached.equals(model)) && cachedModels.find(cached => { + return cached[this.dbProperties.localKey] === model[this.dbProperties.foreignKey]; + }), ).reduce((array: M[], val) => array.find(v => v.equals(val)) ? array : [...array, val], [])); - } while (count !== this.cachedModels.length); + } while (count !== cachedModels.length); - if (this.reverse) this.cachedModels!.reverse(); + if (this.reverse) cachedModels.reverse(); } } diff --git a/src/db/MysqlConnectionManager.ts b/src/db/MysqlConnectionManager.ts index 5c6e53a..ca39167 100644 --- a/src/db/MysqlConnectionManager.ts +++ b/src/db/MysqlConnectionManager.ts @@ -1,17 +1,21 @@ -import mysql, {Connection, FieldInfo, Pool} from 'mysql'; +import mysql, {Connection, FieldInfo, MysqlError, Pool, PoolConnection} from 'mysql'; import config from 'config'; -import Migration from "./Migration"; +import Migration, {MigrationType} from "./Migration"; import Logger from "../Logger"; import {Type} from "../Utils"; export interface QueryResult { - readonly results: any[]; + readonly results: Record[]; readonly fields: FieldInfo[]; - readonly other?: any; + readonly other?: Record; foundRows?: number; } -export async function query(queryString: string, values?: any, connection?: Connection): Promise { +export async function query( + queryString: string, + values?: QueryVariable[], + connection?: Connection, +): Promise { return await MysqlConnectionManager.query(queryString, values, connection); } @@ -25,7 +29,7 @@ export default class MysqlConnectionManager { return this.databaseReady && this.currentPool !== undefined; } - public static registerMigrations(migrations: Type[]) { + public static registerMigrations(migrations: MigrationType[]): void { if (!this.migrationsRegistered) { this.migrationsRegistered = true; migrations.forEach(m => this.registerMigration(v => new m(v))); @@ -36,14 +40,14 @@ export default class MysqlConnectionManager { this.migrations.push(migration(this.migrations.length + 1)); } - public static hasMigration(migration: Type) { + public static hasMigration(migration: Type): boolean { for (const m of this.migrations) { if (m.constructor === migration) return true; } return false; } - public static async prepare(runMigrations: boolean = true) { + public static async prepare(runMigrations: boolean = true): Promise { if (config.get('mysql.create_database_automatically') === true) { const dbName = config.get('mysql.database'); Logger.info(`Creating database ${dbName}...`); @@ -55,11 +59,9 @@ export default class MysqlConnectionManager { }); await new Promise((resolve, reject) => { connection.query(`CREATE DATABASE IF NOT EXISTS ${dbName}`, (error) => { - if (error !== null) { - reject(error); - } else { + return error !== null ? + reject(error) : resolve(); - } }); }); connection.end(); @@ -89,20 +91,24 @@ export default class MysqlConnectionManager { } public static async endPool(): Promise { - return new Promise(resolve => { - if (this.currentPool !== undefined) { - this.currentPool.end(() => { - Logger.info('Mysql connection pool ended.'); - resolve(); - }); - this.currentPool = undefined; - } else { - resolve(); + return await new Promise(resolve => { + if (this.currentPool === undefined) { + return resolve(); } + + this.currentPool.end(() => { + Logger.info('Mysql connection pool ended.'); + resolve(); + }); + this.currentPool = undefined; }); } - public static async query(queryString: string, values?: any, connection?: Connection): Promise { + public static async query( + queryString: string, + values: QueryVariable[] = [], + connection?: Connection, + ): Promise { return await new Promise((resolve, reject) => { Logger.dev('SQL:', Logger.isVerboseMode() ? mysql.format(queryString, values) : queryString); @@ -115,7 +121,7 @@ export default class MysqlConnectionManager { resolve({ results: Array.isArray(results) ? results : [], fields: fields !== undefined ? fields : [], - other: Array.isArray(results) ? null : results + other: Array.isArray(results) ? null : results, }); }); }); @@ -123,13 +129,13 @@ export default class MysqlConnectionManager { public static async wrapTransaction(transaction: (connection: Connection) => Promise): Promise { return await new Promise((resolve, reject) => { - this.pool.getConnection((err, connection) => { + this.pool.getConnection((err: MysqlError | undefined, connection: PoolConnection) => { if (err) { reject(err); return; } - connection.beginTransaction((err) => { + connection.beginTransaction((err?: MysqlError) => { if (err) { reject(err); this.pool.releaseConnection(connection); @@ -137,7 +143,7 @@ export default class MysqlConnectionManager { } transaction(connection).then(val => { - connection.commit((err) => { + connection.commit((err?: MysqlError) => { if (err) { this.rejectAndRollback(connection, err, reject); this.pool.releaseConnection(connection); @@ -156,13 +162,15 @@ export default class MysqlConnectionManager { }); } - private static rejectAndRollback(connection: Connection, err: any, reject: (err: any) => void) { - connection.rollback((rollbackErr) => { - if (rollbackErr) { - reject(err + '\n' + rollbackErr); - } else { + private static rejectAndRollback( + connection: Connection, + err: MysqlError | undefined, + reject: (err: unknown) => void, + ) { + connection.rollback((rollbackErr?: MysqlError) => { + return rollbackErr ? + reject(err + '\n' + rollbackErr) : reject(err); - } }); } @@ -171,7 +179,7 @@ export default class MysqlConnectionManager { try { const result = await query('SELECT id FROM migrations ORDER BY id DESC LIMIT 1'); - currentVersion = result.results[0].id; + currentVersion = Number(result.results[0]?.id); } catch (e) { if (e.code === 'ECONNREFUSED' || e.code !== 'ER_NO_SUCH_TABLE') { throw new Error('Cannot run migrations: ' + e.code); @@ -197,16 +205,16 @@ export default class MysqlConnectionManager { } for (const migration of this.migrations) { - migration.registerModels(); + migration.registerModels?.(); } } /** - * @param migrationID what migration to rollback. Use with caution. default=0 is for last registered migration. + * @param migrationId what migration to rollback. Use with caution. default=0 is for last registered migration. */ - public static async rollbackMigration(migrationID: number = 0): Promise { - migrationID--; - const migration = this.migrations[migrationID]; + public static async rollbackMigration(migrationId: number = 0): Promise { + migrationId--; + const migration = this.migrations[migrationId]; Logger.info('Rolling back migration ', migration.version, migration.constructor.name); await MysqlConnectionManager.wrapTransaction(async c => { await migration.rollback(c); @@ -220,12 +228,12 @@ export default class MysqlConnectionManager { for (let i = 0; i < args.length; i++) { if (args[i] === 'rollback') { - let migrationID = 0; + let migrationId = 0; if (args.length > i + 1) { - migrationID = parseInt(args[i + 1]); + migrationId = parseInt(args[i + 1]); } await this.prepare(false); - await this.rollbackMigration(migrationID); + await this.rollbackMigration(migrationId); return; } } @@ -233,4 +241,21 @@ export default class MysqlConnectionManager { await MysqlConnectionManager.endPool(); } } -} \ No newline at end of file +} + +export type QueryVariable = + | string + | number + | Date + | Buffer + | null + | undefined; + +export function isQueryVariable(value: unknown): value is QueryVariable { + return typeof value === "string" || + typeof value === 'number' || + value instanceof Date || + value instanceof Buffer || + value === null || + value === undefined; +} diff --git a/src/db/Validator.ts b/src/db/Validator.ts index b926bf6..b849452 100644 --- a/src/db/Validator.ts +++ b/src/db/Validator.ts @@ -1,20 +1,19 @@ -import Model from "./Model"; +import Model, {ModelType} from "./Model"; import ModelQuery, {WhereTest} from "./ModelQuery"; import {Connection} from "mysql"; -import {Type} from "../Utils"; import {ServerError} from "../HttpError"; export const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/; -export default class Validator { - private readonly steps: ValidationStep[] = []; +export default class Validator { + private readonly steps: ValidationStep[] = []; private readonly validationAttributes: string[] = []; - private readonly rawValueToHuman?: (val: T) => string; + private readonly rawValueToHuman?: (val: V) => string; private _min?: number; private _max?: number; - public constructor(rawValueToHuman?: (val: T) => string) { + public constructor(rawValueToHuman?: (val: V) => string) { this.rawValueToHuman = rawValueToHuman; } @@ -24,8 +23,13 @@ export default class Validator { * @param onlyFormat {@code true} to only validate format properties, {@code false} otherwise. * @param connection A connection to use in case of wrapped transactions. */ - async execute(thingName: string, value: T | undefined, onlyFormat: boolean, connection?: Connection): Promise { - const bag = new ValidationBag(); + public async execute( + thingName: string, + value: V | undefined, + onlyFormat: boolean, + connection?: Connection, + ): Promise { + const bag = new ValidationBag(); for (const step of this.steps) { if (onlyFormat && !step.isFormat) continue; @@ -41,7 +45,7 @@ export default class Validator { } if (result === false && step.throw) { - const error: ValidationError = step.throw(); + const error: ValidationError = step.throw(); error.rawValueToHuman = this.rawValueToHuman; error.thingName = thingName; error.value = value; @@ -57,7 +61,7 @@ export default class Validator { } } - public defined(): Validator { + public defined(): Validator { this.validationAttributes.push('required'); this.addStep({ @@ -68,17 +72,21 @@ export default class Validator { return this; } - public acceptUndefined(alsoAcceptEmptyString: boolean = false): Validator { + public acceptUndefined(alsoAcceptEmptyString: boolean = false): Validator { this.addStep({ verifyStep: () => true, throw: null, - interrupt: val => val === undefined || val === null || (alsoAcceptEmptyString && typeof val === 'string' && val.length === 0), + interrupt: val => { + return val === undefined || + val === null || + alsoAcceptEmptyString && typeof val === 'string' && val.length === 0; + }, isFormat: true, }); return this; } - public equals(other?: T): Validator { + public equals(other?: V): Validator { this.addStep({ verifyStep: val => val === other, throw: () => new BadValueValidationError(other), @@ -87,7 +95,7 @@ export default class Validator { return this; } - public sameAs(otherName?: string, other?: T): Validator { + public sameAs(otherName?: string, other?: V): Validator { this.addStep({ verifyStep: val => val === other, throw: () => new DifferentThanError(otherName), @@ -96,7 +104,7 @@ export default class Validator { return this; } - public regexp(regexp: RegExp): Validator { + public regexp(regexp: RegExp): Validator { this.validationAttributes.push(`pattern="${regexp}"`); this.addStep({ verifyStep: val => regexp.test(val), @@ -106,9 +114,9 @@ export default class Validator { return this; } - public length(length: number): Validator { + public length(length: number): Validator { this.addStep({ - verifyStep: val => (val).length === length, + verifyStep: val => isLenghtable(val) && val.length === length, throw: () => new BadLengthValidationError(length), isFormat: true, }); @@ -118,9 +126,9 @@ export default class Validator { /** * @param minLength included */ - public minLength(minLength: number): Validator { + public minLength(minLength: number): Validator { this.addStep({ - verifyStep: val => (val).length >= minLength, + verifyStep: val => isLenghtable(val) && val.length >= minLength, throw: () => new TooShortError(minLength), isFormat: true, }); @@ -130,9 +138,9 @@ export default class Validator { /** * @param maxLength included */ - public maxLength(maxLength: number): Validator { + public maxLength(maxLength: number): Validator { this.addStep({ - verifyStep: val => (val).length <= maxLength, + verifyStep: val => isLenghtable(val) && val.length <= maxLength, throw: () => new TooLongError(maxLength), isFormat: true, }); @@ -143,11 +151,11 @@ export default class Validator { * @param minLength included * @param maxLength included */ - public between(minLength: number, maxLength: number): Validator { + public between(minLength: number, maxLength: number): Validator { this.addStep({ verifyStep: val => { - const length = (val).length; - return length >= minLength && length <= maxLength; + return isLenghtable(val) && + val.length >= minLength && val.length <= maxLength; }, throw: () => new BadLengthValidationError(minLength, maxLength), isFormat: true, @@ -158,12 +166,12 @@ export default class Validator { /** * @param min included */ - public min(min: number): Validator { + public min(min: number): Validator { this.validationAttributes.push(`min="${min}"`); this._min = min; this.addStep({ verifyStep: val => { - return (val) >= min; + return typeof val === 'number' && val >= min; }, throw: () => new OutOfRangeValidationError(this._min, this._max), isFormat: true, @@ -174,12 +182,12 @@ export default class Validator { /** * @param max included */ - public max(max: number): Validator { + public max(max: number): Validator { this.validationAttributes.push(`max="${max}"`); this._max = max; this.addStep({ verifyStep: val => { - return (val) <= max; + return typeof val === 'number' && val <= max; }, throw: () => new OutOfRangeValidationError(this._min, this._max), isFormat: true, @@ -187,35 +195,46 @@ export default class Validator { return this; } - public unique(model: M | Type, foreignKey?: string, querySupplier?: () => ModelQuery): Validator { + public unique( + model: M | ModelType, + foreignKey?: string, + querySupplier?: () => ModelQuery, + ): Validator { this.addStep({ verifyStep: async (val, thingName, c) => { if (!foreignKey) foreignKey = thingName; let query: ModelQuery; if (querySupplier) { - query = querySupplier().where(foreignKey, val); + query = querySupplier(); } else { - query = (model instanceof Model ? model.constructor : model).select('').where(foreignKey, val); + query = (model instanceof Model ? >model.constructor : model).select(''); } - if (model instanceof Model && typeof model.id === 'number') query = query.where('id', model.id, WhereTest.NE); + query.where(foreignKey, val); + if (model instanceof Model && typeof model.id === 'number') + query = query.where('id', model.id, WhereTest.NE); return (await query.execute(c)).results.length === 0; }, - throw: () => new AlreadyExistsValidationError((model).table), + throw: () => new AlreadyExistsValidationError(model.table), isFormat: false, }); return this; } - public exists(modelClass: Function, foreignKey?: string): Validator { + public exists(modelType: ModelType, foreignKey?: string): Validator { this.addStep({ - verifyStep: async (val, thingName, c) => (await (modelClass).select('').where(foreignKey !== undefined ? foreignKey : thingName, val).execute(c)).results.length >= 1, - throw: () => new UnknownRelationValidationError((modelClass).table, foreignKey), + verifyStep: async (val, thingName, c) => { + const results = await modelType.select('') + .where(foreignKey !== undefined ? foreignKey : thingName, val) + .execute(c); + return results.results.length >= 1; + }, + throw: () => new UnknownRelationValidationError(modelType.table, foreignKey), isFormat: false, }); return this; } - private addStep(step: ValidationStep) { + private addStep(step: ValidationStep) { this.steps.push(step); } @@ -223,31 +242,31 @@ export default class Validator { return this.validationAttributes; } - public step(step: number): Validator { + public step(step: number): Validator { this.validationAttributes.push(`step="${step}"`); return this; } } -interface ValidationStep { - interrupt?: (val?: T) => boolean; +interface ValidationStep { + interrupt?: (val?: V) => boolean; - verifyStep(val: T | undefined, thingName: string, connection?: Connection): boolean | Promise; + verifyStep(val: V | undefined, thingName: string, connection?: Connection): boolean | Promise; - throw: ((val?: T) => ValidationError) | null; + throw: ((val?: V) => ValidationError) | null; readonly isFormat: boolean; } -export class ValidationBag extends Error { - private readonly errors: ValidationError[] = []; +export class ValidationBag extends Error { + private readonly errors: ValidationError[] = []; - public addMessage(err: ValidationError) { + public addMessage(err: ValidationError): void { if (!err.thingName) throw new Error('Null thing name'); this.errors.push(err); } - public addBag(otherBag: ValidationBag) { + public addBag(otherBag: ValidationBag): void { for (const error of otherBag.errors) { this.errors.push(error); } @@ -257,10 +276,10 @@ export class ValidationBag extends Error { return this.errors.length > 0; } - public getMessages(): { [p: string]: ValidationError } { - const messages: { [p: string]: ValidationError } = {}; + public getMessages(): { [p: string]: ValidationError } { + const messages: { [p: string]: ValidationError } = {}; for (const err of this.errors) { - messages[err.thingName!] = { + messages[err.thingName || 'unknown'] = { name: err.name, message: err.message, value: err.value, @@ -269,26 +288,26 @@ export class ValidationBag extends Error { return messages; } - public getErrors(): ValidationError[] { + public getErrors(): ValidationError[] { return this.errors; } } -export abstract class ValidationError extends Error { - public rawValueToHuman?: (val: any) => string; +export abstract class ValidationError extends Error { + public rawValueToHuman?: (val: V) => string; public thingName?: string; - public value?: any; + public value?: V; public get name(): string { return this.constructor.name; } } -export class BadLengthValidationError extends ValidationError { +export class BadLengthValidationError extends ValidationError { private readonly expectedLength: number; private readonly maxLength?: number; - constructor(expectedLength: number, maxLength?: number) { + public constructor(expectedLength: number, maxLength?: number) { super(); this.expectedLength = expectedLength; this.maxLength = maxLength; @@ -296,14 +315,14 @@ export class BadLengthValidationError extends ValidationError { public get message(): string { return `${this.thingName} expected length: ${this.expectedLength}${this.maxLength !== undefined ? ` to ${this.maxLength}` : ''}; ` + - `actual length: ${this.value.length}.`; + `actual length: ${isLenghtable(this.value) && this.value.length}.`; } } -export class TooShortError extends ValidationError { +export class TooShortError extends ValidationError { private readonly minLength: number; - constructor(minLength: number) { + public constructor(minLength: number) { super(); this.minLength = minLength; } @@ -313,10 +332,10 @@ export class TooShortError extends ValidationError { } } -export class TooLongError extends ValidationError { +export class TooLongError extends ValidationError { private readonly maxLength: number; - constructor(maxLength: number) { + public constructor(maxLength: number) { super(); this.maxLength = maxLength; } @@ -326,43 +345,43 @@ export class TooLongError extends ValidationError { } } -export class BadValueValidationError extends ValidationError { - private readonly expectedValue: any; +export class BadValueValidationError extends ValidationError { + private readonly expectedValue: V; - constructor(expectedValue: any) { + public constructor(expectedValue: V) { super(); this.expectedValue = expectedValue; } public get message(): string { - let expectedValue = this.expectedValue; - let actualValue = this.value; - if (this.rawValueToHuman) { - expectedValue = this.rawValueToHuman(expectedValue); - actualValue = this.rawValueToHuman(actualValue); + let expectedValue: string = String(this.expectedValue); + let actualValue: string = String(this.value); + if (this.rawValueToHuman && this.value) { + expectedValue = this.rawValueToHuman(this.expectedValue); + actualValue = this.rawValueToHuman(this.value); } - return `Expected: ${expectedValue}; got: ${actualValue}.` + return `Expected: ${expectedValue}; got: ${actualValue}.`; } } -export class DifferentThanError extends ValidationError { - private readonly otherName: any; +export class DifferentThanError extends ValidationError { + private readonly otherName?: string; - constructor(otherName: any) { + public constructor(otherName?: string) { super(); this.otherName = otherName; } public get message(): string { - return `This should be the same as ${this.otherName}.` + return `This should be the same as ${this.otherName}.`; } } -export class OutOfRangeValidationError extends ValidationError { +export class OutOfRangeValidationError extends ValidationError { private readonly min?: number; private readonly max?: number; - constructor(min?: number, max?: number) { + public constructor(min?: number, max?: number) { super(); this.min = min; this.max = max; @@ -374,32 +393,32 @@ export class OutOfRangeValidationError extends ValidationError { } else if (this.max === undefined) { return `${this.thingName} must be at least ${this.min}`; } - let min: any = this.min; - let max: any = this.max; + let min: string = String(this.min); + let max: string = String(this.max); if (this.rawValueToHuman) { - min = this.rawValueToHuman(min); - max = this.rawValueToHuman(max); + min = this.rawValueToHuman(this.min as unknown as V); + max = this.rawValueToHuman(this.max as unknown as V); } return `${this.thingName} must be between ${min} and ${max}.`; } } -export class InvalidFormatValidationError extends ValidationError { +export class InvalidFormatValidationError extends ValidationError { public get message(): string { return `"${this.value}" is not a valid ${this.thingName}.`; } } -export class UndefinedValueValidationError extends ValidationError { +export class UndefinedValueValidationError extends ValidationError { public get message(): string { return `${this.thingName} is required.`; } } -export class AlreadyExistsValidationError extends ValidationError { +export class AlreadyExistsValidationError extends ValidationError { private readonly table: string; - constructor(table: string) { + public constructor(table: string) { super(); this.table = table; } @@ -409,11 +428,11 @@ export class AlreadyExistsValidationError extends ValidationError { } } -export class UnknownRelationValidationError extends ValidationError { +export class UnknownRelationValidationError extends ValidationError { private readonly table: string; private readonly foreignKey?: string; - constructor(table: string, foreignKey?: string) { + public constructor(table: string, foreignKey?: string) { super(); this.table = table; this.foreignKey = foreignKey; @@ -424,15 +443,24 @@ export class UnknownRelationValidationError extends ValidationError { } } -export class FileError extends ValidationError { - private readonly m: string; +export class FileError extends ValidationError { + private readonly _message: string; - constructor(message: string) { + public constructor(message: string) { super(); - this.m = message; + this._message = message; } public get message(): string { - return `${this.m}`; + return `${this._message}`; } } + +export type Lengthable = { + length: number, +}; + +export function isLenghtable(value: unknown): value is Lengthable { + return value !== undefined && value !== null && + typeof (value as Lengthable).length === 'number'; +} diff --git a/src/helpers/BackendController.ts b/src/helpers/BackendController.ts index da754e0..f1901ee 100644 --- a/src/helpers/BackendController.ts +++ b/src/helpers/BackendController.ts @@ -39,9 +39,12 @@ export default class BackendController extends Controller { public routes(): void { this.get('/', this.getIndex, 'backend', RequireAuthMiddleware, RequireAdminMiddleware); if (User.isApprovalMode()) { - this.get('/accounts-approval', this.getAccountApproval, 'accounts-approval', RequireAuthMiddleware, RequireAdminMiddleware); - this.post('/accounts-approval/approve', this.postApproveAccount, 'approve-account', RequireAuthMiddleware, RequireAdminMiddleware); - this.post('/accounts-approval/reject', this.postRejectAccount, 'reject-account', RequireAuthMiddleware, RequireAdminMiddleware); + this.get('/accounts-approval', this.getAccountApproval, 'accounts-approval', + RequireAuthMiddleware, RequireAdminMiddleware); + this.post('/accounts-approval/approve', this.postApproveAccount, 'approve-account', + RequireAuthMiddleware, RequireAdminMiddleware); + this.post('/accounts-approval/reject', this.postRejectAccount, 'reject-account', + RequireAuthMiddleware, RequireAdminMiddleware); } } @@ -71,11 +74,11 @@ export default class BackendController extends Controller { account.as(UserApprovedComponent).approved = true; await account.save(); - if (email) { + if (email && email.email) { await new Mail(ACCOUNT_REVIEW_NOTICE_MAIL_TEMPLATE, { approved: true, link: config.get('base_url') + Controller.route('auth'), - }).send(email.email!); + }).send(email.email); } req.flash('success', `Account successfully approved.`); @@ -87,10 +90,10 @@ export default class BackendController extends Controller { await account.delete(); - if (email) { + if (email && email.email) { await new Mail(ACCOUNT_REVIEW_NOTICE_MAIL_TEMPLATE, { approved: false, - }).send(email.email!); + }).send(email.email); } req.flash('success', `Account successfully deleted.`); diff --git a/src/migrations/CreateLogsTable.ts b/src/migrations/CreateLogsTable.ts index b25c2fc..830e8ac 100644 --- a/src/migrations/CreateLogsTable.ts +++ b/src/migrations/CreateLogsTable.ts @@ -29,4 +29,4 @@ export default class CreateLogsTable extends Migration { public registerModels(): void { ModelFactory.register(Log); } -} \ No newline at end of file +} diff --git a/src/migrations/CreateMigrationsTable.ts b/src/migrations/CreateMigrationsTable.ts index 019a8c9..915321b 100644 --- a/src/migrations/CreateMigrationsTable.ts +++ b/src/migrations/CreateMigrationsTable.ts @@ -31,7 +31,4 @@ export default class CreateMigrationsTable extends Migration { public async rollback(connection: Connection): Promise { await this.query('DROP TABLE migrations', connection); } - - public registerModels(): void { - } -} \ No newline at end of file +} diff --git a/src/models/Log.ts b/src/models/Log.ts index b922cbe..1dc0430 100644 --- a/src/models/Log.ts +++ b/src/models/Log.ts @@ -1,6 +1,6 @@ import Model from "../db/Model"; import {LogLevel, LogLevelKeys} from "../Logger"; -import {bufferToUUID} from "../Utils"; +import {bufferToUuid} from "../Utils"; export default class Log extends Model { public readonly id?: number = undefined; @@ -26,15 +26,15 @@ export default class Log extends Model { return LogLevel[this.level]; } - public setLevel(level: LogLevelKeys) { - this.level = LogLevel[level]; + public setLevel(level: LogLevel): void { + this.level = level; } - public getLogID(): string | null { - return this.log_id ? bufferToUUID(this.log_id!) : null; + public getLogId(): string | null { + return this.log_id ? bufferToUuid(this.log_id) : null; } - public setLogID(buffer: Buffer) { + public setLogId(buffer: Buffer): void { this.log_id = buffer; } @@ -50,7 +50,7 @@ export default class Log extends Model { return this.error_stack || ''; } - public setError(error?: Error) { + public setError(error?: Error): void { if (!error) return; this.error_name = error.name; diff --git a/src/types/Express.d.ts b/src/types/Express.d.ts index 6764ea9..e73d653 100644 --- a/src/types/Express.d.ts +++ b/src/types/Express.d.ts @@ -1,10 +1,14 @@ import {Files} from "formidable"; import {Type} from "../Utils"; import Middleware from "../Middleware"; +import {FlashMessages} from "../components/SessionComponent"; declare global { namespace Express { export interface Request { + getSession(): Session; + + files: Files; @@ -13,15 +17,15 @@ declare global { as(type: Type): M; - flash(): { [key: string]: string[] }; + flash(): FlashMessages; - flash(message: string): any; + flash(message: string): unknown[]; - flash(event: string, message: any): any; + flash(event: string, message: string): void; } export interface Response { - redirectBack(defaultUrl?: string): any; + redirectBack(defaultUrl?: string): void; } } -} \ No newline at end of file +} diff --git a/test/CsrfProtectionComponent.test.ts b/test/CsrfProtectionComponent.test.ts index 992e36d..1d30a0d 100644 --- a/test/CsrfProtectionComponent.test.ts +++ b/test/CsrfProtectionComponent.test.ts @@ -8,12 +8,12 @@ useApp((addr, port) => { return app = new class extends TestApp { protected async init(): Promise { this.use(new class extends Controller { - routes(): void { - this.get('/', (req, res, next) => { + public routes(): void { + this.get('/', (req, res) => { res.render('test/csrf.njk'); }, 'csrf_test'); - this.post('/', (req, res, next) => { + this.post('/', (req, res) => { res.json({ status: 'ok', }); @@ -97,4 +97,4 @@ describe('Test CSRF protection', () => { .send({csrf: csrf}) .expect(200, done); }); -}); \ No newline at end of file +}); diff --git a/test/Model.test.ts b/test/Model.test.ts index 9e8e6f0..574ba10 100644 --- a/test/Model.test.ts +++ b/test/Model.test.ts @@ -43,9 +43,6 @@ class Author extends Model { localPivotKey: 'author_id', foreignPivotKey: 'role_id', }); - - protected init(): void { - } } class Role extends Model { @@ -59,17 +56,11 @@ class Role extends Model { localPivotKey: 'role_id', foreignPivotKey: 'permission_id', }); - - protected init(): void { - } } class Permission extends Model { public id?: number = undefined; public name?: string = undefined; - - protected init(): void { - } } class AuthorRole extends Model { @@ -133,12 +124,12 @@ beforeAll(async () => { postFactory, authorFactory, roleFactory, - permissionFactory + permissionFactory, ]) { - await MysqlConnectionManager.query(`DROP TABLE IF EXISTS ${(factory.table)}`); + await MysqlConnectionManager.query(`DROP TABLE IF EXISTS ${factory.table}`); } - await MysqlConnectionManager.query(`CREATE TABLE ${(fakeDummyModelModelFactory.table)}( + await MysqlConnectionManager.query(`CREATE TABLE ${fakeDummyModelModelFactory.table}( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(256), date DATETIME, @@ -146,24 +137,24 @@ beforeAll(async () => { PRIMARY KEY(id) )`); - await MysqlConnectionManager.query(`CREATE TABLE ${(authorFactory.table)}( + await MysqlConnectionManager.query(`CREATE TABLE ${authorFactory.table}( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(64), PRIMARY KEY(id) )`); - await MysqlConnectionManager.query(`CREATE TABLE ${(postFactory.table)}( + await MysqlConnectionManager.query(`CREATE TABLE ${postFactory.table}( id INT NOT NULL AUTO_INCREMENT, author_id INT NOT NULL, content VARCHAR(512), PRIMARY KEY(id), - FOREIGN KEY post_author_fk (author_id) REFERENCES ${(authorFactory.table)} (id) + FOREIGN KEY post_author_fk (author_id) REFERENCES ${authorFactory.table} (id) )`); - await MysqlConnectionManager.query(`CREATE TABLE ${(roleFactory.table)}( + await MysqlConnectionManager.query(`CREATE TABLE ${roleFactory.table}( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(64), PRIMARY KEY(id) )`); - await MysqlConnectionManager.query(`CREATE TABLE ${(permissionFactory.table)}( + await MysqlConnectionManager.query(`CREATE TABLE ${permissionFactory.table}( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(64), PRIMARY KEY(id) @@ -174,16 +165,16 @@ beforeAll(async () => { author_id INT NOT NULL, role_id INT NOT NULL, PRIMARY KEY(id), - FOREIGN KEY author_role_author_fk (author_id) REFERENCES ${(authorFactory.table)} (id), - FOREIGN KEY author_role_role_fk (role_id) REFERENCES ${(roleFactory.table)} (id) + FOREIGN KEY author_role_author_fk (author_id) REFERENCES ${authorFactory.table} (id), + FOREIGN KEY author_role_role_fk (role_id) REFERENCES ${roleFactory.table} (id) )`); await MysqlConnectionManager.query(`CREATE TABLE role_permission( id INT NOT NULL AUTO_INCREMENT, role_id INT NOT NULL, permission_id INT NOT NULL, PRIMARY KEY(id), - FOREIGN KEY role_permission_role_fk (role_id) REFERENCES ${(roleFactory.table)} (id), - FOREIGN KEY role_permission_permission_fk (permission_id) REFERENCES ${(permissionFactory.table)} (id) + FOREIGN KEY role_permission_role_fk (role_id) REFERENCES ${roleFactory.table} (id), + FOREIGN KEY role_permission_permission_fk (permission_id) REFERENCES ${permissionFactory.table} (id) )`); @@ -289,10 +280,10 @@ describe('Model', () => { // Check that row exists in DB const retrievedInstance = await FakeDummyModel.getById(1); expect(retrievedInstance).toBeDefined(); - expect(retrievedInstance!.id).toBe(1); - expect(retrievedInstance!.name).toBe('name1'); - expect(retrievedInstance!.date?.getTime()).toBeCloseTo(date.getTime(), -4); - expect(retrievedInstance!.date_default).toBeDefined(); + expect(retrievedInstance?.id).toBe(1); + expect(retrievedInstance?.name).toBe('name1'); + expect(retrievedInstance?.date?.getTime()).toBeCloseTo(date.getTime(), -4); + expect(retrievedInstance?.date_default).toBeDefined(); const failingInsertModel = fakeDummyModelModelFactory.create({ name: 'a', @@ -308,17 +299,19 @@ describe('Model', () => { const preUpdatedModel = await FakeDummyModel.getById(insertModel.id); expect(preUpdatedModel).not.toBeNull(); - expect(preUpdatedModel!.name).toBe(insertModel.name); + expect(preUpdatedModel?.name).toBe(insertModel.name); // Update model - preUpdatedModel!.name = 'updated_name'; - await preUpdatedModel!.save(); + if (preUpdatedModel) { + preUpdatedModel.name = 'updated_name'; + await preUpdatedModel.save(); + } const postUpdatedModel = await FakeDummyModel.getById(insertModel.id); expect(postUpdatedModel).not.toBeNull(); - expect(postUpdatedModel!.id).toBe(insertModel.id); - expect(postUpdatedModel!.name).not.toBe(insertModel.name); - expect(postUpdatedModel!.name).toBe(preUpdatedModel!.name); + expect(postUpdatedModel?.id).toBe(insertModel.id); + expect(postUpdatedModel?.name).not.toBe(insertModel.name); + expect(postUpdatedModel?.name).toBe(preUpdatedModel?.name); }); it('should delete properly', async () => { @@ -330,7 +323,7 @@ describe('Model', () => { const preDeleteModel = await FakeDummyModel.getById(insertModel.id); expect(preDeleteModel).not.toBeNull(); - await preDeleteModel!.delete(); + await preDeleteModel?.delete(); const postDeleteModel = await FakeDummyModel.getById(insertModel.id); expect(postDeleteModel).toBeNull(); @@ -359,21 +352,28 @@ describe('ModelRelation', () => { expect(posts.length).toBe(3); - async function testPost(post: Post, originalPost: Post, expectedAuthor: Author, expectedRoles: Role[], expectedPermissions: Permission[]) { - console.log('Testing post', post) + async function testPost( + post: Post, + originalPost: Post, + expectedAuthor: Author, + expectedRoles: Role[], + expectedPermissions: Permission[], + ) { + console.log('Testing post', post); expect(post.id).toBe(originalPost.id); expect(post.content).toBe(originalPost.content); const actualAuthor = await post.author.get(); - expect(actualAuthor).not.toBeNull() + expect(actualAuthor).not.toBeNull(); expect(await post.author.has(expectedAuthor)).toBeTruthy(); - expect(actualAuthor!.equals(expectedAuthor)).toBe(true); + expect(actualAuthor?.equals(expectedAuthor)).toBe(true); - const authorRoles = await actualAuthor!.roles.get(); + const authorRoles = await actualAuthor?.roles.get() || []; console.log('Roles:'); expect(authorRoles.map(r => r.id)).toStrictEqual(expectedRoles.map(r => r.id)); - const authorPermissions = (await Promise.all(authorRoles.map(async r => await r.permissions.get()))).flatMap(p => p); + const authorPermissions = (await Promise.all(authorRoles.map(async r => await r.permissions.get()))) + .flatMap(p => p); console.log('Permissions:'); expect(authorPermissions.map(p => p.id)).toStrictEqual(expectedPermissions.map(p => p.id)); } diff --git a/test/ModelQuery.test.ts b/test/ModelQuery.test.ts index dae8ddf..4b2f199 100644 --- a/test/ModelQuery.test.ts +++ b/test/ModelQuery.test.ts @@ -31,7 +31,11 @@ describe('Test ModelQuery', () => { }); test('function select', () => { - const query = ModelQuery.select({table: 'model'} as unknown as ModelFactory, 'f1', new SelectFieldValue('_count', 'COUNT(*)', true)); + const query = ModelQuery.select( + {table: 'model'} as unknown as ModelFactory, + 'f1', + new SelectFieldValue('_count', 'COUNT(*)', true), + ); expect(query.toString(true)).toBe('SELECT `model`.`f1`,(COUNT(*)) AS `_count` FROM `model`'); expect(query.variables).toStrictEqual([]); }); @@ -81,6 +85,6 @@ describe('Test ModelQuery', () => { query.union(query2, 'model.f1', 'DESC', false, 8); expect(query.toString(true)).toBe("(SELECT `model`.* FROM `model`) UNION (SELECT `model2`.* FROM `model2` WHERE `f2`=?) ORDER BY `model`.`f1` DESC LIMIT 8"); - expect(query.variables).toStrictEqual(['v2']) + expect(query.variables).toStrictEqual(['v2']); }); }); diff --git a/test/_app.ts b/test/_app.ts index 09d0ba9..8f38fc5 100644 --- a/test/_app.ts +++ b/test/_app.ts @@ -1,7 +1,6 @@ import {setupMailServer, teardownMailServer} from "./_mail_server"; import Application from "../src/Application"; -import Migration from "../src/db/Migration"; -import {Type} from "../src/Utils"; +import Migration, {MigrationType} from "../src/db/Migration"; import {MIGRATIONS} from "./_migrations"; import ExpressAppComponent from "../src/components/ExpressAppComponent"; import RedisComponent from "../src/components/RedisComponent"; @@ -17,8 +16,9 @@ import FormHelperComponent from "../src/components/FormHelperComponent"; import RedirectBackComponent from "../src/components/RedirectBackComponent"; import ServeStaticDirectoryComponent from "../src/components/ServeStaticDirectoryComponent"; import {Express} from "express"; +import packageJson = require('../package.json'); -export default function useApp(appSupplier?: (addr: string, port: number) => TestApp) { +export default function useApp(appSupplier?: (addr: string, port: number) => TestApp): void { let app: Application; beforeAll(async (done) => { @@ -30,8 +30,21 @@ export default function useApp(appSupplier?: (addr: string, port: number) => Tes }); afterAll(async (done) => { - await app.stop(); - await teardownMailServer(); + const errors = []; + + try { + await app.stop(); + } catch (e) { + errors.push(e); + } + + try { + await teardownMailServer(); + } catch (e) { + errors.push(e); + } + + if (errors.length > 0) throw errors; done(); }); } @@ -41,23 +54,23 @@ export class TestApp extends Application { private readonly port: number; private expressAppComponent?: ExpressAppComponent; - constructor(addr: string, port: number) { - super(require('../package.json').version, true); + public constructor(addr: string, port: number) { + super(packageJson.version, true); this.addr = addr; this.port = port; } - protected getMigrations(): Type[] { + protected getMigrations(): MigrationType[] { return MIGRATIONS; } protected async init(): Promise { this.registerComponents(); - this.registerWebSocketListeners(); - this.registerControllers(); + this.registerWebSocketListeners?.(); + this.registerControllers?.(); } - protected registerComponents() { + protected registerComponents(): void { this.expressAppComponent = new ExpressAppComponent(this.addr, this.port); const redisComponent = new RedisComponent(); const mysqlComponent = new MysqlComponent(); @@ -84,7 +97,7 @@ export class TestApp extends Application { // Auth this.use(new AuthComponent(new class extends AuthGuard { public async getProofForSession(session: Express.Session): Promise { - return await MagicLink.bySessionID(session.id, ['login', 'register']); + return await MagicLink.bySessionId(session.id, ['login', 'register']); } })); @@ -92,15 +105,11 @@ export class TestApp extends Application { this.use(new FormHelperComponent()); } - protected registerWebSocketListeners() { - } + protected registerWebSocketListeners?(): void; - protected registerControllers() { - } + protected registerControllers?(): void; public getExpressApp(): Express { - return this.expressAppComponent!.getExpressApp(); + return this.as(ExpressAppComponent).getExpressApp(); } } - -export const DEFAULT_ADDR = 'http://localhost:8966'; \ No newline at end of file diff --git a/test/_mail_server.ts b/test/_mail_server.ts index da2110d..9c914f6 100644 --- a/test/_mail_server.ts +++ b/test/_mail_server.ts @@ -1,19 +1,19 @@ -const MailDev = require("maildev"); +import MailDev from "maildev"; export const MAIL_SERVER = new MailDev({ ip: 'localhost', }); -export async function setupMailServer() { - await new Promise((resolve, reject) => MAIL_SERVER.listen((err: Error) => { +export async function setupMailServer(): Promise { + await new Promise((resolve, reject) => MAIL_SERVER.listen((err?: Error) => { if (err) reject(err); else resolve(); })); -}; +} -export async function teardownMailServer() { - await new Promise((resolve, reject) => MAIL_SERVER.close((err: Error) => { +export async function teardownMailServer(): Promise { + await new Promise((resolve, reject) => MAIL_SERVER.close((err?: Error) => { if (err) reject(err); else resolve(); })); -}; \ No newline at end of file +} diff --git a/test/_migrations.ts b/test/_migrations.ts index 7611f2a..eb8fffe 100644 --- a/test/_migrations.ts +++ b/test/_migrations.ts @@ -12,4 +12,4 @@ export const MIGRATIONS = [ FixUserMainEmailRelation, DropNameFromUsers, CreateMagicLinksTable, -]; \ No newline at end of file +]; diff --git a/test/types/maildev.d.ts b/test/types/maildev.d.ts new file mode 100644 index 0000000..05570f3 --- /dev/null +++ b/test/types/maildev.d.ts @@ -0,0 +1,216 @@ +// Type definitions for maildev 1.0.0-rc3 +// Project: https://github.com/djfarrelly/maildev +// Definitions by: Cyril Schumacher +// Zak Barbuto +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +declare module 'maildev' { + import fs = require("fs"); + + /** + * Interface for {@link MailDev}. + */ + export default class MailDev { + /** + * Constructor. + * + * @public + * @param {MailDevOptions} options The options. + */ + public constructor(options: MailDevOptions); + + /** + * Deletes a given email by identifier. + * + * @public + * @param {string} id The email identifier. + * @param {Function} callback The error callback. + */ + public deleteEmail(id: string, callback?: (error: Error) => void): void; + + /** + * Deletes all email and their attachments. + * + * @public + * @param {Function} callback The error callback. + */ + public deleteAllEmail(callback?: (error: Error) => void): void; + + /** + * Stops the SMTP server. + * + * @public + * @param {Function} callback The error callback. + */ + public close(callback?: (error: Error) => void): void; + + /** + * Accepts e-mail identifier, returns email object. + * + * @public + * @param {string} id The e-mail identifier. + * @param {Function} callback The error callback. + */ + public getEmail(id: string, callback?: (error: Error) => void): void; + + /** + * Returns a readable stream of the raw e-mail. + * + * @public + * @param {string} id The e-mail identifier. + */ + public getRawEmail(id: string, callback?: (error: Error, readStream: fs.ReadStream) => void): void; + + /** + * Returns array of all e-mail. + + * @public + */ + public getAllEmail(done: (error: Error, emails: Array>) => void): void; + + /** + * Starts the SMTP server. + * + * @public + * @param {Function} callback The error callback. + */ + public listen(callback?: (error: Error) => void): void; + + /** + * Event called when a new e-mail is received. Callback receives single mail object. + * + * @public + * @param {string} eventName The event name. + * @param {Function} email The email. + */ + public on(eventName: string, callback: (email: Record) => void): void; + + /** + * Relay the e-mail. + * + * @param {string} idOrMailObject The identifier or mail object. + * @param {Function} done The callback. + */ + public relayMail(idOrMailObject: string, done: (error: Error) => void): void; + } + + /** + * Interface for {@link MailDev} options. + */ + export interface MailDevOptions { + /** + * IP Address to bind SMTP service to', '0.0.0.0' + * + * @type {string} + */ + ip?: string; + + /** + * SMTP host for outgoing emails + * + * @type {string} + */ + outgoingHost?: string; + + /** + * SMTP password for outgoing emails + * + * @type {string} + */ + outgoingPass?: string; + + /** + * SMTP port for outgoing emails. + * + * @type {number} + */ + outgoingPort?: number; + + /** + * SMTP user for outgoing emails + * + * @type {string} + */ + outgoingUser?: string; + + /** + * Use SMTP SSL for outgoing emails + * + * @type {boolean} + */ + outgoingSecure?: boolean; + + /** + * SMTP port to catch emails. + * + * @type {number} + */ + smtp?: number; + + /** + * Port to use for web UI + * + * @type {number} + */ + web?: number; + + /** + * IP Address to bind HTTP service to + * + * @type {string} + */ + webIp?: string; + + /** + * Do not start web UI + * + * @type {boolean} + */ + disableWeb?: boolean; + + /** + * Do not output console.log messages + * + * @type {boolean} + */ + silent?: boolean; + + /** + * HTTP user for GUI + * + * @type {string} + */ + webUser?: string; + + /** + * HTTP password for GUI + * + * @type {string} + */ + webPass?: string; + + /** + * Open the Web GUI after startup + * + * @type {boolean} + */ + open?: boolean; + } + + /** + * Interface for mail. + */ + export interface Mail { + /** + * Identifier. + */ + id?: string; + + /** + * Client. + */ + envelope?: Record; + } +} diff --git a/test/views/test/csrf.njk b/test/views/test/csrf.njk index 1df1416..7322da1 100644 --- a/test/views/test/csrf.njk +++ b/test/views/test/csrf.njk @@ -1 +1 @@ -{{ getCSRFToken() }} \ No newline at end of file +{{ getCsrfToken() }} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index bebdd64..f34d0e9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,8 +6,6 @@ "stripInternal": true, "strict": true, - // "noUnusedLocals": true, - // "noUnusedParameters": true, "allowSyntheticDefaultImports": true, "moduleResolution": "Node", diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 0000000..897a6b4 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "typeRoots": [ + "node_modules/@types", + "src/types", + "test/types" + ] + }, + "include": [ + "src/types/**/*", + "test/**/*" + ] +} \ No newline at end of file diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo deleted file mode 100644 index acc04c6..0000000 --- a/tsconfig.tsbuildinfo +++ /dev/null @@ -1,3132 +0,0 @@ -{ - "program": { - "fileInfos": { - "./node_modules/typescript/lib/lib.es5.d.ts": { - "version": "b42eddba1a53c9d27279cfe7fc0416c10a81489826ad47e39013b9d340fc0cc7", - "signature": "b42eddba1a53c9d27279cfe7fc0416c10a81489826ad47e39013b9d340fc0cc7" - }, - "./node_modules/typescript/lib/lib.es2015.d.ts": { - "version": "7994d44005046d1413ea31d046577cdda33b8b2470f30281fd9c8b3c99fe2d96", - "signature": "7994d44005046d1413ea31d046577cdda33b8b2470f30281fd9c8b3c99fe2d96" - }, - "./node_modules/typescript/lib/lib.es2016.d.ts": { - "version": "5f217838d25704474d9ef93774f04164889169ca31475fe423a9de6758f058d1", - "signature": "5f217838d25704474d9ef93774f04164889169ca31475fe423a9de6758f058d1" - }, - "./node_modules/typescript/lib/lib.es2017.d.ts": { - "version": "459097c7bdd88fc5731367e56591e4f465f2c9de81a35427a7bd473165c34743", - "signature": "459097c7bdd88fc5731367e56591e4f465f2c9de81a35427a7bd473165c34743" - }, - "./node_modules/typescript/lib/lib.es2018.d.ts": { - "version": "9c67dcc7ca897b61f58d57d487bc9f07950546e5ac8701cbc41a8a4fec48b091", - "signature": "9c67dcc7ca897b61f58d57d487bc9f07950546e5ac8701cbc41a8a4fec48b091" - }, - "./node_modules/typescript/lib/lib.es2019.d.ts": { - "version": "0fc0f68d3f4d94aa65fab955592e4a9f2066e6f8ee2f66fcc45adf4037fc167b", - "signature": "0fc0f68d3f4d94aa65fab955592e4a9f2066e6f8ee2f66fcc45adf4037fc167b" - }, - "./node_modules/typescript/lib/lib.es2020.d.ts": { - "version": "585694acba05fe18d6ad9c9f662f3de3766779933efb9f2d8c482c1a92bf073c", - "signature": "585694acba05fe18d6ad9c9f662f3de3766779933efb9f2d8c482c1a92bf073c" - }, - "./node_modules/typescript/lib/lib.es2015.core.d.ts": { - "version": "734ddc145e147fbcd55f07d034f50ccff1086f5a880107665ec326fb368876f6", - "signature": "734ddc145e147fbcd55f07d034f50ccff1086f5a880107665ec326fb368876f6" - }, - "./node_modules/typescript/lib/lib.es2015.collection.d.ts": { - "version": "4a0862a21f4700de873db3b916f70e41570e2f558da77d2087c9490f5a0615d8", - "signature": "4a0862a21f4700de873db3b916f70e41570e2f558da77d2087c9490f5a0615d8" - }, - "./node_modules/typescript/lib/lib.es2015.generator.d.ts": { - "version": "765e0e9c9d74cf4d031ca8b0bdb269a853e7d81eda6354c8510218d03db12122", - "signature": "765e0e9c9d74cf4d031ca8b0bdb269a853e7d81eda6354c8510218d03db12122" - }, - "./node_modules/typescript/lib/lib.es2015.iterable.d.ts": { - "version": "285958e7699f1babd76d595830207f18d719662a0c30fac7baca7df7162a9210", - "signature": "285958e7699f1babd76d595830207f18d719662a0c30fac7baca7df7162a9210" - }, - "./node_modules/typescript/lib/lib.es2015.promise.d.ts": { - "version": "d4deaafbb18680e3143e8b471acd650ed6f72a408a33137f0a0dd104fbe7f8ca", - "signature": "d4deaafbb18680e3143e8b471acd650ed6f72a408a33137f0a0dd104fbe7f8ca" - }, - "./node_modules/typescript/lib/lib.es2015.proxy.d.ts": { - "version": "5e72f949a89717db444e3bd9433468890068bb21a5638d8ab15a1359e05e54fe", - "signature": "5e72f949a89717db444e3bd9433468890068bb21a5638d8ab15a1359e05e54fe" - }, - "./node_modules/typescript/lib/lib.es2015.reflect.d.ts": { - "version": "f5b242136ae9bfb1cc99a5971cccc44e99947ae6b5ef6fd8aa54b5ade553b976", - "signature": "f5b242136ae9bfb1cc99a5971cccc44e99947ae6b5ef6fd8aa54b5ade553b976" - }, - "./node_modules/typescript/lib/lib.es2015.symbol.d.ts": { - "version": "9ae2860252d6b5f16e2026d8a2c2069db7b2a3295e98b6031d01337b96437230", - "signature": "9ae2860252d6b5f16e2026d8a2c2069db7b2a3295e98b6031d01337b96437230" - }, - "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts": { - "version": "3e0a459888f32b42138d5a39f706ff2d55d500ab1031e0988b5568b0f67c2303", - "signature": "3e0a459888f32b42138d5a39f706ff2d55d500ab1031e0988b5568b0f67c2303" - }, - "./node_modules/typescript/lib/lib.es2016.array.include.d.ts": { - "version": "3f96f1e570aedbd97bf818c246727151e873125d0512e4ae904330286c721bc0", - "signature": "3f96f1e570aedbd97bf818c246727151e873125d0512e4ae904330286c721bc0" - }, - "./node_modules/typescript/lib/lib.es2017.object.d.ts": { - "version": "c2d60b2e558d44384e4704b00e6b3d154334721a911f094d3133c35f0917b408", - "signature": "c2d60b2e558d44384e4704b00e6b3d154334721a911f094d3133c35f0917b408" - }, - "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts": { - "version": "b8667586a618c5cf64523d4e500ae39e781428abfb28f3de441fc66b56144b6f", - "signature": "b8667586a618c5cf64523d4e500ae39e781428abfb28f3de441fc66b56144b6f" - }, - "./node_modules/typescript/lib/lib.es2017.string.d.ts": { - "version": "21df2e0059f14dcb4c3a0e125859f6b6ff01332ee24b0065a741d121250bc71c", - "signature": "21df2e0059f14dcb4c3a0e125859f6b6ff01332ee24b0065a741d121250bc71c" - }, - "./node_modules/typescript/lib/lib.es2017.intl.d.ts": { - "version": "c1759cb171c7619af0d2234f2f8fb2a871ee88e956e2ed91bb61778e41f272c6", - "signature": "c1759cb171c7619af0d2234f2f8fb2a871ee88e956e2ed91bb61778e41f272c6" - }, - "./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts": { - "version": "28569d59e07d4378cb3d54979c4c60f9f06305c9bb6999ffe6cab758957adc46", - "signature": "28569d59e07d4378cb3d54979c4c60f9f06305c9bb6999ffe6cab758957adc46" - }, - "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts": { - "version": "2958de3d25bfb0b5cdace0244e11c9637e5988920b99024db705a720ce6348e7", - "signature": "2958de3d25bfb0b5cdace0244e11c9637e5988920b99024db705a720ce6348e7" - }, - "./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts": { - "version": "85085a0783532dc04b66894748dc4a49983b2fbccb0679b81356947021d7a215", - "signature": "85085a0783532dc04b66894748dc4a49983b2fbccb0679b81356947021d7a215" - }, - "./node_modules/typescript/lib/lib.es2018.intl.d.ts": { - "version": "5494f46d3a8a0329d13ddc37f8759d5288760febb51c92336608d1c06bb18d29", - "signature": "5494f46d3a8a0329d13ddc37f8759d5288760febb51c92336608d1c06bb18d29" - }, - "./node_modules/typescript/lib/lib.es2018.promise.d.ts": { - "version": "efe049114bad1035b0aa9a4a0359f50ab776e3897c411521e51d3013079cbd62", - "signature": "efe049114bad1035b0aa9a4a0359f50ab776e3897c411521e51d3013079cbd62" - }, - "./node_modules/typescript/lib/lib.es2018.regexp.d.ts": { - "version": "e7780d04cd4120ee554c665829db2bbdd6b947cbaa3c150b7d9ea74df3beb2e8", - "signature": "e7780d04cd4120ee554c665829db2bbdd6b947cbaa3c150b7d9ea74df3beb2e8" - }, - "./node_modules/typescript/lib/lib.es2019.array.d.ts": { - "version": "7054111c49ea06f0f2e623eab292a9c1ae9b7d04854bd546b78f2b8b57e13d13", - "signature": "7054111c49ea06f0f2e623eab292a9c1ae9b7d04854bd546b78f2b8b57e13d13" - }, - "./node_modules/typescript/lib/lib.es2019.object.d.ts": { - "version": "989b95205f1189943fab0ce12a39c80570edf8f200aca60e0fdc500afc4d5859", - "signature": "989b95205f1189943fab0ce12a39c80570edf8f200aca60e0fdc500afc4d5859" - }, - "./node_modules/typescript/lib/lib.es2019.string.d.ts": { - "version": "e9bfd234b801c955459cde7109bebf6fd1b4814fd8b394942f5ba746828a6486", - "signature": "e9bfd234b801c955459cde7109bebf6fd1b4814fd8b394942f5ba746828a6486" - }, - "./node_modules/typescript/lib/lib.es2019.symbol.d.ts": { - "version": "5f2a476cdb4990b249077b46a6242979876e9bba5152e066d68fad77510ee328", - "signature": "5f2a476cdb4990b249077b46a6242979876e9bba5152e066d68fad77510ee328" - }, - "./node_modules/typescript/lib/lib.es2020.bigint.d.ts": { - "version": "0c9ea8c2028047f39a3f66752682604f543c08be8806258c3d95c93e75a43255", - "signature": "0c9ea8c2028047f39a3f66752682604f543c08be8806258c3d95c93e75a43255" - }, - "./node_modules/typescript/lib/lib.es2020.promise.d.ts": { - "version": "4a44be5b17ae6385fcc9a486361f50231992d556c9298373ae0d38cfae9f4056", - "signature": "4a44be5b17ae6385fcc9a486361f50231992d556c9298373ae0d38cfae9f4056" - }, - "./node_modules/typescript/lib/lib.es2020.string.d.ts": { - "version": "01f1170ac78a31964a8a05cc46df7dc63d6911f683cb49586b27c49f54187a86", - "signature": "01f1170ac78a31964a8a05cc46df7dc63d6911f683cb49586b27c49f54187a86" - }, - "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts": { - "version": "1debec13dc47b66e7e5a5ceb3872ea7f141613148f6083ef6dc38626ee8c9a93", - "signature": "1debec13dc47b66e7e5a5ceb3872ea7f141613148f6083ef6dc38626ee8c9a93" - }, - "./node_modules/typescript/lib/lib.esnext.intl.d.ts": { - "version": "1377923021927244ea19433873b997ad8585533b0a56d5de29cda497f7842756", - "signature": "1377923021927244ea19433873b997ad8585533b0a56d5de29cda497f7842756" - }, - "./node_modules/@types/node/globals.d.ts": { - "version": "9d0b32c595a2e0d320a56b3d0e8f0a317e4149239ec913aa8f11eeb73edc92be", - "signature": "9d0b32c595a2e0d320a56b3d0e8f0a317e4149239ec913aa8f11eeb73edc92be" - }, - "./node_modules/@types/node/async_hooks.d.ts": { - "version": "96e547b51f95ee76bdb25731c92420fa6f93b59c3f38f23d505be36e2de394ee", - "signature": "96e547b51f95ee76bdb25731c92420fa6f93b59c3f38f23d505be36e2de394ee" - }, - "./node_modules/@types/node/buffer.d.ts": { - "version": "61215c1a376bbe8f51cab4cc4ddbf3746387015113c37a84d981d4738c21b878", - "signature": "61215c1a376bbe8f51cab4cc4ddbf3746387015113c37a84d981d4738c21b878" - }, - "../node_modules/@types/events/index.d.ts": { - "version": "400db42c3a46984118bff14260d60cec580057dc1ab4c2d7310beb643e4f5935", - "signature": "400db42c3a46984118bff14260d60cec580057dc1ab4c2d7310beb643e4f5935" - }, - "./node_modules/@types/node/child_process.d.ts": { - "version": "3ca89ecb953fe3b63dae41e5bb986506e812754dde0369c5fe61de26eff47dbe", - "signature": "3ca89ecb953fe3b63dae41e5bb986506e812754dde0369c5fe61de26eff47dbe" - }, - "./node_modules/@types/node/cluster.d.ts": { - "version": "123ec69e4b3a686eb49afd94ebe3292a5c84a867ecbcb6bb84bdd720a12af803", - "signature": "123ec69e4b3a686eb49afd94ebe3292a5c84a867ecbcb6bb84bdd720a12af803" - }, - "./node_modules/@types/node/console.d.ts": { - "version": "525c8fc510d9632d2a0a9de2d41c3ac1cdd79ff44d3b45c6d81cacabb683528d", - "signature": "525c8fc510d9632d2a0a9de2d41c3ac1cdd79ff44d3b45c6d81cacabb683528d" - }, - "./node_modules/@types/node/constants.d.ts": { - "version": "90c85ddbb8de82cd19198bda062065fc51b7407c0f206f2e399e65a52e979720", - "signature": "90c85ddbb8de82cd19198bda062065fc51b7407c0f206f2e399e65a52e979720" - }, - "./node_modules/@types/node/crypto.d.ts": { - "version": "d56c93b6bf66e602869e926ddc8b1b4630d1ff397909291767d18d4ffc22d33f", - "signature": "d56c93b6bf66e602869e926ddc8b1b4630d1ff397909291767d18d4ffc22d33f" - }, - "./node_modules/@types/node/dgram.d.ts": { - "version": "7ecfe97b43aa6c8b8f90caa599d5648bb559962e74e6f038f73a77320569dd78", - "signature": "7ecfe97b43aa6c8b8f90caa599d5648bb559962e74e6f038f73a77320569dd78" - }, - "./node_modules/@types/node/dns.d.ts": { - "version": "aad3237c3f99480041cad7ca04d64307c98933996f822342b7c0ee4a78553346", - "signature": "aad3237c3f99480041cad7ca04d64307c98933996f822342b7c0ee4a78553346" - }, - "./node_modules/@types/node/domain.d.ts": { - "version": "4d4c83f77ac21a72252785baa5328a5612b0b6598d512f68b8cb14f7966d059e", - "signature": "4d4c83f77ac21a72252785baa5328a5612b0b6598d512f68b8cb14f7966d059e" - }, - "./node_modules/@types/node/events.d.ts": { - "version": "5ffa4219ee64e130980a4231392cbc628544df137ccf650ae8d76e0a1744fd2b", - "signature": "5ffa4219ee64e130980a4231392cbc628544df137ccf650ae8d76e0a1744fd2b" - }, - "./node_modules/@types/node/fs.d.ts": { - "version": "e1a12c7e7951b9762cfbcc43c72eb5611120967706a7c3142ad303c6b7ee767f", - "signature": "e1a12c7e7951b9762cfbcc43c72eb5611120967706a7c3142ad303c6b7ee767f" - }, - "./node_modules/@types/node/http.d.ts": { - "version": "b5fd0a137bd6d0afe291d465e99c7469b082b66b3ee89273b3b22801b6c2948e", - "signature": "b5fd0a137bd6d0afe291d465e99c7469b082b66b3ee89273b3b22801b6c2948e" - }, - "./node_modules/@types/node/http2.d.ts": { - "version": "873da589b78a1f1fa7d623483bd2c2730a02e0852259fb8fdcfe5221ac51d18a", - "signature": "873da589b78a1f1fa7d623483bd2c2730a02e0852259fb8fdcfe5221ac51d18a" - }, - "./node_modules/@types/node/https.d.ts": { - "version": "c969bf4c7cdfe4d5dd28aa09432f99d09ad1d8d8b839959646579521d0467d1a", - "signature": "c969bf4c7cdfe4d5dd28aa09432f99d09ad1d8d8b839959646579521d0467d1a" - }, - "./node_modules/@types/node/inspector.d.ts": { - "version": "4218ced3933a31eed1278d350dd63c5900df0f0904f57d61c054d7a4b83dbe4c", - "signature": "4218ced3933a31eed1278d350dd63c5900df0f0904f57d61c054d7a4b83dbe4c" - }, - "./node_modules/@types/node/module.d.ts": { - "version": "a376e245f494b58365a4391a2568e6dd9da372c3453f4732eb6e15ebb9038451", - "signature": "a376e245f494b58365a4391a2568e6dd9da372c3453f4732eb6e15ebb9038451" - }, - "./node_modules/@types/node/net.d.ts": { - "version": "ffe8912b7c45288810c870b768190c6c097459930a587dd6ef0d900a5529a811", - "signature": "ffe8912b7c45288810c870b768190c6c097459930a587dd6ef0d900a5529a811" - }, - "./node_modules/@types/node/os.d.ts": { - "version": "f53678bdb9f25445c8cdf021f2b003b74fd638e69bb1959dde8e370e8cc1e4fa", - "signature": "f53678bdb9f25445c8cdf021f2b003b74fd638e69bb1959dde8e370e8cc1e4fa" - }, - "./node_modules/@types/node/path.d.ts": { - "version": "84044697c8b3e08ef24e4b32cfe6440143d07e469a5e34bda0635276d32d9f35", - "signature": "84044697c8b3e08ef24e4b32cfe6440143d07e469a5e34bda0635276d32d9f35" - }, - "./node_modules/@types/node/perf_hooks.d.ts": { - "version": "0b6098fedb648cab8091cca2b022a5c729b6ef18da923852033f495907cb1a45", - "signature": "0b6098fedb648cab8091cca2b022a5c729b6ef18da923852033f495907cb1a45" - }, - "./node_modules/@types/node/process.d.ts": { - "version": "0e0d58f5e90c0a270dac052b9c5ad8ccdfc8271118c2105b361063218d528d6e", - "signature": "0e0d58f5e90c0a270dac052b9c5ad8ccdfc8271118c2105b361063218d528d6e" - }, - "./node_modules/@types/node/punycode.d.ts": { - "version": "30ec6f9c683b988c3cfaa0c4690692049c4e7ed7dc6f6e94f56194c06b86f5e1", - "signature": "30ec6f9c683b988c3cfaa0c4690692049c4e7ed7dc6f6e94f56194c06b86f5e1" - }, - "./node_modules/@types/node/querystring.d.ts": { - "version": "9f633ecf3e065ff82c19eccab35c8aa1d6d5d1a49af282dc29ef5a64cca34164", - "signature": "9f633ecf3e065ff82c19eccab35c8aa1d6d5d1a49af282dc29ef5a64cca34164" - }, - "./node_modules/@types/node/readline.d.ts": { - "version": "6b2bb67b0942bcfce93e1d6fad5f70afd54940a2b13df7f311201fba54b2cbe9", - "signature": "6b2bb67b0942bcfce93e1d6fad5f70afd54940a2b13df7f311201fba54b2cbe9" - }, - "./node_modules/@types/node/repl.d.ts": { - "version": "dd3706b25d06fe23c73d16079e8c66ac775831ef419da00716bf2aee530a04a4", - "signature": "dd3706b25d06fe23c73d16079e8c66ac775831ef419da00716bf2aee530a04a4" - }, - "./node_modules/@types/node/stream.d.ts": { - "version": "d74b8e644da7415e3757a17a42b7f284597b577e3c87b80f4b3ba0cc2db1184f", - "signature": "d74b8e644da7415e3757a17a42b7f284597b577e3c87b80f4b3ba0cc2db1184f" - }, - "./node_modules/@types/node/string_decoder.d.ts": { - "version": "7e62aac2cc9c0710d772047ad89e8d7117f52592c791eb995ce1f865fedab432", - "signature": "7e62aac2cc9c0710d772047ad89e8d7117f52592c791eb995ce1f865fedab432" - }, - "./node_modules/@types/node/timers.d.ts": { - "version": "b40652bf8ce4a18133b31349086523b219724dca8df3448c1a0742528e7ad5b9", - "signature": "b40652bf8ce4a18133b31349086523b219724dca8df3448c1a0742528e7ad5b9" - }, - "./node_modules/@types/node/tls.d.ts": { - "version": "424bc64b2794d9280c1e1f4a3518ba9d285385a16d84753a6427bb469e582eca", - "signature": "424bc64b2794d9280c1e1f4a3518ba9d285385a16d84753a6427bb469e582eca" - }, - "./node_modules/@types/node/trace_events.d.ts": { - "version": "a77fdb357c78b70142b2fdbbfb72958d69e8f765fd2a3c69946c1018e89d4638", - "signature": "a77fdb357c78b70142b2fdbbfb72958d69e8f765fd2a3c69946c1018e89d4638" - }, - "./node_modules/@types/node/tty.d.ts": { - "version": "3c2ac350c3baa61fd2b1925844109e098f4376d0768a4643abc82754fd752748", - "signature": "3c2ac350c3baa61fd2b1925844109e098f4376d0768a4643abc82754fd752748" - }, - "./node_modules/@types/node/url.d.ts": { - "version": "826d48e49c905cedb906cbde6ccaf758827ff5867d4daa006b5a79e0fb489357", - "signature": "826d48e49c905cedb906cbde6ccaf758827ff5867d4daa006b5a79e0fb489357" - }, - "./node_modules/@types/node/util.d.ts": { - "version": "893d1b5dd98f1c01a0ec4122dfd7f774e0fa1560e1aa19e509c96ed543c6244e", - "signature": "893d1b5dd98f1c01a0ec4122dfd7f774e0fa1560e1aa19e509c96ed543c6244e" - }, - "./node_modules/@types/node/v8.d.ts": { - "version": "289be113bad7ee27ee7fa5b1e373c964c9789a5e9ed7db5ddcb631371120b953", - "signature": "289be113bad7ee27ee7fa5b1e373c964c9789a5e9ed7db5ddcb631371120b953" - }, - "./node_modules/@types/node/vm.d.ts": { - "version": "e4abb8eaa8a7d78236be0f8342404aab076668d20590209e32fdeb924588531e", - "signature": "e4abb8eaa8a7d78236be0f8342404aab076668d20590209e32fdeb924588531e" - }, - "./node_modules/@types/node/worker_threads.d.ts": { - "version": "1b4db6ed54916341a48bb81cfd9f910999b3bcd6b71c6a4c7416532a6908775d", - "signature": "1b4db6ed54916341a48bb81cfd9f910999b3bcd6b71c6a4c7416532a6908775d" - }, - "./node_modules/@types/node/zlib.d.ts": { - "version": "f409183966a1dd93d3a9cd1d54fbeb85c73101e87cd5b19467c5e37b252f3fd8", - "signature": "f409183966a1dd93d3a9cd1d54fbeb85c73101e87cd5b19467c5e37b252f3fd8" - }, - "./node_modules/@types/node/base.d.ts": { - "version": "5ff4ecfd544d596de3c8011a6d44c59443c85e1f99065095e556b15237eb39ac", - "signature": "5ff4ecfd544d596de3c8011a6d44c59443c85e1f99065095e556b15237eb39ac" - }, - "./node_modules/@types/node/ts3.2/fs.d.ts": { - "version": "12b2608d6074167c331c9c3c6994a57819f6ff934c7fd4527e23aabf56d4c8d1", - "signature": "12b2608d6074167c331c9c3c6994a57819f6ff934c7fd4527e23aabf56d4c8d1" - }, - "./node_modules/@types/node/ts3.2/util.d.ts": { - "version": "ffc1cd688606ad1ddb59a40e8f3defbde907af2a3402d1d9ddf69accb2903f07", - "signature": "ffc1cd688606ad1ddb59a40e8f3defbde907af2a3402d1d9ddf69accb2903f07" - }, - "./node_modules/@types/node/ts3.2/globals.d.ts": { - "version": "4926e99d2ad39c0bbd36f2d37cc8f52756bc7a5661ad7b12815df871a4b07ba1", - "signature": "4926e99d2ad39c0bbd36f2d37cc8f52756bc7a5661ad7b12815df871a4b07ba1" - }, - "./node_modules/@types/node/ts3.2/base.d.ts": { - "version": "8a70903bbbdad1d58e3936ca90b3ad993e54827ea324e20f2f63cef4e14e9d55", - "signature": "8a70903bbbdad1d58e3936ca90b3ad993e54827ea324e20f2f63cef4e14e9d55" - }, - "./node_modules/@types/node/assert.d.ts": { - "version": "f61a4062a627acbe5c4a9650319132ec8fa7fe2f276a7f40a056e59c2a877e04", - "signature": "f61a4062a627acbe5c4a9650319132ec8fa7fe2f276a7f40a056e59c2a877e04" - }, - "./node_modules/@types/node/ts3.2/index.d.ts": { - "version": "9522f3e35b412f2f17974b1431a1b18d06e0a8f614a0700c37220a4afb04afa8", - "signature": "9522f3e35b412f2f17974b1431a1b18d06e0a8f614a0700c37220a4afb04afa8" - }, - "./node_modules/@types/range-parser/index.d.ts": { - "version": "4e88b833be14c7f384e0dcd57bb30acd799e8e34d212635d693e41a75a71164b", - "signature": "4e88b833be14c7f384e0dcd57bb30acd799e8e34d212635d693e41a75a71164b" - }, - "./node_modules/@types/express-serve-static-core/index.d.ts": { - "version": "a3c58104e1f519cb211279ab6a0dc70e6232f7c7eb11b6a0ca0b43d7e3e72983", - "signature": "a3c58104e1f519cb211279ab6a0dc70e6232f7c7eb11b6a0ca0b43d7e3e72983" - }, - "./node_modules/@types/mime/index.d.ts": { - "version": "be27a64e821a3e5af838650e4aa25805c60f057d0c37a9762c378d19d364b3e6", - "signature": "be27a64e821a3e5af838650e4aa25805c60f057d0c37a9762c378d19d364b3e6" - }, - "./node_modules/@types/serve-static/index.d.ts": { - "version": "cdbae5083ef8f786069519405ca1f1e2ce72b9efebdf5e1931584fba747f3bc0", - "signature": "cdbae5083ef8f786069519405ca1f1e2ce72b9efebdf5e1931584fba747f3bc0" - }, - "./node_modules/@types/connect/index.d.ts": { - "version": "e6ffa74698f0a1d23e4223242ed7dcdb89d02bbbb063a1930e9f91d0385abe16", - "signature": "e6ffa74698f0a1d23e4223242ed7dcdb89d02bbbb063a1930e9f91d0385abe16" - }, - "./node_modules/@types/body-parser/index.d.ts": { - "version": "ebddbd167c2fabd0151f50e5df94ca6d845149c47521280d8867afe3429dd078", - "signature": "ebddbd167c2fabd0151f50e5df94ca6d845149c47521280d8867afe3429dd078" - }, - "./node_modules/@types/qs/index.d.ts": { - "version": "7bc3168fdda8512614c9b6627fbd356043e61070639879cf23d102265259730c", - "signature": "7bc3168fdda8512614c9b6627fbd356043e61070639879cf23d102265259730c" - }, - "./node_modules/@types/express/index.d.ts": { - "version": "ead1ed9dd4874f4907a506a31e4fe9c4e079b42816f6b7ea5016a6d5ddf2fde3", - "signature": "ead1ed9dd4874f4907a506a31e4fe9c4e079b42816f6b7ea5016a6d5ddf2fde3" - }, - "./src/Utils.ts": { - "version": "3fafe931d1756c86680c24af41a389419674bffacc5a2113e7bad6228aeca27a", - "signature": "2336cc1135d6c2625d134e4f9efd92bd7a8d032a46a6b07704955fc942ee2e60" - }, - "./src/HttpError.ts": { - "version": "4c20f2f3d3b94dce23f5a7e1f69f513418e54d5ad29dda562d8d5b83a8a4b26a", - "signature": "a3ad2414c8f96cc5a0133dd38723f942bea58067e7e284646f73d20e81351f21" - }, - "../node_modules/@types/nunjucks/index.d.ts": { - "version": "47081001316dd776632f5bf4954183ba40a0690d1dff832cc709685950e25471", - "signature": "47081001316dd776632f5bf4954183ba40a0690d1dff832cc709685950e25471" - }, - "../node_modules/@types/config/index.d.ts": { - "version": "a2841f04e5d6e69661720db979db826a07dd2c2c6b170fb5fb8ff2680692e922", - "signature": "a2841f04e5d6e69661720db979db826a07dd2c2c6b170fb5fb8ff2680692e922" - }, - "../node_modules/@types/uuid/interfaces.d.ts": { - "version": "5cc5d6f26a50072d51c4ea3a85ee65574b7fa2ae48261ae27b07014695638c50", - "signature": "5cc5d6f26a50072d51c4ea3a85ee65574b7fa2ae48261ae27b07014695638c50" - }, - "../node_modules/@types/uuid/index.d.ts": { - "version": "f961dd194a4ed86a12a6e651bd1fc10d1cea2084b4dbb1a2bb8f3af9ee03a964", - "signature": "f961dd194a4ed86a12a6e651bd1fc10d1cea2084b4dbb1a2bb8f3af9ee03a964" - }, - "../node_modules/@types/mysql/index.d.ts": { - "version": "c31e81b6cf25fee45088689e5043c6243284a7ac1ec9368094d901ea5602bd7b", - "signature": "c31e81b6cf25fee45088689e5043c6243284a7ac1ec9368094d901ea5602bd7b" - }, - "./src/db/Migration.ts": { - "version": "8561d53e8860d46b21bdbdac51e3d68a13a574cb37b6920989df2b6b78f8f371", - "signature": "15cb26bcb2cc6c96ef080c577563c71543e177f199ea5a247beff26ed754d9ed" - }, - "./src/db/MysqlConnectionManager.ts": { - "version": "055fbe99285d902e53ea0eb853696dcb2e35adeb942ce8da515a0be2df99b756", - "signature": "3e6e686f61efa3d2d3312b282bfb08ae6396618d8ff7ee8dee15cb25c5858bf7" - }, - "./src/db/Query.ts": { - "version": "a43192457b79127d344087091c80d4189964edf4ddc86ed476b12d176e22fc70", - "signature": "d37930d32d2842039847f68b7b40855622404378811df23f4d3eac7d15cbb896" - }, - "./src/db/Validator.ts": { - "version": "826ebd3a2060d1a07c14dcb14c41c11ff3ec7d252dc48a3f92744e21e0a76bf4", - "signature": "b279f5059a857fb54b3044e90179aa5f73429ce96be90970a4d94c1aea03aba9" - }, - "./src/Pagination.ts": { - "version": "23419feda468a0484fb8780cf80767efac9944791043c035e5a99772fe0080f1", - "signature": "6aea91ae324d18504957ff52a8c31bb61d15b9895e7bff53e5044f77e0146d1f" - }, - "./src/db/Model.ts": { - "version": "b48b098abf85a4bc11f5c2ccfe735edc3f9e9d808ba3de340961fbfb0a4e6e5f", - "signature": "44fbb4d4ec99995dd6da1283a1ced2f9e56dbb699ba0ab92792c583940f0d04f" - }, - "./src/models/Log.ts": { - "version": "306ff5f522fd37e6e19b207f9d82d147a56f4050ec66e2cb912d84cb6253fb77", - "signature": "fe0f4f3bef6db55a4dba56e4b229cb5abd2225af12fe217d38268e42f2308ae9" - }, - "./src/Logger.ts": { - "version": "37e9fda17789d37a59318f932373d0f7a91fb440c04ad127735535a42b447d03", - "signature": "543d96fd1f49c36dd6061439805a2b7bb91e50b2fa9e552d9ee7906b5d0cf01a" - }, - "../node_modules/@types/ws/index.d.ts": { - "version": "75ce9fa40c86cf9a4f0a546958cc0e5104bf53e408e0f2b71c3757a610adb6b4", - "signature": "75ce9fa40c86cf9a4f0a546958cc0e5104bf53e408e0f2b71c3757a610adb6b4" - }, - "./src/WebSocketListener.ts": { - "version": "ee4d3c2651d6c8e064dba83ba650d92e3a0bd07f9914638d68f43377635e848a", - "signature": "3d406b9aa15cc62f4365fb0ef64aa0f4118003d1166e20927bf299d6f30a07e8" - }, - "./src/ApplicationComponent.ts": { - "version": "23f6f0f5509fc12ddb5e0eec429d448be24fb254d7aef3b6e9a61cf90e797d63", - "signature": "c09ebb6934e80943c2f3699fd8bf29d012281049af1c7f5af576e57fefc0f8d7" - }, - "./src/Controller.ts": { - "version": "2a243e8b262491c3c6ed7f50a87d64d063b964d5e52cc210d36876a579f8b75d", - "signature": "9aee25f9c3c8b8f7d12d49f9e357afe668608a43a2edbecce146829ef028a60a" - }, - "./src/Application.ts": { - "version": "4ece554b602b37717c7ffa073555d58445036b3d8022557ce87c63c294d9a10d", - "signature": "29edd84f74afdcf8d07c6e76f4aa5c69dc883310b5f7612a2f10bc1dbf0dbf63" - }, - "../node_modules/@types/nodemailer/lib/dkim/index.d.ts": { - "version": "971b6006a4610efd734e051f5d1421f87bc0c73bfc3cd205819236d497cba1e4", - "signature": "971b6006a4610efd734e051f5d1421f87bc0c73bfc3cd205819236d497cba1e4" - }, - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts": { - "version": "d9be0e7047e30df44cafac456f18dd3f43af529225ad747c7330e835da6b370c", - "signature": "d9be0e7047e30df44cafac456f18dd3f43af529225ad747c7330e835da6b370c" - }, - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts": { - "version": "a9d32ef46fa1075bfeff4a4ab96c1331254558865ca9c7bf383712baa297f065", - "signature": "a9d32ef46fa1075bfeff4a4ab96c1331254558865ca9c7bf383712baa297f065" - }, - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts": { - "version": "bf54271e59aa6df4670631b40b7fc0666e8ac0978fae18f96ed99f37fb8b3936", - "signature": "bf54271e59aa6df4670631b40b7fc0666e8ac0978fae18f96ed99f37fb8b3936" - }, - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts": { - "version": "689b62c8e45e8f63dacf3a6de1655e06d524cf853f9a96f9446461553c49bd84", - "signature": "689b62c8e45e8f63dacf3a6de1655e06d524cf853f9a96f9446461553c49bd84" - }, - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts": { - "version": "559d3b5e23b28a26355233cd54b496701c6837fd9b539511158e44c028d7b8c5", - "signature": "559d3b5e23b28a26355233cd54b496701c6837fd9b539511158e44c028d7b8c5" - }, - "../node_modules/@types/nodemailer/lib/shared.d.ts": { - "version": "06fdb97fb4733b9ff5a24fc3bf9c0713c93231d361f27ea95ed05bfab679ac61", - "signature": "06fdb97fb4733b9ff5a24fc3bf9c0713c93231d361f27ea95ed05bfab679ac61" - }, - "../node_modules/@types/nodemailer/lib/json-transport.d.ts": { - "version": "f5af2c4bee48b94b4a247464406d600b5232036df7b835d16504f84303977474", - "signature": "f5af2c4bee48b94b4a247464406d600b5232036df7b835d16504f84303977474" - }, - "../node_modules/@types/nodemailer/lib/sendmail-transport/index.d.ts": { - "version": "2739f287a5d26386849a9e1fd05421ece3366ae533f7569654ab73cc74d30aae", - "signature": "2739f287a5d26386849a9e1fd05421ece3366ae533f7569654ab73cc74d30aae" - }, - "../node_modules/@types/nodemailer/lib/ses-transport.d.ts": { - "version": "dd335f22e01cf7abb3445c837e2a8a94650fc23b37572876581d36c2b8f96cb8", - "signature": "dd335f22e01cf7abb3445c837e2a8a94650fc23b37572876581d36c2b8f96cb8" - }, - "../node_modules/@types/nodemailer/lib/smtp-pool/index.d.ts": { - "version": "f44c29cd43b1b2ebcb49b51b3315c85d00fd5ed66b80a7c7a629ad27132bf213", - "signature": "f44c29cd43b1b2ebcb49b51b3315c85d00fd5ed66b80a7c7a629ad27132bf213" - }, - "../node_modules/@types/nodemailer/lib/smtp-transport.d.ts": { - "version": "b5a4a00d0d26d9ca9ce666ea46c2cf84f12139aa4e57b648d22c33362e25554a", - "signature": "b5a4a00d0d26d9ca9ce666ea46c2cf84f12139aa4e57b648d22c33362e25554a" - }, - "../node_modules/@types/nodemailer/lib/stream-transport.d.ts": { - "version": "d10c3e41c9d07022049b732e9b5e8d16a5e584393cfa589b299ac29630ab671a", - "signature": "d10c3e41c9d07022049b732e9b5e8d16a5e584393cfa589b299ac29630ab671a" - }, - "../node_modules/@types/nodemailer/index.d.ts": { - "version": "7c9ad24b7763a35bc2b94f495ee80a4f08f5d7f6fa677526c9931af90fdf6da5", - "signature": "7c9ad24b7763a35bc2b94f495ee80a4f08f5d7f6fa677526c9931af90fdf6da5" - }, - "../node_modules/@types/mjml/index.d.ts": { - "version": "29e6dd4f18688f445ad9d23a358c37e55493894768940449c28ddad2bc118aab", - "signature": "29e6dd4f18688f445ad9d23a358c37e55493894768940449c28ddad2bc118aab" - }, - "./src/Mail.ts": { - "version": "a321991e2afb9ffb308a93936b46edcdc3102e3a18cb55ef23b1d0dc0549cca1", - "signature": "ad7c8edfa4c0e9e5d8325228af68fc92d018fa2cf702dcb5cd793956cabf1036" - }, - "./src/index.ts": { - "version": "21dac02d30e8c4266c081894aa6d0938b620d7ba06c0d3632ab790ccd517be5f", - "signature": "22e5bc2b989e4d6c621ac438700ed6567b63dcc6ff67bffb54e0ede2ef45e721" - }, - "./src/components/CsrfProtectionComponent.ts": { - "version": "d2ac8a26b66bd7c9de6e85eb0fa31223f786636f129be51098e1121f12e91e32", - "signature": "7a208416ae5bfff4bd1f0fe507fdbb23b2026149b1e70c6dd5d52efbf834f049" - }, - "./src/components/ExpressAppComponent.ts": { - "version": "0bf2a47d0497ea6ba5231e5020ea560eafd6272045080f0407b39b42417eb486", - "signature": "1893d96ff6b9d0cc83f76612c4bf48e999e361ffecb6b68b79d908eec4657f80" - }, - "./src/components/FormHelperComponent.ts": { - "version": "6cf21d88314fafeb0499a1b926c9b9ca8f475d7c92c15ca3a06ce40cccb1e1b3", - "signature": "8993db64158ef1437c674fad5f62785b854f777a02273eaa1e3eafd54e670288" - }, - "../node_modules/@types/on-finished/index.d.ts": { - "version": "c69767317aec528b574762b18727db85eef7cf66f33617cc0ee905cbe5a43d97", - "signature": "c69767317aec528b574762b18727db85eef7cf66f33617cc0ee905cbe5a43d97" - }, - "./src/components/LogRequestsComponent.ts": { - "version": "770580c0d8eb417d27b035cba14d18ecc137a72f2a7b2efc4b4e8c7fb94898e6", - "signature": "bdcfd88a151dbdba6a995f66555318bfa466c0b520ebaecbfa4174a7b6107c57" - }, - "./src/components/MailComponent.ts": { - "version": "91f2f87f4c14bdbce5a4a0636f0982482bb7e09390f68fbbc7d7a9ab77cc3388", - "signature": "4051b829aa2900c112bf181f96346150ddb248cb3c0a9395cb592d1f4e46a177" - }, - "./src/components/MaintenanceComponent.ts": { - "version": "0cb6d08367b949a54920be736a0ca7e7d0bd48219082a9743afc7f669f5f4c9a", - "signature": "94f0546ca6c9f8255740ecc19c3883310bec540012c28e9652c10ffb477ac8dc" - }, - "./src/components/MysqlComponent.ts": { - "version": "842acfffb204031d1f449a32f36448f2289e7b979d7438c6922932cfdc3bce66", - "signature": "140c141b201786ff49458f1cbcce2b77052881d168f7ae79d0582185b9aeedee" - }, - "./src/components/RedirectBackComponent.ts": { - "version": "aeed6a141a3295545db9a40642601a3002a75c47ce4fc7803d8103cf03f1707f", - "signature": "ed921b450bfc547bd1ea2edbc0e77d71505c432d8ca141c62a5e4883849eb54c" - }, - "../node_modules/@types/redis/ts3.1/index.d.ts": { - "version": "c09db611897b893f45fc71ba3c8f0ad2b578911f5454b0063cd099d7d7c82ad5", - "signature": "c09db611897b893f45fc71ba3c8f0ad2b578911f5454b0063cd099d7d7c82ad5" - }, - "../node_modules/@types/express/index.d.ts": { - "version": "ead1ed9dd4874f4907a506a31e4fe9c4e079b42816f6b7ea5016a6d5ddf2fde3", - "signature": "ead1ed9dd4874f4907a506a31e4fe9c4e079b42816f6b7ea5016a6d5ddf2fde3" - }, - "../node_modules/@types/express-session/index.d.ts": { - "version": "3e03ea3c4d568a10e41f540bc891c5fb42c036a430187132e599176f7974eaf7", - "signature": "3e03ea3c4d568a10e41f540bc891c5fb42c036a430187132e599176f7974eaf7" - }, - "../node_modules/@types/ioredis/index.d.ts": { - "version": "1b5e15b9e676645123c3f17404ac4736e4dd5eba8189a572b23a09a569989d8f", - "signature": "1b5e15b9e676645123c3f17404ac4736e4dd5eba8189a572b23a09a569989d8f" - }, - "../node_modules/@types/connect-redis/index.d.ts": { - "version": "36b01abb39b1ea4a1081cc4347e4ea09878e015e2ff66bdd1ad25e17f318c93a", - "signature": "36b01abb39b1ea4a1081cc4347e4ea09878e015e2ff66bdd1ad25e17f318c93a" - }, - "./src/components/RedisComponent.ts": { - "version": "c6b95081fc7b4ece4a2b3883e478bfffddb1815fc11b2bf75297056f9c47454c", - "signature": "ed4412eae1fff66afd3f714dd1004aa6d7cb69229fe67e1ce192820c373ec191" - }, - "./src/components/ServeStaticDirectoryComponent.ts": { - "version": "3afaf06a8cadbcc74427bf9e7b987b9cc9413c503df01b8f3f58c7c975cd2dd6", - "signature": "b01e48eed7e04d1f10b2d3f9df5c87b08fd86bc77c5dd1dca7a8ced23f369841" - }, - "../node_modules/@types/connect-flash/index.d.ts": { - "version": "eb6dd47dbc0800f57073a9d5388e0e8cffdc34cc5f3910d8311cdf4a799d5eaa", - "signature": "eb6dd47dbc0800f57073a9d5388e0e8cffdc34cc5f3910d8311cdf4a799d5eaa" - }, - "./src/components/SessionComponent.ts": { - "version": "0ca82dd47213589b8cb879aa25f456157de6d1984ca7e7b157bfd63598c570bb", - "signature": "0b026cff1f2e9cd1e4f22be20024b1cf6c22478229a25adb77dc7086a3438dd4" - }, - "../node_modules/@types/cookie/index.d.ts": { - "version": "90643a7d80d87f379ec4c6448a4b5e473b7fb64062ac649a61d93b3a1a8b2180", - "signature": "90643a7d80d87f379ec4c6448a4b5e473b7fb64062ac649a61d93b3a1a8b2180" - }, - "../node_modules/@types/cookie-parser/index.d.ts": { - "version": "8d77ed4e39114c32edc2e35b683b6f54a6b3292ecdf392e4bfc5f726734955d8", - "signature": "8d77ed4e39114c32edc2e35b683b6f54a6b3292ecdf392e4bfc5f726734955d8" - }, - "./src/components/WebSocketServerComponent.ts": { - "version": "b3705ed6eee728898b2a34b5bbf731c86dceefb9ae2a38a8a40efc8f4b57b759", - "signature": "752b5d1937d8bc6a5e9146dda0bf0de9d9a2470735a86a7471a0de8e06dc3f38" - }, - "./src/migrations/CreateLogsTable.ts": { - "version": "943eae01421342827dfb1e345f225da23605264c72a71fa1b1bff23a80746672", - "signature": "f773ac0c4f5a4182882e6aba40dae5613738f0931b3affe712fdeb7d2b9953c7" - }, - "./src/migrations/CreateMigrationsTable.ts": { - "version": "53c71413d70f75862c2c2b56ecddbf01e592cf7106b5182969f762790e2bbf20", - "signature": "604690ec96d6d95d9d9a3b3662caf186f87c49d8e88a3a36bf63a29449fd0a9c" - }, - "./src/types/Express.d.ts": { - "version": "ace3d52e1a42f5ba8324fba29ca2327a1e0789b8c1a2a51e04fa537254fdc6b9", - "signature": "ace3d52e1a42f5ba8324fba29ca2327a1e0789b8c1a2a51e04fa537254fdc6b9" - } - }, - "options": { - "module": 1, - "esModuleInterop": true, - "outDir": "./dist", - "target": 2, - "strict": true, - "lib": [ - "lib.es2020.d.ts" - ], - "typeRoots": [ - "./node_modules/@types", - "./src/types" - ], - "composite": true, - "rootDir": "./src", - "declaration": true, - "declarationMap": true, - "configFilePath": "./tsconfig.json" - }, - "referencedMap": { - "./node_modules/typescript/lib/lib.es5.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2016.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.core.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.collection.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.generator.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.iterable.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.promise.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.proxy.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.reflect.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.symbol.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2016.array.include.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.object.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.string.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.intl.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.intl.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.promise.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.regexp.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.array.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.object.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.string.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.symbol.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.bigint.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.promise.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.string.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.esnext.intl.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/globals.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/async_hooks.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/buffer.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/events/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/child_process.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/cluster.d.ts": [ - "./node_modules/@types/node/child_process.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/console.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/constants.d.ts": [ - "./node_modules/@types/node/os.d.ts", - "./node_modules/@types/node/crypto.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/crypto.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/dgram.d.ts": [ - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/dns.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/dns.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/domain.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/events.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/fs.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/http.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/http2.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/tls.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/https.d.ts": [ - "./node_modules/@types/node/tls.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/inspector.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/module.d.ts": [ - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/net.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/dns.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/os.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/path.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/perf_hooks.d.ts": [ - "./node_modules/@types/node/async_hooks.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/process.d.ts": [ - "./node_modules/@types/node/tty.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/punycode.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/querystring.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/readline.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/repl.d.ts": [ - "./node_modules/@types/node/readline.d.ts", - "./node_modules/@types/node/vm.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/stream.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/string_decoder.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/timers.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/tls.d.ts": [ - "./node_modules/@types/node/crypto.d.ts", - "./node_modules/@types/node/dns.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/trace_events.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/tty.d.ts": [ - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/url.d.ts": [ - "./node_modules/@types/node/querystring.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/util.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/v8.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/vm.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/worker_threads.d.ts": [ - "./node_modules/@types/node/vm.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/zlib.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/base.d.ts": [ - "./node_modules/@types/node/globals.d.ts", - "./node_modules/@types/node/async_hooks.d.ts", - "./node_modules/@types/node/buffer.d.ts", - "./node_modules/@types/node/child_process.d.ts", - "./node_modules/@types/node/cluster.d.ts", - "./node_modules/@types/node/console.d.ts", - "./node_modules/@types/node/constants.d.ts", - "./node_modules/@types/node/crypto.d.ts", - "./node_modules/@types/node/dgram.d.ts", - "./node_modules/@types/node/dns.d.ts", - "./node_modules/@types/node/domain.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/http2.d.ts", - "./node_modules/@types/node/https.d.ts", - "./node_modules/@types/node/inspector.d.ts", - "./node_modules/@types/node/module.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/os.d.ts", - "./node_modules/@types/node/path.d.ts", - "./node_modules/@types/node/perf_hooks.d.ts", - "./node_modules/@types/node/process.d.ts", - "./node_modules/@types/node/punycode.d.ts", - "./node_modules/@types/node/querystring.d.ts", - "./node_modules/@types/node/readline.d.ts", - "./node_modules/@types/node/repl.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/string_decoder.d.ts", - "./node_modules/@types/node/timers.d.ts", - "./node_modules/@types/node/tls.d.ts", - "./node_modules/@types/node/trace_events.d.ts", - "./node_modules/@types/node/tty.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/v8.d.ts", - "./node_modules/@types/node/vm.d.ts", - "./node_modules/@types/node/worker_threads.d.ts", - "./node_modules/@types/node/zlib.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/ts3.2/fs.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/ts3.2/util.d.ts": [ - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts" - ], - "./node_modules/@types/node/ts3.2/globals.d.ts": [ - "./node_modules/@types/node/globals.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/ts3.2/base.d.ts": [ - "./node_modules/@types/node/base.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts", - "./node_modules/@types/node/ts3.2/globals.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/util.d.ts" - ], - "./node_modules/@types/node/assert.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/ts3.2/index.d.ts": [ - "./node_modules/@types/node/ts3.2/base.d.ts", - "./node_modules/@types/node/assert.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/range-parser/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/express-serve-static-core/index.d.ts": [ - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/range-parser/index.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/mime/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/serve-static/index.d.ts": [ - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/mime/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/connect/index.d.ts": [ - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/body-parser/index.d.ts": [ - "./node_modules/@types/connect/index.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/qs/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/express/index.d.ts": [ - "./node_modules/@types/body-parser/index.d.ts", - "./node_modules/@types/serve-static/index.d.ts", - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/qs/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/Utils.ts": [ - "./node_modules/@types/node/crypto.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/HttpError.ts": [ - "./src/Utils.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nunjucks/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/config/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/uuid/interfaces.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/uuid/index.d.ts": [ - "../node_modules/@types/uuid/interfaces.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/mysql/index.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/tls.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/db/Migration.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/db/MysqlConnectionManager.ts": [ - "../node_modules/@types/mysql/index.d.ts", - "../node_modules/@types/config/index.d.ts", - "./src/db/Migration.ts", - "./src/Logger.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/db/Query.ts": [ - "./src/db/MysqlConnectionManager.ts", - "../node_modules/@types/mysql/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/db/Validator.ts": [ - "./src/db/Model.ts", - "./src/db/Query.ts", - "../node_modules/@types/mysql/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/Pagination.ts": [ - "./src/db/Model.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/db/Model.ts": [ - "./src/db/MysqlConnectionManager.ts", - "./src/db/Validator.ts", - "../node_modules/@types/mysql/index.d.ts", - "./src/db/Query.ts", - "./node_modules/@types/express/index.d.ts", - "./src/Pagination.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/models/Log.ts": [ - "./src/db/Model.ts", - "./src/Logger.ts", - "./src/db/Validator.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/Logger.ts": [ - "../node_modules/@types/config/index.d.ts", - "../node_modules/@types/uuid/index.d.ts", - "./src/models/Log.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/ws/index.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/https.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/zlib.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/WebSocketListener.ts": [ - "../node_modules/@types/ws/index.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/ApplicationComponent.ts": [ - "./node_modules/@types/express/index.d.ts", - "./src/Logger.ts", - "./src/Utils.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/Controller.ts": [ - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/express-serve-static-core/index.d.ts", - "../node_modules/@types/config/index.d.ts", - "./src/Logger.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/Application.ts": [ - "./node_modules/@types/express/index.d.ts", - "./src/HttpError.ts", - "../node_modules/@types/nunjucks/index.d.ts", - "./src/Logger.ts", - "./src/WebSocketListener.ts", - "./src/ApplicationComponent.ts", - "./src/Controller.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/dkim/index.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts": [ - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/url.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/dkim/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/tls.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/shared.d.ts": [ - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/json-transport.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/sendmail-transport/index.d.ts": [ - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/ses-transport.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/smtp-pool/index.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/smtp-transport.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/stream-transport.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/index.d.ts": [ - "../node_modules/@types/nodemailer/lib/json-transport.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/sendmail-transport/index.d.ts", - "../node_modules/@types/nodemailer/lib/ses-transport.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-pool/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-transport.d.ts", - "../node_modules/@types/nodemailer/lib/stream-transport.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/mjml/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/Mail.ts": [ - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/config/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nunjucks/index.d.ts", - "./node_modules/@types/node/util.d.ts", - "./src/Utils.ts", - "../node_modules/@types/mjml/index.d.ts", - "./node_modules/@types/node/querystring.d.ts", - "./src/Logger.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/index.ts": [ - "./src/ApplicationComponent.ts", - "./src/Mail.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/CsrfProtectionComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/node/crypto.d.ts", - "./src/HttpError.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/ExpressAppComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "./src/Logger.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/FormHelperComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/on-finished/index.d.ts": [ - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/LogRequestsComponent.ts": [ - "./src/ApplicationComponent.ts", - "../node_modules/@types/on-finished/index.d.ts", - "./src/Logger.ts", - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/MailComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "./src/Mail.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/MaintenanceComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "./src/HttpError.ts", - "./src/Application.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/MysqlComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "./src/db/MysqlConnectionManager.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/RedirectBackComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "../node_modules/@types/on-finished/index.d.ts", - "./src/Logger.ts", - "./src/HttpError.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/redis/ts3.1/index.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/express/index.d.ts": [ - "./node_modules/@types/body-parser/index.d.ts", - "./node_modules/@types/serve-static/index.d.ts", - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/qs/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/express-session/index.d.ts": [ - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/ioredis/index.d.ts": [ - "./node_modules/@types/node/tls.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/connect-redis/index.d.ts": [ - "./node_modules/@types/express/index.d.ts", - "../node_modules/@types/express-session/index.d.ts", - "../node_modules/@types/ioredis/index.d.ts", - "../node_modules/@types/redis/ts3.1/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/RedisComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "../node_modules/@types/redis/ts3.1/index.d.ts", - "../node_modules/@types/config/index.d.ts", - "./src/Logger.ts", - "../node_modules/@types/express-session/index.d.ts", - "../node_modules/@types/connect-redis/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/ServeStaticDirectoryComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/connect-flash/index.d.ts": [ - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/SessionComponent.ts": [ - "./src/ApplicationComponent.ts", - "../node_modules/@types/express-session/index.d.ts", - "../node_modules/@types/config/index.d.ts", - "./src/components/RedisComponent.ts", - "../node_modules/@types/connect-flash/index.d.ts", - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/cookie/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/cookie-parser/index.d.ts": [ - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/WebSocketServerComponent.ts": [ - "./src/ApplicationComponent.ts", - "./node_modules/@types/express/index.d.ts", - "../node_modules/@types/ws/index.d.ts", - "./src/Logger.ts", - "../node_modules/@types/cookie/index.d.ts", - "../node_modules/@types/cookie-parser/index.d.ts", - "../node_modules/@types/config/index.d.ts", - "./src/components/ExpressAppComponent.ts", - "./src/Application.ts", - "./src/components/RedisComponent.ts", - "./src/WebSocketListener.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/migrations/CreateLogsTable.ts": [ - "./src/db/Migration.ts", - "./src/db/MysqlConnectionManager.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/migrations/CreateMigrationsTable.ts": [ - "./src/db/Migration.ts", - "./src/db/MysqlConnectionManager.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/types/Express.d.ts": [ - "../node_modules/@types/nunjucks/index.d.ts", - "./src/db/Model.ts", - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ] - }, - "exportedModulesMap": { - "./node_modules/typescript/lib/lib.es5.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2016.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.core.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.collection.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.generator.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.iterable.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.promise.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.proxy.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.reflect.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.symbol.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2016.array.include.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.object.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.string.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.intl.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.intl.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.promise.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2018.regexp.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.array.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.object.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.string.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2019.symbol.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.bigint.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.promise.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.string.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/typescript/lib/lib.esnext.intl.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/globals.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/async_hooks.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/buffer.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/events/index.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/child_process.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/cluster.d.ts": [ - "./node_modules/@types/node/child_process.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/console.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/constants.d.ts": [ - "./node_modules/@types/node/os.d.ts", - "./node_modules/@types/node/crypto.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/crypto.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/dgram.d.ts": [ - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/dns.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/dns.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/domain.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/events.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/fs.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/http.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/http2.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/tls.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/https.d.ts": [ - "./node_modules/@types/node/tls.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/inspector.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/module.d.ts": [ - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/net.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/dns.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/os.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/path.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/perf_hooks.d.ts": [ - "./node_modules/@types/node/async_hooks.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/process.d.ts": [ - "./node_modules/@types/node/tty.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/punycode.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/querystring.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/readline.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/repl.d.ts": [ - "./node_modules/@types/node/readline.d.ts", - "./node_modules/@types/node/vm.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/stream.d.ts": [ - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/string_decoder.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/timers.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/tls.d.ts": [ - "./node_modules/@types/node/crypto.d.ts", - "./node_modules/@types/node/dns.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/trace_events.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/tty.d.ts": [ - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/url.d.ts": [ - "./node_modules/@types/node/querystring.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/util.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/v8.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/vm.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/worker_threads.d.ts": [ - "./node_modules/@types/node/vm.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/zlib.d.ts": [ - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/base.d.ts": [ - "./node_modules/@types/node/globals.d.ts", - "./node_modules/@types/node/async_hooks.d.ts", - "./node_modules/@types/node/buffer.d.ts", - "./node_modules/@types/node/child_process.d.ts", - "./node_modules/@types/node/cluster.d.ts", - "./node_modules/@types/node/console.d.ts", - "./node_modules/@types/node/constants.d.ts", - "./node_modules/@types/node/crypto.d.ts", - "./node_modules/@types/node/dgram.d.ts", - "./node_modules/@types/node/dns.d.ts", - "./node_modules/@types/node/domain.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/http2.d.ts", - "./node_modules/@types/node/https.d.ts", - "./node_modules/@types/node/inspector.d.ts", - "./node_modules/@types/node/module.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/os.d.ts", - "./node_modules/@types/node/path.d.ts", - "./node_modules/@types/node/perf_hooks.d.ts", - "./node_modules/@types/node/process.d.ts", - "./node_modules/@types/node/punycode.d.ts", - "./node_modules/@types/node/querystring.d.ts", - "./node_modules/@types/node/readline.d.ts", - "./node_modules/@types/node/repl.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/string_decoder.d.ts", - "./node_modules/@types/node/timers.d.ts", - "./node_modules/@types/node/tls.d.ts", - "./node_modules/@types/node/trace_events.d.ts", - "./node_modules/@types/node/tty.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/v8.d.ts", - "./node_modules/@types/node/vm.d.ts", - "./node_modules/@types/node/worker_threads.d.ts", - "./node_modules/@types/node/zlib.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/ts3.2/fs.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/ts3.2/util.d.ts": [ - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts" - ], - "./node_modules/@types/node/ts3.2/globals.d.ts": [ - "./node_modules/@types/node/globals.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/ts3.2/base.d.ts": [ - "./node_modules/@types/node/base.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts", - "./node_modules/@types/node/ts3.2/globals.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/util.d.ts" - ], - "./node_modules/@types/node/assert.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/node/ts3.2/index.d.ts": [ - "./node_modules/@types/node/ts3.2/base.d.ts", - "./node_modules/@types/node/assert.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/range-parser/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/express-serve-static-core/index.d.ts": [ - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/range-parser/index.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/mime/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/serve-static/index.d.ts": [ - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/mime/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/connect/index.d.ts": [ - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/body-parser/index.d.ts": [ - "./node_modules/@types/connect/index.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/qs/index.d.ts": [ - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./node_modules/@types/express/index.d.ts": [ - "./node_modules/@types/body-parser/index.d.ts", - "./node_modules/@types/serve-static/index.d.ts", - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/qs/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/HttpError.ts": [ - "./src/Utils.ts" - ], - "../node_modules/@types/nunjucks/index.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/config/index.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/uuid/interfaces.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/uuid/index.d.ts": [ - "../node_modules/@types/uuid/interfaces.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/mysql/index.d.ts": [ - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/node/tls.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/db/MysqlConnectionManager.ts": [ - "../node_modules/@types/mysql/index.d.ts", - "./src/db/Migration.ts" - ], - "./src/db/Query.ts": [ - "../node_modules/@types/mysql/index.d.ts", - "./src/db/MysqlConnectionManager.ts" - ], - "./src/db/Validator.ts": [ - "../node_modules/@types/mysql/index.d.ts", - "./src/db/Model.ts", - "./src/db/Query.ts" - ], - "./src/Pagination.ts": [ - "./src/db/Model.ts" - ], - "./src/db/Model.ts": [ - "./node_modules/@types/express/index.d.ts", - "./src/db/Query.ts", - "./src/db/Validator.ts", - "../node_modules/@types/mysql/index.d.ts" - ], - "./src/models/Log.ts": [ - "./src/Logger.ts", - "./src/db/Model.ts" - ], - "../node_modules/@types/ws/index.d.ts": [ - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/node/http.d.ts", - "../node_modules/@types/node/https.d.ts", - "../node_modules/@types/node/net.d.ts", - "../node_modules/@types/node/url.d.ts", - "../node_modules/@types/node/zlib.d.ts", - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/WebSocketListener.ts": [ - "../node_modules/@types/ws/index.d.ts", - "./node_modules/@types/node/http.d.ts" - ], - "./src/ApplicationComponent.ts": [ - "./node_modules/@types/express/index.d.ts" - ], - "./src/Controller.ts": [ - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/express-serve-static-core/index.d.ts" - ], - "./src/Application.ts": [ - "./src/Controller.ts", - "./src/WebSocketListener.ts", - "./src/ApplicationComponent.ts" - ], - "../node_modules/@types/nodemailer/lib/dkim/index.d.ts": [ - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts": [ - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts": [ - "../node_modules/@types/node/http.d.ts", - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts": [ - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/node/net.d.ts", - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/node/url.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/dkim/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts": [ - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts": [ - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/node/net.d.ts", - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/node/tls.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/shared.d.ts": [ - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/json-transport.d.ts": [ - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/sendmail-transport/index.d.ts": [ - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/ses-transport.d.ts": [ - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/smtp-pool/index.d.ts": [ - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/smtp-transport.d.ts": [ - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/lib/stream-transport.d.ts": [ - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/nodemailer/index.d.ts": [ - "../node_modules/@types/nodemailer/lib/json-transport.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/sendmail-transport/index.d.ts", - "../node_modules/@types/nodemailer/lib/ses-transport.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-pool/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-transport.d.ts", - "../node_modules/@types/nodemailer/lib/stream-transport.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/mjml/index.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/Mail.ts": [ - "../node_modules/@types/nodemailer/index.d.ts" - ], - "./src/components/CsrfProtectionComponent.ts": [ - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "./src/components/ExpressAppComponent.ts": [ - "./node_modules/@types/express/index.d.ts", - "./node_modules/@types/node/http.d.ts", - "./src/ApplicationComponent.ts" - ], - "./src/components/FormHelperComponent.ts": [ - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "../node_modules/@types/on-finished/index.d.ts": [ - "../node_modules/@types/node/http.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/LogRequestsComponent.ts": [ - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "./src/components/MailComponent.ts": [ - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "./src/components/MaintenanceComponent.ts": [ - "./src/Application.ts", - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "./src/components/MysqlComponent.ts": [ - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "./src/components/RedirectBackComponent.ts": [ - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "../node_modules/@types/redis/ts3.1/index.d.ts": [ - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/express/index.d.ts": [ - "../node_modules/@types/body-parser/index.d.ts", - "../node_modules/@types/serve-static/index.d.ts", - "../node_modules/@types/express-serve-static-core/index.d.ts", - "../node_modules/@types/qs/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/express-session/index.d.ts": [ - "../node_modules/@types/express/index.d.ts", - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/ioredis/index.d.ts": [ - "../node_modules/@types/node/tls.d.ts", - "../node_modules/@types/node/stream.d.ts", - "../node_modules/@types/node/events.d.ts", - "../node_modules/@types/node/ts3.2/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/connect-redis/index.d.ts": [ - "../node_modules/@types/express/index.d.ts", - "../node_modules/@types/express-session/index.d.ts", - "../node_modules/@types/ioredis/index.d.ts", - "../node_modules/@types/redis/ts3.1/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/RedisComponent.ts": [ - "./node_modules/@types/express/index.d.ts", - "../node_modules/@types/express-session/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "./src/components/ServeStaticDirectoryComponent.ts": [ - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "../node_modules/@types/connect-flash/index.d.ts": [ - "../node_modules/@types/express/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/SessionComponent.ts": [ - "./src/components/RedisComponent.ts", - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "../node_modules/@types/cookie/index.d.ts": [ - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "../node_modules/@types/cookie-parser/index.d.ts": [ - "../node_modules/@types/express/index.d.ts", - "../node_modules/@types/node/fs.d.ts", - "../node_modules/@types/node/ts3.2/fs.d.ts", - "../node_modules/@types/node/util.d.ts", - "../node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/components/WebSocketServerComponent.ts": [ - "./src/Application.ts", - "./src/components/ExpressAppComponent.ts", - "./src/components/RedisComponent.ts", - "./node_modules/@types/express/index.d.ts", - "./src/ApplicationComponent.ts" - ], - "./src/migrations/CreateLogsTable.ts": [ - "./src/db/Migration.ts" - ], - "./src/migrations/CreateMigrationsTable.ts": [ - "./src/db/Migration.ts" - ], - "./src/types/Express.d.ts": [ - "../node_modules/@types/nunjucks/index.d.ts", - "./src/db/Model.ts", - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts" - ], - "./src/index.ts": [ - "./src/ApplicationComponent.ts", - "./src/Mail.ts" - ] - }, - "semanticDiagnosticsPerFile": [ - "./node_modules/typescript/lib/lib.es5.d.ts", - "./node_modules/typescript/lib/lib.es2015.d.ts", - "./node_modules/typescript/lib/lib.es2016.d.ts", - "./node_modules/typescript/lib/lib.es2017.d.ts", - "./node_modules/typescript/lib/lib.es2018.d.ts", - "./node_modules/typescript/lib/lib.es2019.d.ts", - "./node_modules/typescript/lib/lib.es2020.d.ts", - "./node_modules/typescript/lib/lib.es2015.core.d.ts", - "./node_modules/typescript/lib/lib.es2015.collection.d.ts", - "./node_modules/typescript/lib/lib.es2015.generator.d.ts", - "./node_modules/typescript/lib/lib.es2015.iterable.d.ts", - "./node_modules/typescript/lib/lib.es2015.promise.d.ts", - "./node_modules/typescript/lib/lib.es2015.proxy.d.ts", - "./node_modules/typescript/lib/lib.es2015.reflect.d.ts", - "./node_modules/typescript/lib/lib.es2015.symbol.d.ts", - "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts", - "./node_modules/typescript/lib/lib.es2016.array.include.d.ts", - "./node_modules/typescript/lib/lib.es2017.object.d.ts", - "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts", - "./node_modules/typescript/lib/lib.es2017.string.d.ts", - "./node_modules/typescript/lib/lib.es2017.intl.d.ts", - "./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts", - "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts", - "./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts", - "./node_modules/typescript/lib/lib.es2018.intl.d.ts", - "./node_modules/typescript/lib/lib.es2018.promise.d.ts", - "./node_modules/typescript/lib/lib.es2018.regexp.d.ts", - "./node_modules/typescript/lib/lib.es2019.array.d.ts", - "./node_modules/typescript/lib/lib.es2019.object.d.ts", - "./node_modules/typescript/lib/lib.es2019.string.d.ts", - "./node_modules/typescript/lib/lib.es2019.symbol.d.ts", - "./node_modules/typescript/lib/lib.es2020.bigint.d.ts", - "./node_modules/typescript/lib/lib.es2020.promise.d.ts", - "./node_modules/typescript/lib/lib.es2020.string.d.ts", - "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts", - "./node_modules/typescript/lib/lib.esnext.intl.d.ts", - "./node_modules/@types/node/globals.d.ts", - "./node_modules/@types/node/async_hooks.d.ts", - "./node_modules/@types/node/buffer.d.ts", - "../node_modules/@types/events/index.d.ts", - "./node_modules/@types/node/child_process.d.ts", - "./node_modules/@types/node/cluster.d.ts", - "./node_modules/@types/node/console.d.ts", - "./node_modules/@types/node/constants.d.ts", - "./node_modules/@types/node/crypto.d.ts", - "./node_modules/@types/node/dgram.d.ts", - "./node_modules/@types/node/dns.d.ts", - "./node_modules/@types/node/domain.d.ts", - "./node_modules/@types/node/events.d.ts", - "./node_modules/@types/node/fs.d.ts", - "./node_modules/@types/node/http.d.ts", - "./node_modules/@types/node/http2.d.ts", - "./node_modules/@types/node/https.d.ts", - "./node_modules/@types/node/inspector.d.ts", - "./node_modules/@types/node/module.d.ts", - "./node_modules/@types/node/net.d.ts", - "./node_modules/@types/node/os.d.ts", - "./node_modules/@types/node/path.d.ts", - "./node_modules/@types/node/perf_hooks.d.ts", - "./node_modules/@types/node/process.d.ts", - "./node_modules/@types/node/punycode.d.ts", - "./node_modules/@types/node/querystring.d.ts", - "./node_modules/@types/node/readline.d.ts", - "./node_modules/@types/node/repl.d.ts", - "./node_modules/@types/node/stream.d.ts", - "./node_modules/@types/node/string_decoder.d.ts", - "./node_modules/@types/node/timers.d.ts", - "./node_modules/@types/node/tls.d.ts", - "./node_modules/@types/node/trace_events.d.ts", - "./node_modules/@types/node/tty.d.ts", - "./node_modules/@types/node/url.d.ts", - "./node_modules/@types/node/util.d.ts", - "./node_modules/@types/node/v8.d.ts", - "./node_modules/@types/node/vm.d.ts", - "./node_modules/@types/node/worker_threads.d.ts", - "./node_modules/@types/node/zlib.d.ts", - "./node_modules/@types/node/base.d.ts", - "./node_modules/@types/node/ts3.2/fs.d.ts", - "./node_modules/@types/node/ts3.2/util.d.ts", - "./node_modules/@types/node/ts3.2/globals.d.ts", - "./node_modules/@types/node/ts3.2/base.d.ts", - "./node_modules/@types/node/assert.d.ts", - "./node_modules/@types/node/ts3.2/index.d.ts", - "./node_modules/@types/range-parser/index.d.ts", - "./node_modules/@types/express-serve-static-core/index.d.ts", - "./node_modules/@types/mime/index.d.ts", - "./node_modules/@types/serve-static/index.d.ts", - "./node_modules/@types/connect/index.d.ts", - "./node_modules/@types/body-parser/index.d.ts", - "./node_modules/@types/qs/index.d.ts", - "./node_modules/@types/express/index.d.ts", - "./src/Utils.ts", - "./src/HttpError.ts", - "../node_modules/@types/nunjucks/index.d.ts", - "../node_modules/@types/config/index.d.ts", - "../node_modules/@types/uuid/interfaces.d.ts", - "../node_modules/@types/uuid/index.d.ts", - "../node_modules/@types/mysql/index.d.ts", - "./src/db/Migration.ts", - "./src/db/MysqlConnectionManager.ts", - "./src/db/Query.ts", - "./src/db/Validator.ts", - "./src/Pagination.ts", - "./src/db/Model.ts", - "./src/models/Log.ts", - "./src/Logger.ts", - "../node_modules/@types/ws/index.d.ts", - "./src/WebSocketListener.ts", - "./src/ApplicationComponent.ts", - "./src/Controller.ts", - "./src/Application.ts", - "../node_modules/@types/nodemailer/lib/dkim/index.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/mail-message.d.ts", - "../node_modules/@types/nodemailer/lib/xoauth2.d.ts", - "../node_modules/@types/nodemailer/lib/mailer/index.d.ts", - "../node_modules/@types/nodemailer/lib/mime-node/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-connection/index.d.ts", - "../node_modules/@types/nodemailer/lib/shared.d.ts", - "../node_modules/@types/nodemailer/lib/json-transport.d.ts", - "../node_modules/@types/nodemailer/lib/sendmail-transport/index.d.ts", - "../node_modules/@types/nodemailer/lib/ses-transport.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-pool/index.d.ts", - "../node_modules/@types/nodemailer/lib/smtp-transport.d.ts", - "../node_modules/@types/nodemailer/lib/stream-transport.d.ts", - "../node_modules/@types/nodemailer/index.d.ts", - "../node_modules/@types/mjml/index.d.ts", - "./src/Mail.ts", - "./src/components/CsrfProtectionComponent.ts", - "./src/components/ExpressAppComponent.ts", - "./src/components/FormHelperComponent.ts", - "../node_modules/@types/on-finished/index.d.ts", - "./src/components/LogRequestsComponent.ts", - "./src/components/MailComponent.ts", - "./src/components/MaintenanceComponent.ts", - "./src/components/MysqlComponent.ts", - "./src/components/RedirectBackComponent.ts", - "../node_modules/@types/redis/ts3.1/index.d.ts", - "../node_modules/@types/express/index.d.ts", - "../node_modules/@types/express-session/index.d.ts", - "../node_modules/@types/ioredis/index.d.ts", - "../node_modules/@types/connect-redis/index.d.ts", - "./src/components/RedisComponent.ts", - "./src/components/ServeStaticDirectoryComponent.ts", - "../node_modules/@types/connect-flash/index.d.ts", - "./src/components/SessionComponent.ts", - "../node_modules/@types/cookie/index.d.ts", - "../node_modules/@types/cookie-parser/index.d.ts", - "./src/components/WebSocketServerComponent.ts", - "./src/migrations/CreateLogsTable.ts", - "./src/migrations/CreateMigrationsTable.ts", - "./src/types/Express.d.ts", - "./src/index.ts" - ] - }, - "version": "3.8.3" -} \ No newline at end of file diff --git a/views/auth/auth.njk b/views/auth/auth.njk index 10fb3a4..76c9e5a 100644 --- a/views/auth/auth.njk +++ b/views/auth/auth.njk @@ -29,18 +29,18 @@ Go back - {{ macros.csrf(getCSRFToken) }} + {{ macros.csrf(getCsrfToken) }} {% else %}

Log in or register

- {# {{ macros.message('info', 'If we don\'t find your email address in our database, you will be able to register.', false, true) }}#} + {# {{ macros.message('info', 'If we don\'t find your email address in our database, you will be able to register.', false, true) }} #}
{{ macros.field(_locals, 'email', 'email', query.email or '', 'Your email address', "If we don't find your email address in our database, you will be able to register.", 'required') }}
- {{ macros.csrf(getCSRFToken) }} + {{ macros.csrf(getCsrfToken) }} {% endif %} diff --git a/views/backend/accounts_approval.njk b/views/backend/accounts_approval.njk index 5ace855..cc0ae9f 100644 --- a/views/backend/accounts_approval.njk +++ b/views/backend/accounts_approval.njk @@ -28,14 +28,14 @@
- {{ macros.csrf(getCSRFToken) }} + {{ macros.csrf(getCsrfToken) }}
- {{ macros.csrf(getCSRFToken) }} + {{ macros.csrf(getCsrfToken) }}
diff --git a/views/macros.njk b/views/macros.njk index dc89f32..b62170b 100644 --- a/views/macros.njk +++ b/views/macros.njk @@ -28,8 +28,8 @@ {% endif %} {% endmacro %} -{% macro csrf(getCSRFToken) %} - +{% macro csrf(getCsrfToken) %} + {% endmacro %} {% macro field(_locals, type, name, value, placeholder, hint, validation_attributes='', extraData='', icon=null) %}