import {Express} from "express"; import Application from "./Application.js"; import AccountController from "./auth/AccountController.js"; import AuthComponent from "./auth/AuthComponent.js"; import AuthController from "./auth/AuthController.js"; import AddUsedToMagicLinksMigration from "./auth/magic_link/AddUsedToMagicLinksMigration.js"; import CreateMagicLinksTableMigration from "./auth/magic_link/CreateMagicLinksTableMigration.js"; import MagicLinkAuthMethod from "./auth/magic_link/MagicLinkAuthMethod.js"; import MagicLinkController from "./auth/magic_link/MagicLinkController.js"; import MagicLinkWebSocketListener from "./auth/magic_link/MagicLinkWebSocketListener.js"; import MakeMagicLinksSessionNotUniqueMigration from "./auth/magic_link/MakeMagicLinksSessionNotUniqueMigration.js"; import AddApprovedFieldToUsersTableMigration from "./auth/migrations/AddApprovedFieldToUsersTableMigration.js"; import AddNameChangedAtToUsersMigration from "./auth/migrations/AddNameChangedAtToUsersMigration.js"; import AddNameToUsersMigration from "./auth/migrations/AddNameToUsersMigration.js"; import CreateUsersAndUserEmailsTableMigration from "./auth/migrations/CreateUsersAndUserEmailsTableMigration.js"; import AddPasswordToUsersMigration from "./auth/password/AddPasswordToUsersMigration.js"; import PasswordAuthMethod from "./auth/password/PasswordAuthMethod.js"; import CsrfProtectionComponent from "./components/CsrfProtectionComponent.js"; import ExpressAppComponent from "./components/ExpressAppComponent.js"; import FormHelperComponent from "./components/FormHelperComponent.js"; import FrontendToolsComponent from "./components/FrontendToolsComponent.js"; import LogRequestsComponent from "./components/LogRequestsComponent.js"; import MailComponent from "./components/MailComponent.js"; import MaintenanceComponent from "./components/MaintenanceComponent.js"; import MysqlComponent from "./components/MysqlComponent.js"; import PreviousUrlComponent from "./components/PreviousUrlComponent.js"; import RedisComponent from "./components/RedisComponent.js"; import ServeStaticDirectoryComponent from "./components/ServeStaticDirectoryComponent.js"; import SessionComponent from "./components/SessionComponent.js"; import WebSocketServerComponent from "./components/WebSocketServerComponent.js"; import Controller from "./Controller.js"; import Migration, {MigrationType} from "./db/Migration.js"; import AssetCompiler from "./frontend/AssetCompiler.js"; import CopyAssetPreCompiler from "./frontend/CopyAssetPreCompiler.js"; import MailViewEngine from "./frontend/MailViewEngine.js"; import NunjucksViewEngine from "./frontend/NunjucksViewEngine.js"; import ScssAssetPreCompiler from "./frontend/ScssAssetPreCompiler.js"; import SvelteViewEngine from "./frontend/SvelteViewEngine.js"; import TypeScriptPreCompiler from "./frontend/TypeScriptPreCompiler.js"; import BackendController from "./helpers/BackendController.js"; import MailController from "./mail/MailController.js"; import {MAGIC_LINK_MAIL} from "./Mails.js"; import CreateMigrationsTable from "./migrations/CreateMigrationsTable.js"; export const MIGRATIONS = [ CreateMigrationsTable, CreateUsersAndUserEmailsTableMigration, AddPasswordToUsersMigration, CreateMagicLinksTableMigration, AddNameToUsersMigration, MakeMagicLinksSessionNotUniqueMigration, AddUsedToMagicLinksMigration, AddNameChangedAtToUsersMigration, ]; export default class TestApp extends Application { private readonly addr: string; private readonly port: number; public constructor( version: string, addr: string, port: number, ignoreCommandLine: boolean = false, private readonly approvalMode: boolean, ) { super(version, ignoreCommandLine); this.addr = addr; this.port = port; } protected getMigrations(): MigrationType[] { const migrations = [...MIGRATIONS]; if (this.approvalMode) { migrations.push(AddApprovedFieldToUsersTableMigration); } return migrations; } protected async init(): Promise { this.registerComponents(); this.registerWebSocketListeners(); this.registerControllers(); } protected registerComponents(): void { // Base this.use(new ExpressAppComponent(this.addr, this.port)); this.use(new LogRequestsComponent()); // Static files this.use(new ServeStaticDirectoryComponent('public')); // Maintenance this.use(new MaintenanceComponent()); // Dynamic views and routes const intermediateDirectory = 'intermediates/assets'; const assetCompiler = new AssetCompiler(intermediateDirectory, 'public'); this.use(new FrontendToolsComponent( assetCompiler, new CopyAssetPreCompiler(intermediateDirectory, '', 'json', ['test/assets'], false), new ScssAssetPreCompiler(intermediateDirectory, assetCompiler.targetDir, 'scss', ['test/assets']), new CopyAssetPreCompiler(intermediateDirectory, 'img', 'svg', ['test/assets'], true), new TypeScriptPreCompiler(intermediateDirectory, ['test/assets']), new SvelteViewEngine(intermediateDirectory, 'test/assets'), new NunjucksViewEngine(intermediateDirectory, 'test/assets'), )); this.use(new PreviousUrlComponent()); // Services this.use(new MysqlComponent()); this.use(new MailComponent(new MailViewEngine('intermediates/assets', 'test/assets'))); // Session this.use(new RedisComponent()); this.use(new SessionComponent(this.as(RedisComponent))); // Utils this.use(new FormHelperComponent()); // Middlewares this.use(new CsrfProtectionComponent()); // Auth this.use(new AuthComponent(this, new MagicLinkAuthMethod(this, MAGIC_LINK_MAIL), new PasswordAuthMethod(this))); // WebSocket server this.use(new WebSocketServerComponent()); } protected registerWebSocketListeners(): void { this.use(new MagicLinkWebSocketListener()); } protected registerControllers(): void { this.use(new MailController()); this.use(new AuthController()); this.use(new AccountController()); this.use(new BackendController()); this.use(new MagicLinkController(this.as>(MagicLinkWebSocketListener))); // Special home controller this.use(new class extends Controller { public routes(): void { this.get('/', (req, res) => { res.formatViewData('home'); }, 'home'); this.get('/tests', (req, res) => { res.formatViewData('tests'); }, 'tests'); this.get('/design', (req, res) => { req.flash('success', 'Success.'); req.flash('info', 'Info.'); req.flash('warning', 'Warning.'); req.flash('error', 'Error.'); req.flash('error-alert', 'Error alert.'); res.formatViewData('design'); }, 'design'); } }()); } public getExpressApp(): Express { return this.as(ExpressAppComponent).getExpressApp(); } }