refactor names

This commit is contained in:
srgooglo 2023-01-24 20:08:18 +01:00
parent 3d1513d2ca
commit ba42538c1d

View File

@ -1,18 +1,13 @@
const fs = require("fs") const fs = require("fs")
const http = require("http") const http = require("http")
const https = require("https") const https = require("https")
const io = require("socket.io") const io = require("socket.io")
const tokenizer = require("corenode/libs/tokenizer") const tokenizer = require("corenode/libs/tokenizer")
const { randomWord } = require("@corenode/utils")
const { serverManifest, outputServerError, internalConsole } = require("./lib") const { serverManifest, outputServerError, internalConsole } = require("./lib")
const InternalConsole = global.InternalInternalConsole = internalConsole const InternalConsole = global.InternalInternalConsole = internalConsole
const builtInMiddlewares = []
const HTTPProtocolsInstances = { const HTTPProtocolsInstances = {
http: http, http: http,
https: https, https: https,
@ -30,70 +25,56 @@ const HTTPEngines = {
}, },
} }
const linebridge_ascii = require("./linebridge_ascii.js")
class Server { class Server {
constructor(params = {}, controllers = [], middlewares = {}) { constructor(params = {}, controllers = {}, middlewares = {}, headers = {}) {
// register aliases
this.params = { this.params = {
...global.DEFAULT_SERVER_PARAMS, ...global.DEFAULT_SERVER_PARAMS,
...params ...params
} }
this.controllers = [
this.controllers = {
...controllers ...controllers
] }
this.middlewares = { this.middlewares = {
...middlewares ...middlewares.default ?? middlewares,
} }
this.headers = { this.headers = {
...global.DEFAULT_HEADERS, ...global.DEFAULT_SERVER_HEADERS,
...this.params.headers ...headers
} }
this.endpointsMap = {}
this.listenPort = this.params.port ?? 3010 this.endpoints_map = {}
// TODO: Handle HTTPS and WSS // fix and fulfill params
this.HTTPAddress = `${this.params.protocol}://${global.LOCALHOST_ADDRESS}:${this.listenPort}` this.params.listen_port = this.params.listen_port ?? 3000
this.WSAddress = `${this.params.wsProtocol}://${global.LOCALHOST_ADDRESS}:${this.listenPort}` this.params.http_protocol = this.params.http_protocol ?? "http"
this.params.ws_protocol = this.params.ws_protocol ?? "ws"
this.params.http_address = `${this.params.http_protocol}://${global.LOCALHOST_ADDRESS}:${this.params.listen_port}`
this.params.ws_address = `${this.params.ws_protocol}://${global.LOCALHOST_ADDRESS}:${this.params.listen_port}`
//* set server basics
// check if engine is supported // check if engine is supported
if (typeof HTTPProtocolsInstances[this.params.protocol].createServer !== "function") { if (typeof HTTPProtocolsInstances[this.params.http_protocol]?.createServer !== "function") {
throw new Error("Invalid HTTP protocol (Missing createServer function)") throw new Error("Invalid HTTP protocol (Missing createServer function)")
} }
this.engineInstance = global.engineInstance = HTTPEngines[this.params.httpEngine]() // create instances the 3 main instances of the server (Engine, HTTP, WebSocket)
this.httpInstance = global.httpInstance = HTTPProtocolsInstances[this.params.protocol].createServer({ this.engine_instance = global.engine_instance = HTTPEngines[this.params.engine]()
this.http_instance = global.http_instance = HTTPProtocolsInstances[this.params.http_protocol].createServer({
...this.params.httpOptions ?? {}, ...this.params.httpOptions ?? {},
}, this.engineInstance) }, this.engine_instance)
this.wsInterface = global.wsInterface = {
io: new io.Server(this.httpInstance), this.websocket_instance = global.websocket_instance = {
io: new io.Server(this.http_instance),
map: {}, map: {},
eventsChannels: [], eventsChannels: [],
} }
//? check if origin.server exists this.initializeManifest()
if (!fs.existsSync(serverManifest.filepath)) {
serverManifest.create()
}
//? check origin.server integrity
const MANIFEST_DATA = global.MANIFEST_DATA = serverManifest.get()
const MANIFEST_STAT = global.MANIFEST_STAT = serverManifest.stat()
if (typeof MANIFEST_DATA.created === "undefined") {
InternalConsole.warn("Server generation file not contains an creation date")
serverManifest.write({ created: Date.parse(MANIFEST_STAT.birthtime) })
}
if (typeof MANIFEST_DATA.serverToken === "undefined") {
InternalConsole.warn("Missing server token!")
serverManifest.create()
}
this.id = this.params.id ?? randomWord.generate() ?? "unavailable"
this.usid = tokenizer.generateUSID()
this.oskid = serverManifest.get("serverToken")
serverManifest.write({ lastStart: Date.now() })
// handle silent mode // handle silent mode
global.consoleSilent = this.params.silent global.consoleSilent = this.params.silent
@ -107,39 +88,67 @@ class Server {
} }
} }
// handle exit events
process.on("SIGTERM", this.cleanupProcess)
process.on("SIGINT", this.cleanupProcess)
return this return this
} }
initializeManifest = () => {
// check if origin.server exists
if (!fs.existsSync(serverManifest.filepath)) {
serverManifest.create()
}
// check origin.server integrity
const MANIFEST_DATA = global.MANIFEST_DATA = serverManifest.get()
const MANIFEST_STAT = global.MANIFEST_STAT = serverManifest.stat()
if (typeof MANIFEST_DATA.created === "undefined") {
InternalConsole.warn("Server generation file not contains an creation date")
serverManifest.write({ created: Date.parse(MANIFEST_STAT.birthtime) })
}
if (typeof MANIFEST_DATA.server_token === "undefined") {
InternalConsole.warn("Missing server token!")
serverManifest.create()
}
this.usid = tokenizer.generateUSID()
this.server_token = serverManifest.get("server_token")
serverManifest.write({ last_start: Date.now() })
}
initialize = async () => { initialize = async () => {
InternalConsole.log(linebridge_ascii)
InternalConsole.info(`🚀 Starting server...`)
//* set server defined headers //* set server defined headers
this.initializeHeaders() this.initializeHeaders()
//* set server defined middlewares //* set server defined middlewares
this.initializeMiddlewares() this.initializeRequiredMiddlewares()
//* register main index endpoint `/`
await this.registerBaseEndpoints()
//* register controllers //* register controllers
await this.initializeControllers() await this.initializeControllers()
//* register main index endpoint `/`
await this.registerBaseEndpoints()
// initialize main socket // initialize main socket
this.wsInterface.io.on("connection", this.handleWSClientConnection) this.websocket_instance.io.on("connection", this.handleWSClientConnection)
// initialize http server // initialize http server
await this.httpInstance.listen(this.listenPort, this.params.listen ?? "0.0.0.0") await this.http_instance.listen(this.params.listen_port, this.params.listen_ip ?? "0.0.0.0", () => {
// output server info
// output server info this.outputServerInfo()
InternalConsole.log(`✅ Server is up and running!`) })
this.OutputServerInfo()
// handle exit events
process.on("SIGTERM", this.cleanupProcess)
process.on("SIGINT", this.cleanupProcess)
} }
initializeHeaders = () => { initializeHeaders = () => {
this.engineInstance.use((req, res, next) => { this.engine_instance.use((req, res, next) => {
Object.keys(this.headers).forEach((key) => { Object.keys(this.headers).forEach((key) => {
res.setHeader(key, this.headers[key]) res.setHeader(key, this.headers[key])
}) })
@ -148,18 +157,20 @@ class Server {
}) })
} }
initializeMiddlewares = () => { initializeRequiredMiddlewares = () => {
const useMiddlewares = [...builtInMiddlewares, ...global.DEFAULT_MIDDLEWARES, ...(this.params.middlewares ?? [])] const useMiddlewares = [...this.params.useMiddlewares ?? [], ...global.DEFAULT_MIDDLEWARES]
useMiddlewares.forEach((middleware) => { useMiddlewares.forEach((middleware) => {
if (typeof middleware === "function") { if (typeof middleware === "function") {
this.engineInstance.use(middleware) this.engine_instance.use(middleware)
} }
}) })
} }
initializeControllers = async () => { initializeControllers = async () => {
for await (let controller of this.controllers) { const controllers = Object.entries(this.controllers)
for await (let [key, controller] of controllers) {
if (typeof controller !== "function") { if (typeof controller !== "function") {
throw new Error(`Controller must use the controller class!`) throw new Error(`Controller must use the controller class!`)
} }
@ -173,8 +184,8 @@ class Server {
const ControllerInstance = new controller() const ControllerInstance = new controller()
// get endpoints from controller (ComplexController) // get endpoints from controller (ComplexController)
const HTTPEndpoints = ControllerInstance.getEndpoints() const HTTPEndpoints = ControllerInstance.__get_http_endpoints()
const WSEndpoints = ControllerInstance.getWSEndpoints() const WSEndpoints = ControllerInstance.__get_ws_endpoints()
HTTPEndpoints.forEach((endpoint) => { HTTPEndpoints.forEach((endpoint) => {
this.registerHTTPEndpoint(endpoint, ...this.resolveMiddlewares(controller.useMiddlewares)) this.registerHTTPEndpoint(endpoint, ...this.resolveMiddlewares(controller.useMiddlewares))
@ -204,7 +215,7 @@ class Server {
} }
// check if method is supported // check if method is supported
if (typeof this.engineInstance[endpoint.method] !== "function") { if (typeof this.engine_instance[endpoint.method] !== "function") {
throw new Error(`Method [${endpoint.method}] is not supported!`) throw new Error(`Method [${endpoint.method}] is not supported!`)
} }
@ -216,19 +227,19 @@ class Server {
} }
// make sure method has root object on endpointsMap // make sure method has root object on endpointsMap
if (typeof this.endpointsMap[endpoint.method] !== "object") { if (typeof this.endpoints_map[endpoint.method] !== "object") {
this.endpointsMap[endpoint.method] = {} this.endpoints_map[endpoint.method] = {}
} }
// create model for http interface router // create model for http interface router
const routeModel = [endpoint.route, ...middlewares, this.createHTTPRequestHandler(endpoint)] const routeModel = [endpoint.route, ...middlewares, this.createHTTPRequestHandler(endpoint)]
// register endpoint to http interface router // register endpoint to http interface router
this.engineInstance[endpoint.method](...routeModel) this.engine_instance[endpoint.method](...routeModel)
// extend to map // extend to map
this.endpointsMap[endpoint.method] = { this.endpoints_map[endpoint.method] = {
...this.endpointsMap[endpoint.method], ...this.endpoints_map[endpoint.method],
[endpoint.route]: { [endpoint.route]: {
route: endpoint.route, route: endpoint.route,
enabled: endpoint.enabled ?? true, enabled: endpoint.enabled ?? true,
@ -239,9 +250,9 @@ class Server {
registerWSEndpoint = (endpoint, ...execs) => { registerWSEndpoint = (endpoint, ...execs) => {
endpoint.nsp = endpoint.nsp ?? "/main" endpoint.nsp = endpoint.nsp ?? "/main"
this.wsInterface.eventsChannels.push([endpoint.nsp, endpoint.on, endpoint.dispatch]) this.websocket_instance.eventsChannels.push([endpoint.nsp, endpoint.on, endpoint.dispatch])
this.wsInterface.map[endpoint.on] = { this.websocket_instance.map[endpoint.on] = {
nsp: endpoint.nsp, nsp: endpoint.nsp,
channel: endpoint.on, channel: endpoint.on,
} }
@ -261,53 +272,47 @@ class Server {
fn: (req, res) => { fn: (req, res) => {
return res.json({ return res.json({
LINEBRIDGE_SERVER_VERSION: LINEBRIDGE_SERVER_VERSION, LINEBRIDGE_SERVER_VERSION: LINEBRIDGE_SERVER_VERSION,
id: this.id,
usid: this.usid, usid: this.usid,
oskid: this.oskid,
requestTime: new Date().getTime(), requestTime: new Date().getTime(),
endpointsMap: this.endpointsMap, endpointsMap: this.endpoints_map,
wsEndpointsMap: this.wsInterface.map, wsEndpointsMap: this.websocket_instance.map,
}) })
} }
}) })
} }
//* resolvers //* resolvers
resolveMiddlewares = (middlewares) => { resolveMiddlewares = (requestedMiddlewares) => {
middlewares = Array.isArray(middlewares) ? middlewares : [middlewares] requestedMiddlewares = Array.isArray(requestedMiddlewares) ? requestedMiddlewares : [requestedMiddlewares]
const middlewaresArray = []
middlewares.forEach((middleware) => { const execs = []
if (typeof middleware === "string") {
if (typeof this.middlewares[middleware] !== "function") { requestedMiddlewares.forEach((middlewareKey) => {
throw new Error(`Middleware ${middleware} not found!`) if (typeof middlewareKey === "string") {
if (typeof this.middlewares[middlewareKey] !== "function") {
throw new Error(`Middleware ${middlewareKey} not found!`)
} }
middlewaresArray.push(this.middlewares[middleware]) execs.push(this.middlewares[middlewareKey])
} }
if (typeof middleware === "function") { if (typeof middlewareKey === "function") {
middlewaresArray.push(middleware) execs.push(middlewareKey)
} }
}) })
return middlewaresArray return execs
} }
log = (...args) => {
if (!this.params.silent) {
InternalConsole.log(...args)
}
}
cleanupProcess = () => { cleanupProcess = () => {
this.log("🛑 Stopping server...") InternalConsole.log("🛑 Stopping server...")
if (typeof this.engineInstance.close === "function") { if (typeof this.engine_instance.close === "function") {
this.engineInstance.close() this.engine_instance.close()
} }
this.wsInterface.io.close() this.websocket_instance.io.close()
process.exit(1) process.exit(1)
} }
@ -317,7 +322,7 @@ class Server {
return async (req, res) => { return async (req, res) => {
try { try {
// check if endpoint is disabled // check if endpoint is disabled
if (!this.endpointsMap[endpoint.method][endpoint.route].enabled) { if (!this.endpoints_map[endpoint.method][endpoint.route].enabled) {
throw new Error("Endpoint is disabled!") throw new Error("Endpoint is disabled!")
} }
@ -355,7 +360,7 @@ class Server {
await this.params.onWSClientConnection(client) await this.params.onWSClientConnection(client)
} }
for await (const [nsp, on, dispatch] of this.wsInterface.eventsChannels) { for await (const [nsp, on, dispatch] of this.websocket_instance.eventsChannels) {
client.on(on, async (...args) => { client.on(on, async (...args) => {
try { try {
await dispatch(client, ...args).catch((error) => { await dispatch(client, ...args).catch((error) => {
@ -383,30 +388,28 @@ class Server {
} }
// public methods // public methods
OutputServerInfo = () => { outputServerInfo = () => {
InternalConsole.log(`🌐 Server info:`) InternalConsole.log("✅ Ready !")
InternalConsole.table({ InternalConsole.table({
"ID": this.id, "linebridge_version": LINEBRIDGE_SERVER_VERSION,
"HTTPEngine": this.params.httpEngine, "engine": this.params.engine,
"Version": LINEBRIDGE_SERVER_VERSION, "http_address": this.params.http_address,
"WS Protocol": this.params.wsProtocol, "websocket_address": this.params.ws_address,
"Protocol": this.params.protocol, "listen_port": this.params.listen_port,
"HTTP address": this.HTTPAddress,
"WS address": this.WSAddress,
"Listen port": this.listenPort,
}) })
} }
toogleEndpointReachability = (method, route, enabled) => { toogleEndpointReachability = (method, route, enabled) => {
if (typeof this.endpointsMap[method] !== "object") { if (typeof this.endpoints_map[method] !== "object") {
throw new Error(`Cannot toogle endpoint, method [${method}] not set!`) throw new Error(`Cannot toogle endpoint, method [${method}] not set!`)
} }
if (typeof this.endpointsMap[method][route] !== "object") { if (typeof this.endpoints_map[method][route] !== "object") {
throw new Error(`Cannot toogle endpoint [${route}], is not registered!`) throw new Error(`Cannot toogle endpoint [${route}], is not registered!`)
} }
this.endpointsMap[method][route].enabled = enabled ?? !this.endpointsMap[method][route].enabled this.endpoints_map[method][route].enabled = enabled ?? !this.endpoints_map[method][route].enabled
} }
} }