outers
Version:
outers - a all in one package for your day to day use
285 lines • 20.7 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _CreateClusterByClass_ExpressServer, _CreateClusterByClass_PORT, _CreateClusterByClass_NumberOfWorkers, _CreateClusterByClass_BeforeListenFunctions, _CreateClusterByClass_AfterListenFunctions, _CreateClusterByClass_FunctionMiddlewares, _CreateClusterByClass_GlobalResponseObject, _CreateClusterByClass_EnableTrustProxy;
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
// main code for creating a cluster in node js
const node_os_1 = require("node:os"); // Import os module
const express_1 = __importDefault(require("express")); // Import express module
const node_cluster_1 = __importDefault(require("node:cluster")); // Import Cluster module
const { isPrimary } = node_cluster_1.default; // Import isPrimary from Cluster
const Console_log_1 = require("../../Logs/Console.log"); // Import Console module
// Main Class
class CreateClusterByClass {
// Constructor
/**
* Creates an instance of the server configuration class.
* This constructor initializes the server with the specified Express server, port,
* and optional configurations for workers, middleware, and pre/post listen functions.
*
* @param {Express} ExpressServer - The Express server instance. If not provided, a new Express instance is created.
* @param {number} PORT - The port number on which the Express server will listen.
* @param {number} [NumberOfWorkers=cpus().length] - Optional. The number of worker processes to spawn in cluster mode.
* Defaults to the number of CPU cores available.
* @param {Function[]} [BeforeListenFunctions=[]] - Optional. An array of functions to execute before the server starts listening.
* @param {Function[]} [AfterListenFunctions=[]] - Optional. An array of functions to execute after the server starts listening.
* @param {Function[]} [FunctionMiddlewares=[]] - Optional. An array of middleware functions to apply to the Express server.
*/
constructor(ExpressServer, PORT, NumberOfWorkers, BeforeListenFunctions, AfterListenFunctions, FunctionMiddlewares, EnableTrustProxy) {
// Properties
_CreateClusterByClass_ExpressServer.set(this, void 0); // Express Server Instance
_CreateClusterByClass_PORT.set(this, void 0); // Port Number to Listen
// Private Properties
_CreateClusterByClass_NumberOfWorkers.set(this, void 0); // Number of Copies of Workers
_CreateClusterByClass_BeforeListenFunctions.set(this, void 0); // Any Functions to run before listen
_CreateClusterByClass_AfterListenFunctions.set(this, void 0); // Any Functions to run after listen
_CreateClusterByClass_FunctionMiddlewares.set(this, void 0); // Any Middlewares to apply
_CreateClusterByClass_GlobalResponseObject.set(this, void 0); // Any ResponseObject
_CreateClusterByClass_EnableTrustProxy.set(this, void 0); // Enable Trust Proxy
__classPrivateFieldSet(this, _CreateClusterByClass_ExpressServer, ExpressServer !== null && ExpressServer !== void 0 ? ExpressServer : (0, express_1.default)(), "f"); // Express Server Instance
__classPrivateFieldSet(this, _CreateClusterByClass_PORT, PORT, "f"); // Active Server Instance
__classPrivateFieldSet(this, _CreateClusterByClass_NumberOfWorkers, NumberOfWorkers !== null && NumberOfWorkers !== void 0 ? NumberOfWorkers : (0, node_os_1.cpus)().length, "f"); // Number of Copies of Workers
__classPrivateFieldSet(this, _CreateClusterByClass_BeforeListenFunctions, BeforeListenFunctions !== null && BeforeListenFunctions !== void 0 ? BeforeListenFunctions : [], "f"); // Any Functions to run before listen
__classPrivateFieldSet(this, _CreateClusterByClass_AfterListenFunctions, AfterListenFunctions !== null && AfterListenFunctions !== void 0 ? AfterListenFunctions : [], "f"); // Any Functions to run after listen
__classPrivateFieldSet(this, _CreateClusterByClass_FunctionMiddlewares, FunctionMiddlewares !== null && FunctionMiddlewares !== void 0 ? FunctionMiddlewares : [], "f"); // Any Middlewares to apply
__classPrivateFieldSet(this, _CreateClusterByClass_GlobalResponseObject, {
ActiveServer: __classPrivateFieldGet(this, _CreateClusterByClass_ExpressServer, "f"),
ActiveWorker: __classPrivateFieldGet(this, _CreateClusterByClass_NumberOfWorkers, "f"),
TotalBeforeFunctions: __classPrivateFieldGet(this, _CreateClusterByClass_BeforeListenFunctions, "f").length,
TotalAfterFunctions: __classPrivateFieldGet(this, _CreateClusterByClass_AfterListenFunctions, "f").length,
ActiveMiddlewares: __classPrivateFieldGet(this, _CreateClusterByClass_FunctionMiddlewares, "f"),
TotalCPU: (0, node_os_1.cpus)().length,
TotalFreeRam: `${((0, node_os_1.freemem)() / 1024 / 1024 / 1024).toFixed(2)} GB`,
TotalRam: `${((0, node_os_1.totalmem)() / 1024 / 1024 / 1024).toFixed(2)} GB`,
Architecture: (0, node_os_1.arch)(),
Platform: (0, node_os_1.platform)(),
}, "f");
__classPrivateFieldSet(this, _CreateClusterByClass_EnableTrustProxy, EnableTrustProxy !== null && EnableTrustProxy !== void 0 ? EnableTrustProxy : false, "f"); // Enable Trust Proxy
}
// Start Server Method
/**
* Starts the server using the configured Express instance and port. It initializes
* workers based on the number of workers specified if running in a cluster mode.
* This method also applies any configured middlewares and executes before and after
* listen functions as part of the server startup process.
*
* @returns {Promise<ResponseObject | undefined>} A promise that resolves to a ResponseObject
* containing the server and active worker information if the server starts successfully, or
* undefined if an error occurs.
* @throws {Error} Throws an error if the Express server instance or port is not provided.
*
* The method leverages clustering if `isPrimary` is true, creating workers and managing
* their lifecycle. For the worker processes, or when `isPrimary` is false, it applies
* middlewares, runs before listen functions, starts the Express server, and then runs
* after listen functions.
*
* Note: `Console` is used for logging, and `ClusterConfig`, `platform`, `arch`, `freemem`,
* `cpus` are assumed to be available in the scope for cluster and system information logging.
*/
StartServer() {
return __awaiter(this, void 0, void 0, function* () {
// Check if User Provided Express Server or not
if (!__classPrivateFieldGet(this, _CreateClusterByClass_ExpressServer, "f") || !__classPrivateFieldGet(this, _CreateClusterByClass_ExpressServer, "f") === undefined) {
throw new Error("Express Server is not provided"); // Error Message for Server Start
}
// Check if User Provided Port or not
if (!__classPrivateFieldGet(this, _CreateClusterByClass_PORT, "f") || __classPrivateFieldGet(this, _CreateClusterByClass_PORT, "f") === undefined) {
throw new Error("Port is not provided"); // Error Message for Server Start
}
// Number of Workers to be forked
let ProcessCopy = __classPrivateFieldGet(this, _CreateClusterByClass_NumberOfWorkers, "f"); // Copy Number of Workers
if (isPrimary) {
// If the cluster is the primary node
// Print CPU Count
(0, Console_log_1.bright)(`${(0, node_os_1.platform)()} ${(0, node_os_1.arch)()} server : ${((0, node_os_1.freemem)() /
1024 /
1024 /
1024).toFixed(2)} GB Free Ram : ${(0, node_os_1.cpus)()[0].model}`);
// Create a worker according to the number that is specified
while (ProcessCopy > 0) {
node_cluster_1.default.fork();
ProcessCopy--;
}
// Listen for Cluster Online
node_cluster_1.default.on("online", (worker) => {
(0, Console_log_1.green)(`🚀 Worker ${worker.process.pid} started 🚀`);
(0, Console_log_1.blue)(`Environment Variables Loaded Successfully in Worker : ${worker.process.pid}`);
__classPrivateFieldGet(this, _CreateClusterByClass_GlobalResponseObject, "f").ActiveWorker++; // Increment Active Worker Count by 1
(0, Console_log_1.yellow)(`Worker ${worker.process.pid} is listening`);
});
// Listen for Cluster Exit
node_cluster_1.default.on("exit", (worker) => {
(0, Console_log_1.red)(`Worker ${worker.process.pid} died`);
__classPrivateFieldGet(this, _CreateClusterByClass_GlobalResponseObject, "f").ActiveWorker++; // Increment Active Worker Count by 1
node_cluster_1.default.fork();
(0, Console_log_1.green)(`🚀 Worker ${worker.process.pid} restarted 🚀`);
(0, Console_log_1.blue)(`Environment Variables Loaded Successfully in Worker : ${worker.process.pid}`);
__classPrivateFieldGet(this, _CreateClusterByClass_GlobalResponseObject, "f").ActiveWorker++; // Increment Active Worker Count by 1
(0, Console_log_1.yellow)(`Worker ${worker.process.pid} is listening`);
});
}
else {
// Enable trust proxy for Express Server
__classPrivateFieldGet(this, _CreateClusterByClass_EnableTrustProxy, "f") === true
? __classPrivateFieldGet(this, _CreateClusterByClass_ExpressServer, "f").set("trust proxy", true)
: (0, Console_log_1.yellow)("Trust Proxy is not enabled, if you are working behind a proxy, please enable it to get the real IP Address");
// Apply Function Middlewares to Express Server Instance like CORS, Body Parser, etc.
if (__classPrivateFieldGet(this, _CreateClusterByClass_FunctionMiddlewares, "f").length > 0 ||
__classPrivateFieldGet(this, _CreateClusterByClass_FunctionMiddlewares, "f") !== undefined) {
__classPrivateFieldGet(this, _CreateClusterByClass_FunctionMiddlewares, "f").forEach((FunctionMiddleware) => {
__classPrivateFieldGet(this, _CreateClusterByClass_ExpressServer, "f").use(FunctionMiddleware); // Apply Middleware to Express Server Instance one by one
}); // Apply Middlewares to Express Server Instance
}
// Run Before Listen Functions
if (__classPrivateFieldGet(this, _CreateClusterByClass_BeforeListenFunctions, "f").length > 0 ||
__classPrivateFieldGet(this, _CreateClusterByClass_BeforeListenFunctions, "f") !== undefined) {
for (const ListenFunction of __classPrivateFieldGet(this, _CreateClusterByClass_BeforeListenFunctions, "f")) {
yield ListenFunction(); // Run Before Listen Functions one by one
}
}
// Server Listen
try {
const ActiveServer = __classPrivateFieldGet(this, _CreateClusterByClass_ExpressServer, "f").listen(__classPrivateFieldGet(this, _CreateClusterByClass_PORT, "f"), () => __awaiter(this, void 0, void 0, function* () {
(0, Console_log_1.green)(`🚀 Server is listening on Port ${__classPrivateFieldGet(this, _CreateClusterByClass_PORT, "f")} 🚀`); // Print Message for Server Start
// Run After Listen Functions
if (__classPrivateFieldGet(this, _CreateClusterByClass_AfterListenFunctions, "f").length > 0 ||
__classPrivateFieldGet(this, _CreateClusterByClass_AfterListenFunctions, "f") !== undefined) {
for (const ListenFunction of __classPrivateFieldGet(this, _CreateClusterByClass_AfterListenFunctions, "f")) {
yield ListenFunction(); // Run Function one by one
}
}
})); // Start Server on Port
// Return the Active Server Instance in Response Object
__classPrivateFieldGet(this, _CreateClusterByClass_GlobalResponseObject, "f").ActiveServer = ActiveServer; // Active Server Instance After Listen
return Object.freeze(__classPrivateFieldGet(this, _CreateClusterByClass_GlobalResponseObject, "f")); // Return Response Object to User for further use
}
catch (error) {
(0, Console_log_1.red)(`Error in Starting Server : ${error}`); // Print Error Message for Server Start
return Object.freeze(Object.assign({ Error: error }, __classPrivateFieldGet(this, _CreateClusterByClass_GlobalResponseObject, "f"))); // Return Error to User
}
}
});
}
// Set Number of Workers Method
/**
* Sets the number of worker processes to be used in cluster mode.
* This method updates the instance's number of workers with the provided value,
* ensuring that it is a positive number.
*
* @param {number} NumberOfWorkers - The new number of worker processes to be set.
* Must be a positive integer.
* @throws {Error} Throws an error if `NumberOfWorkers` is not provided,
* is not a number, or is less than or equal to zero.
*/
SetNumberOfWorkers(NumberOfWorkers) {
if (!NumberOfWorkers) {
throw new Error("Number of Workers is not provided"); // Error Message for Server Start
}
if (typeof NumberOfWorkers !== "number") {
throw new Error("Number of Workers is not a Number"); // Error Message for Server Start
}
if (NumberOfWorkers <= 0) {
throw new Error("Number of Workers is not a Positive Number"); // Error Message for Server Start
}
// Update Number of Workers
__classPrivateFieldSet(this, _CreateClusterByClass_NumberOfWorkers, NumberOfWorkers, "f"); // Set Number of Workers
}
// Add Before Listen Function Method
/**
* Adds a function to be executed before the server starts listening.
* This method appends the provided function to the list of functions to run
* before the server starts listening for incoming requests.
*
* @param {Function} FunctionToRun - The function to be added to the list of functions to run.
* @throws {Error} Throws an error if `FunctionToRun` is not provided or is not a function.
*/
AddBeforeListenFunction(FunctionToRun) {
if (!FunctionToRun) {
throw new Error("Function to Run is not provided"); // Error Message for Server Start
}
if (typeof FunctionToRun !== "function") {
throw new Error("Function to Run is not a Function"); // Error Message for Server Start
}
__classPrivateFieldGet(this, _CreateClusterByClass_BeforeListenFunctions, "f").push(FunctionToRun); // Add Function to Before Listen Functions
}
// Add After Listen Function Method
/**
* Adds a function to be executed after the server starts listening.
* This method appends the provided function to the list of functions to run
* after the server starts listening for incoming requests.
*
* @param {Function} FunctionToRun - The function to be added to the list of functions to run.
* @throws {Error} Throws an error if `FunctionToRun` is not provided or is not a function.
*/
AddAfterListenFunction(FunctionToRun) {
if (!FunctionToRun) {
throw new Error("Function to Run is not provided"); // Error Message for Server Start
}
if (typeof FunctionToRun !== "function") {
throw new Error("Function to Run is not a Function"); // Error Message for Server Start
}
__classPrivateFieldGet(this, _CreateClusterByClass_AfterListenFunctions, "f").push(FunctionToRun); // Add Function to After Listen Functions
}
// Add Function Middleware Method
/**
* Adds a middleware function to the list of middleware functions to be applied
* to the Express server instance.
*
* @param {Function} FunctionToRun - The function to be added to the list of middleware functions to run.
* @throws {Error} Throws an error if `FunctionToRun` is not provided or is not a function.
*/
AddFunctionMiddleware(FunctionToRun) {
if (!FunctionToRun) {
throw new Error("Function to Run is not provided"); // Error Message for Server Start
}
if (typeof FunctionToRun !== "function") {
throw new Error("Function to Run is not a Function"); // Error Message for Server Start
}
__classPrivateFieldGet(this, _CreateClusterByClass_FunctionMiddlewares, "f").push(FunctionToRun); // Add Function to Function Middlewares
}
// Enable Trust Proxy Method
/**
* Controls the Trust Proxy setting.
* @param {boolean} Status - The value indicating whether to enable or disable Trust Proxy.
* @throws {Error} If Trust Proxy is already enabled.
* @throws {Error} If the provided value is not a boolean.
*/
ControlTrustProxy(Status) {
// Check if Trust Proxy is already enabled or not
if (__classPrivateFieldGet(this, _CreateClusterByClass_EnableTrustProxy, "f") === true) {
throw new Error("Trust Proxy is already enabled"); // Error Message for Server Start
}
// Check inserted value is boolean or not
if (typeof Status !== "boolean") {
throw new Error("TPlease provide a boolean value to enable Trust Proxy"); // Error Message for Server Start
}
// Enable Trust Proxy
__classPrivateFieldSet(this, _CreateClusterByClass_EnableTrustProxy, Status, "f"); // Enable Trust Proxy
}
}
_CreateClusterByClass_ExpressServer = new WeakMap(), _CreateClusterByClass_PORT = new WeakMap(), _CreateClusterByClass_NumberOfWorkers = new WeakMap(), _CreateClusterByClass_BeforeListenFunctions = new WeakMap(), _CreateClusterByClass_AfterListenFunctions = new WeakMap(), _CreateClusterByClass_FunctionMiddlewares = new WeakMap(), _CreateClusterByClass_GlobalResponseObject = new WeakMap(), _CreateClusterByClass_EnableTrustProxy = new WeakMap();
exports.default = CreateClusterByClass;
//# sourceMappingURL=CreateClusterByClass.method.js.map