webstudio/server/src/core/controllers/app.ts
2025-02-15 17:23:27 +03:00

147 lines
4.4 KiB
TypeScript

import express from "express";
import cors from "cors";
import fileUpload from "express-fileupload";
import { Routes } from "../interfaces/router";
import { Server } from "socket.io";
import { createServer } from "http";
import { SocketSubscriber } from "./socket_controller";
import { dirname } from "path";
import { CheckAndCreateStaticFilesFolderUseCase } from "../usecases/check_and_create_static_files_folder_usecase";
import { DataBaseConnectUseCase } from "../usecases/database_connect_usecase";
import { TypedEvent } from "../helpers/typed_event";
import { CalculationInstanceDBModel } from "../../features/calculations_instance/models/calculations_instance_database_model";
import * as fs from "fs";
import { WriteFileSystemFileUseCase } from "../usecases/write_file_system_file_usecase";
export enum ServerStatus {
init = "init",
finished = "finished",
error = "error",
}
export enum Environment {
DEV = "DEV",
E2E_TEST = "E2E_TEST",
}
export class App extends TypedEvent<ServerStatus> {
public app: express.Application;
public port: number;
public env: Environment;
public socketSubscribers: SocketSubscriber<any>[];
public io: Server;
status: ServerStatus;
constructor(routes: Routes[] = [], socketSubscribers: SocketSubscriber<any>[] = [], env = Environment.DEV) {
super();
this.init(routes, socketSubscribers, env);
}
public init(routes: Routes[], socketSubscribers: SocketSubscriber<any>[], env: Environment) {
this.port = 4001;
this.socketSubscribers = socketSubscribers;
this.env = env;
this.app = express();
this.setServerStatus(ServerStatus.init);
this.loadAppDependencies().then(() => {
this.initializeMiddlewares();
this.initializeRoutes(routes);
if (this.status !== ServerStatus.error) {
this.setServerStatus(ServerStatus.finished);
}
});
}
public listen() {
const httpServer = createServer(this.app);
const io = new Server(httpServer, {
cors: { origin: "*" },
});
io.on("connection", (socket) => {
this.socketSubscribers.map((el) => {
el.emitter.on((e) => {
socket.emit(el.event, e);
});
});
});
httpServer.listen(this.port, () => {
console.info(`=================================`);
console.info(`======= ENV: ${this.env} =======`);
console.info(`🚀 HTTP http://localhost:${this.port}`);
console.info(`🚀 WS ws://localhost:${this.port}`);
console.info(`=================================`);
});
this.io = io;
}
setServerStatus(status: ServerStatus) {
this.emit(status);
this.status = status;
}
public getServer() {
return this.app;
}
private initializeMiddlewares() {
this.app.use(cors());
this.app.use(express.json());
this.app.use(express.urlencoded({ extended: true }));
this.app.use(express.static(App.staticFilesStoreDir()));
this.app.get('/logs', async (req, res) => {
const id = req.query.id;
if (id === undefined) {
return res.status(400).json('need req query id?=')
}
const calculationInstanceDBModel = await CalculationInstanceDBModel.findById(id)
if (calculationInstanceDBModel === null) {
return res.status(400).json("calcultaion db model is null");
}
const p = App.staticFilesStoreDir() + '/log.txt';
(await new WriteFileSystemFileUseCase().call(p, calculationInstanceDBModel.lastProcessLogs)).map(() => {
return res.sendFile(p);
})
})
this.app.use(
fileUpload({
createParentPath: true,
})
);
}
private initializeRoutes(routes: Routes[]) {
routes.forEach((route) => {
this.app.use("/", route.router);
});
}
async loadAppDependencies(): Promise<void> {
const dataBaseName = this.env === Environment.E2E_TEST ? "e2e_test" : "dev";
// TODO(IDONTSUDO):maybe convert it to a class and map it there
const result = await new DataBaseConnectUseCase().call(dataBaseName);
await result.fold(
async (_s) => {
await new CheckAndCreateStaticFilesFolderUseCase().call();
// await new SetLastActivePipelineToRealTimeServiceScenario().call();
},
async (_e) => {
this.setServerStatus(ServerStatus.error);
}
);
}
static staticFilesStoreDir = () => {
const dir = dirname(__filename);
const rootDir = dir.slice(0, dir.length - 20);
return rootDir + "public/";
};
}