From 90086aa083b369a4b34b65fd4bc0fe33af220458 Mon Sep 17 00:00:00 2001 From: SrGooglo Date: Thu, 18 May 2023 12:53:17 +0000 Subject: [PATCH] added file server --- packages/file_server/package.json | 40 +++++++++++ packages/file_server/src/api.js | 115 ++++++++++++++++++++++++++++++ packages/file_server/src/index.js | 56 +++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 packages/file_server/package.json create mode 100644 packages/file_server/src/api.js create mode 100644 packages/file_server/src/index.js diff --git a/packages/file_server/package.json b/packages/file_server/package.json new file mode 100644 index 00000000..5aadea14 --- /dev/null +++ b/packages/file_server/package.json @@ -0,0 +1,40 @@ +{ + "name": "@comty/file_server", + "version": "0.45.2", + "main": "dist/index.js", + "scripts": { + "build": "corenode-cli build", + "dev": "cross-env NODE_ENV=development nodemon --ignore dist/ --exec corenode-node ./src/index.js" + }, + "license": "MIT", + "dependencies": { + "@foxify/events": "^2.1.0", + "@octokit/rest": "^19.0.7", + "axios": "^1.4.0", + "bcrypt": "^5.1.0", + "busboy": "^1.6.0", + "content-range": "^2.0.2", + "corenode": "0.28.26", + "dotenv": "^16.0.3", + "hyper-express": "^6.5.9", + "jsonwebtoken": "^9.0.0", + "linebridge": "0.15.12", + "live-directory": "^3.0.3", + "merge-files": "^0.1.2", + "mime-types": "^2.1.35", + "minio": "^7.0.32", + "moment": "^2.29.4", + "moment-timezone": "^0.5.40", + "normalize-url": "^8.0.0", + "p-map": "^6.0.0", + "p-queue": "^7.3.4", + "redis": "^4.6.6", + "split-chunk-merge": "^1.0.0" + }, + "devDependencies": { + "chai": "^4.3.7", + "cross-env": "^7.0.3", + "mocha": "^10.2.0", + "nodemon": "^2.0.15" + } +} diff --git a/packages/file_server/src/api.js b/packages/file_server/src/api.js new file mode 100644 index 00000000..237a6ae1 --- /dev/null +++ b/packages/file_server/src/api.js @@ -0,0 +1,115 @@ +import fs from "fs" +import path from "path" + +//import RedisClient from "@classes/RedisClient" +import StorageClient from "@classes/StorageClient" + +import hyperexpress from "hyper-express" + +import pkg from "../package.json" + +export default class FileServerAPI { + server = global.server = new hyperexpress.Server() + + listenIp = process.env.HTTP_LISTEN_IP ?? "0.0.0.0" + listenPort = process.env.HTTP_LISTEN_PORT ?? 3006 + + internalRouter = new hyperexpress.Router() + + //redis = global.redis = RedisClient() + + storage = global.storage = StorageClient() + + async __loadControllers() { + let controllersPath = fs.readdirSync(path.resolve(__dirname, "controllers")) + + for await (const controllerPath of controllersPath) { + const controller = require(path.resolve(__dirname, "controllers", controllerPath)).default + + if (!controller) { + this.server.InternalConsole.error(`Controller ${controllerPath} not found.`) + + continue + } + + const handler = controller(new hyperexpress.Router()) + + if (!handler) { + this.server.InternalConsole.error(`Controller ${controllerPath} returning not valid handler.`) + + continue + } + + this.internalRouter.use(handler.path ?? "/", handler.router) + + continue + } + } + + async __loadMiddlewares() { + let middlewaresPath = fs.readdirSync(path.resolve(__dirname, "middlewares")) + + for await (const middlewarePath of middlewaresPath) { + const middleware = require(path.resolve(__dirname, "middlewares", middlewarePath)).default + + if (!middleware) { + this.server.InternalConsole.error(`Middleware ${middlewarePath} not found.`) + + continue + } + + this.server.use(middleware) + } + } + + __getRegisteredRoutes() { + return this.internalRouter.routes.map((route) => { + return { + method: route.method, + path: route.pattern, + } + }) + } + + __registerInternalRoutes() { + this.server.get("/", (req, res) => { + return res.status(200).json({ + name: pkg.name, + version: pkg.version, + routes: this.__getRegisteredRoutes() + }) + }) + + this.server.any("*", (req, res) => { + return res.status(404).json({ + error: "Not found", + }) + }) + } + + async initialize() { + const startHrTime = process.hrtime() + + // initialize clients + await this.redis.initialize() + await this.storage.initialize() + + // register controllers & middlewares + await this.__registerInternalRoutes() + await this.__loadControllers() + await this.__loadMiddlewares() + + // use internal router + this.server.use(this.internalRouter) + + // start server + await this.server.listen(this.listenPort, this.listenIp) + + // calculate elapsed time + const elapsedHrTime = process.hrtime(startHrTime) + const elapsedTimeInMs = elapsedHrTime[0] * 1000 + elapsedHrTime[1] / 1e6 + + // log server started + console.log(`🚀 Server started ready on \n\t - http://${this.listenIp}:${this.listenPort} \n\t - Tooks ${elapsedTimeInMs}ms`) + } +} \ No newline at end of file diff --git a/packages/file_server/src/index.js b/packages/file_server/src/index.js new file mode 100644 index 00000000..acb48ba9 --- /dev/null +++ b/packages/file_server/src/index.js @@ -0,0 +1,56 @@ +require("dotenv").config() +import { webcrypto as crypto } from "crypto" +import path from "path" +import { registerBaseAliases } from "linebridge/dist/server" + +registerBaseAliases(undefined, { + "@services": path.resolve(__dirname, "services"), +}) + +// patches +const { Buffer } = require("buffer") + +global.b64Decode = (data) => { + return Buffer.from(data, "base64").toString("utf-8") +} +global.b64Encode = (data) => { + return Buffer.from(data, "utf-8").toString("base64") +} + +global.nanoid = (t = 21) => crypto.getRandomValues(new Uint8Array(t)).reduce(((t, e) => t += (e &= 63) < 36 ? e.toString(36) : e < 62 ? (e - 26).toString(36).toUpperCase() : e > 62 ? "-" : "_"), ""); + +Array.prototype.updateFromObjectKeys = function (obj) { + this.forEach((value, index) => { + if (obj[value] !== undefined) { + this[index] = obj[value] + } + }) + + return this +} + +global.toBoolean = (value) => { + if (typeof value === "boolean") { + return value + } + + if (typeof value === "string") { + return value.toLowerCase() === "true" + } + + return false +} + +global.isProduction = process.env.NODE_ENV === "production" + +import API from "./api" + +async function main() { + const mainAPI = new API() + + await mainAPI.initialize() +} + +main().catch((error) => { + console.error(`🆘 [FATAL ERROR] >`, error) +}) \ No newline at end of file