Browse Source

extsress v1.0.0

CrazyDoctor 3 days ago
parent
commit
a5106cca43

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+<div align="center">
+<img src="extress-logo.png" alt="Extress Logo" height="256">
+</div>

+ 111 - 0
bin/extress.ts

@@ -0,0 +1,111 @@
+#!/usr/bin/env node
+import * as fs from 'fs';
+import * as path from 'path';
+import { ServerProperties } from '../lib';
+
+class Extress {
+	private static Init: string = 'init';
+
+	private static args: string[] = process.argv.slice(2);
+	private static command: string | undefined = Extress.args[0];
+	private static cwd: string = process.cwd();
+	private static configPath: string = path.join(Extress.cwd, 'config.json');
+	private static srcPath: string = path.join(Extress.cwd, 'src');
+	private static middlewaresPath: string = path.join(Extress.srcPath, 'middlewares');
+	private static routesPath: string = path.join(Extress.srcPath, 'routes');
+
+	private static exitWithError(message: string): never {
+		return console.error(message), process.exit(1);
+	}
+
+	private static loadConfig(): ServerProperties {
+		if(!fs.existsSync(Extress.configPath))
+			Extress.exitWithError('config.json not found in current directory');
+
+		try {
+			const content: string = fs.readFileSync(Extress.configPath, 'utf-8');
+			return JSON.parse(content) as ServerProperties;
+		} catch (error) {
+			const message = error instanceof Error ? error.message : String(error);
+			Extress.exitWithError(`Failed to read config.json: ${message}`);
+		}
+	}
+
+	private static getDefaultConfig(): ServerProperties {
+		return {
+			port: 3000,
+			middlewaresPath: './src/middlewares',
+			routesPath: './src/routes',
+			json: false,
+			urlencoded: false,
+			sessions: false
+		};
+	}
+
+	private static init(): void {
+		if(fs.existsSync(Extress.configPath))
+			return console.log('config.json already exists');
+
+		const serverCode =
+			'import { Server as ExtressServer } from \'extress\';\n\n' +
+			'class Server {\n' +
+			'\tpublic static async start(): Promise<ExtressServer> {\n' +
+			'\t\treturn new ExtressServer().init().then((server: Server) => {\n' +
+			'\t\t\treturn server.start(), server;\n' +
+			'\t\t});\n' +
+			'\t}\n' +
+			'}\n\n' +
+			'export default Server;';
+		
+		const indexCode =
+			'import Server from \'./Server\';\n\n' +
+			'Server.start();';
+		
+		const exampleMiddleware =
+			'import { Middleware, NextFunction, Request, Response } from \'extress\';\n\n' +
+			'class DefaultMiddleware extends Middleware {\n' +
+			'\tprotected action = (req: Request, res: Response, next: NextFunction) => {\n' +
+			'\t\tnext();\n' +
+			'\t};\n' +
+			'\tprotected order: number = 0;\n' +
+			'\tprotected route: string | null = null;\n' +
+			'}\n\n' +
+			'export default DefaultMiddleware;';
+		
+		const exampleRoute =
+			'import { Route, Request, Response, HttpMethod } from \'extress\';\n\n' +
+			'class GetIndex extends Route {\n' +
+			'\tprotected action = (req: Request, res: Response) => {\n' +
+			'\t\tres.status(200).send(\'Welcome to Extress!\');\n' +
+			'\t};\n' +
+			'\tprotected route: string | null = \'/\';\n' +
+			'\tprotected method: HttpMethod = HttpMethod.GET;\n' +
+			'}\n\n' +
+			'export default GetIndex;';
+
+		fs.mkdirSync(Extress.srcPath);
+		fs.mkdirSync(Extress.middlewaresPath);
+		fs.mkdirSync(Extress.routesPath);
+
+		fs.writeFileSync(path.join(Extress.middlewaresPath, 'DefaultMiddleware.ts'), exampleMiddleware);
+		fs.writeFileSync(path.join(Extress.routesPath, 'GetIndex.ts'), exampleRoute);
+		fs.writeFileSync(path.join(Extress.srcPath, 'Server.ts'), serverCode);
+		fs.writeFileSync(path.join(Extress.srcPath, 'index.ts'), indexCode);
+
+		fs.writeFileSync(Extress.configPath, JSON.stringify(Extress.getDefaultConfig(), null, 2), 'utf-8');
+		console.log('Project initialized successfully.');
+	}
+
+	private static printUsage(): void {
+		console.log('Usage:\nextress init');
+	}
+
+	public static run(): void {
+		switch (Extress.command) {
+		case Extress.Init: return Extress.init();
+		default: return Extress.printUsage();
+		}
+	}
+}
+
+Extress.run();

+ 35 - 0
dist/bin/extress.js

@@ -0,0 +1,35 @@
+#!/usr/bin/env node
+"use strict";var l=Object.create;var c=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var f=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty;var h=(t,e,s,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of u(e))!g.call(t,i)&&i!==s&&c(t,i,{get:()=>e[i],enumerable:!(o=p(e,i))||o.enumerable});return t};var d=(t,e,s)=>(s=t!=null?l(f(t)):{},h(e||!t||!t.__esModule?c(s,"default",{value:t,enumerable:!0}):s,t));var r=d(require("fs")),n=d(require("path")),a=class t{static{this.Init="init"}static{this.args=process.argv.slice(2)}static{this.command=t.args[0]}static{this.cwd=process.cwd()}static{this.configPath=n.join(t.cwd,"config.json")}static{this.srcPath=n.join(t.cwd,"src")}static{this.middlewaresPath=n.join(t.srcPath,"middlewares")}static{this.routesPath=n.join(t.srcPath,"routes")}static exitWithError(e){return console.error(e),process.exit(1)}static loadConfig(){r.existsSync(t.configPath)||t.exitWithError("config.json not found in current directory");try{let e=r.readFileSync(t.configPath,"utf-8");return JSON.parse(e)}catch(e){let s=e instanceof Error?e.message:String(e);t.exitWithError(`Failed to read config.json: ${s}`)}}static getDefaultConfig(){return{port:3e3,middlewaresPath:"./src/middlewares",routesPath:"./src/routes",json:!1,urlencoded:!1,sessions:!1}}static init(){if(r.existsSync(t.configPath))return console.log("config.json already exists");let e=`import { Server as ExtressServer } from 'extress';
+
+class Server {
+	public static async start(): Promise<ExtressServer> {
+		return new ExtressServer().init().then((server: Server) => {
+			return server.start(), server;
+		});
+	}
+}
+
+export default Server;`,s=`import Server from './Server';
+
+Server.start();`,o=`import { Middleware, NextFunction, Request, Response } from 'extress';
+
+class DefaultMiddleware extends Middleware {
+	protected action = (req: Request, res: Response, next: NextFunction) => {
+		next();
+	};
+	protected order: number = 0;
+	protected route: string | null = null;
+}
+
+export default DefaultMiddleware;`,i=`import { Route, Request, Response, HttpMethod } from 'extress';
+
+class GetIndex extends Route {
+	protected action = (req: Request, res: Response) => {
+		res.status(200).send('Welcome to Extress!');
+	};
+	protected route: string | null = '/';
+	protected method: HttpMethod = HttpMethod.GET;
+}
+
+export default GetIndex;`;r.mkdirSync(t.srcPath),r.mkdirSync(t.middlewaresPath),r.mkdirSync(t.routesPath),r.writeFileSync(n.join(t.middlewaresPath,"DefaultMiddleware.ts"),o),r.writeFileSync(n.join(t.routesPath,"GetIndex.ts"),i),r.writeFileSync(n.join(t.srcPath,"Server.ts"),e),r.writeFileSync(n.join(t.srcPath,"index.ts"),s),r.writeFileSync(t.configPath,JSON.stringify(t.getDefaultConfig(),null,2),"utf-8"),console.log("Project initialized successfully.")}static printUsage(){console.log(`Usage:
+extress init`)}static run(){return t.command===t.Init?t.init():t.printUsage()}};a.run();

+ 19 - 13
dist/index.d.ts

@@ -103,12 +103,13 @@ export declare abstract class WebSocketHandler {
 export type ServerProperties = {
 export type ServerProperties = {
 	port: number;
 	port: number;
 	host?: string;
 	host?: string;
+	middlewaresPath?: string;
+	sessions?: boolean;
+	routesPath?: string;
 	json?: boolean;
 	json?: boolean;
 	urlencoded?: boolean;
 	urlencoded?: boolean;
 	locale?: string;
 	locale?: string;
 	i18nPath?: string;
 	i18nPath?: string;
-	middlewaresPath?: string;
-	routesPath?: string;
 	viewEngine?: string;
 	viewEngine?: string;
 	viewsPath?: string;
 	viewsPath?: string;
 	swagger?: {
 	swagger?: {
@@ -127,6 +128,17 @@ export type ServerProperties = {
 		[key: string]: any;
 		[key: string]: any;
 	};
 	};
 };
 };
+declare abstract class Registry {
+	private static httpHandlers;
+	private server;
+	protected abstract registerRoutes(): Promise<Registry>;
+	protected abstract registerMiddlewares(): Promise<Registry>;
+	registerHttpHandlers(): Promise<Registry>;
+	protected registerHttpHandler(handler: HttpHandler): Registry;
+	setServer(server: Server): Registry;
+	getServer(): Server | null;
+	static getHttpHandlers(): HttpHandler[];
+}
 /** @sealed */
 /** @sealed */
 export declare class Server {
 export declare class Server {
 	private instance;
 	private instance;
@@ -135,7 +147,6 @@ export declare class Server {
 	private readonly host;
 	private readonly host;
 	private readonly logger;
 	private readonly logger;
 	private i18n;
 	private i18n;
-	private readonly httpHandlers;
 	private readonly wsHandlers;
 	private readonly wsHandlers;
 	private readonly wsServers;
 	private readonly wsServers;
 	private initialized;
 	private initialized;
@@ -152,11 +163,10 @@ export declare class Server {
 	private readonly swaggerDescription?;
 	private readonly swaggerDescription?;
 	private readonly swaggerApiVersion?;
 	private readonly swaggerApiVersion?;
 	private readonly swaggerRoute?;
 	private readonly swaggerRoute?;
-	private swagger;
-	private json;
-	private urlencoded;
+	static registry: Registry;
+	private readonly systemRegistry;
 	constructor(properties: ServerProperties);
 	constructor(properties: ServerProperties);
-	init(): Promise<Server>;
+	private init;
 	private postInit;
 	private postInit;
 	private processHttpHandlers;
 	private processHttpHandlers;
 	addMiddleware(middleware: Middleware): Server;
 	addMiddleware(middleware: Middleware): Server;
@@ -171,15 +181,11 @@ export declare class Server {
 	log(message: Message): void;
 	log(message: Message): void;
 	private get;
 	private get;
 	private post;
 	private post;
-	private registerSystemMiddlewares;
-	private appendHttpHandler;
-	registerRoutes(dir: string): Promise<Server>;
-	registerMiddlewares(dir: string): Promise<Server>;
 	getLogger(): Logger;
 	getLogger(): Logger;
 	i18nLoad(path: string): Server;
 	i18nLoad(path: string): Server;
 	getHost(): string;
 	getHost(): string;
 	getOption(key: string): any;
 	getOption(key: string): any;
-	start(callback?: () => any): void;
+	start(callback?: () => any): Promise<Server>;
 }
 }
 export declare class IncorrectMethodException extends Error {
 export declare class IncorrectMethodException extends Error {
 	constructor();
 	constructor();
@@ -219,7 +225,7 @@ export declare class i18nLoader {
 	loadJson(obj: i18nMap): i18nLoader;
 	loadJson(obj: i18nMap): i18nLoader;
 	get(key: string): string;
 	get(key: string): string;
 }
 }
-export declare const $$: (key: string, params?: KeyParams) => string;
+export declare const $: (key: string, params?: KeyParams) => string;
 export declare enum SwaggerParameterIn {
 export declare enum SwaggerParameterIn {
 	PATH = "path",
 	PATH = "path",
 	QUERY = "query",
 	QUERY = "query",

+ 205 - 145
dist/index.js

@@ -18663,11 +18663,11 @@ var require_view = __commonJS({
     "use strict";
     "use strict";
     var debug = require_src()("express:view");
     var debug = require_src()("express:view");
     var path2 = require("node:path");
     var path2 = require("node:path");
-    var fs3 = require("node:fs");
+    var fs4 = require("node:fs");
     var dirname = path2.dirname;
     var dirname = path2.dirname;
     var basename = path2.basename;
     var basename = path2.basename;
     var extname = path2.extname;
     var extname = path2.extname;
-    var join = path2.join;
+    var join2 = path2.join;
     var resolve = path2.resolve;
     var resolve = path2.resolve;
     module2.exports = View;
     module2.exports = View;
     function View(name, options) {
     function View(name, options) {
@@ -18729,12 +18729,12 @@ var require_view = __commonJS({
     };
     };
     View.prototype.resolve = function resolve2(dir, file) {
     View.prototype.resolve = function resolve2(dir, file) {
       var ext = this.ext;
       var ext = this.ext;
-      var path3 = join(dir, file);
+      var path3 = join2(dir, file);
       var stat = tryStat(path3);
       var stat = tryStat(path3);
       if (stat && stat.isFile()) {
       if (stat && stat.isFile()) {
         return path3;
         return path3;
       }
       }
-      path3 = join(dir, basename(file, ext), "index" + ext);
+      path3 = join2(dir, basename(file, ext), "index" + ext);
       stat = tryStat(path3);
       stat = tryStat(path3);
       if (stat && stat.isFile()) {
       if (stat && stat.isFile()) {
         return path3;
         return path3;
@@ -18743,7 +18743,7 @@ var require_view = __commonJS({
     function tryStat(path3) {
     function tryStat(path3) {
       debug('stat "%s"', path3);
       debug('stat "%s"', path3);
       try {
       try {
-        return fs3.statSync(path3);
+        return fs4.statSync(path3);
       } catch (e) {
       } catch (e) {
         return void 0;
         return void 0;
       }
       }
@@ -22429,7 +22429,7 @@ var require_send = __commonJS({
     var escapeHtml = require_escape_html();
     var escapeHtml = require_escape_html();
     var etag = require_etag();
     var etag = require_etag();
     var fresh = require_fresh();
     var fresh = require_fresh();
-    var fs3 = require("fs");
+    var fs4 = require("fs");
     var mime = require_mime_types();
     var mime = require_mime_types();
     var ms = require_ms();
     var ms = require_ms();
     var onFinished = require_on_finished();
     var onFinished = require_on_finished();
@@ -22439,7 +22439,7 @@ var require_send = __commonJS({
     var Stream = require("stream");
     var Stream = require("stream");
     var util = require("util");
     var util = require("util");
     var extname = path2.extname;
     var extname = path2.extname;
-    var join = path2.join;
+    var join2 = path2.join;
     var normalize = path2.normalize;
     var normalize = path2.normalize;
     var resolve = path2.resolve;
     var resolve = path2.resolve;
     var sep = path2.sep;
     var sep = path2.sep;
@@ -22611,7 +22611,7 @@ var require_send = __commonJS({
           return res;
           return res;
         }
         }
         parts = path3.split(sep);
         parts = path3.split(sep);
-        path3 = normalize(join(root, path3));
+        path3 = normalize(join2(root, path3));
       } else {
       } else {
         if (UP_PATH_REGEXP.test(path3)) {
         if (UP_PATH_REGEXP.test(path3)) {
           debug('malicious path "%s"', path3);
           debug('malicious path "%s"', path3);
@@ -22711,7 +22711,7 @@ var require_send = __commonJS({
       var i = 0;
       var i = 0;
       var self2 = this;
       var self2 = this;
       debug('stat "%s"', path3);
       debug('stat "%s"', path3);
-      fs3.stat(path3, function onstat(err, stat) {
+      fs4.stat(path3, function onstat(err, stat) {
         var pathEndsWithSep = path3[path3.length - 1] === sep;
         var pathEndsWithSep = path3[path3.length - 1] === sep;
         if (err && err.code === "ENOENT" && !extname(path3) && !pathEndsWithSep) {
         if (err && err.code === "ENOENT" && !extname(path3) && !pathEndsWithSep) {
           return next(err);
           return next(err);
@@ -22728,7 +22728,7 @@ var require_send = __commonJS({
         }
         }
         var p = path3 + "." + self2._extensions[i++];
         var p = path3 + "." + self2._extensions[i++];
         debug('stat "%s"', p);
         debug('stat "%s"', p);
-        fs3.stat(p, function(err2, stat) {
+        fs4.stat(p, function(err2, stat) {
           if (err2) return next(err2);
           if (err2) return next(err2);
           if (stat.isDirectory()) return next();
           if (stat.isDirectory()) return next();
           self2.emit("file", p, stat);
           self2.emit("file", p, stat);
@@ -22744,9 +22744,9 @@ var require_send = __commonJS({
           if (err) return self2.onStatError(err);
           if (err) return self2.onStatError(err);
           return self2.error(404);
           return self2.error(404);
         }
         }
-        var p = join(path3, self2._index[i]);
+        var p = join2(path3, self2._index[i]);
         debug('stat "%s"', p);
         debug('stat "%s"', p);
-        fs3.stat(p, function(err2, stat) {
+        fs4.stat(p, function(err2, stat) {
           if (err2) return next(err2);
           if (err2) return next(err2);
           if (stat.isDirectory()) return next();
           if (stat.isDirectory()) return next();
           self2.emit("file", p, stat);
           self2.emit("file", p, stat);
@@ -22758,7 +22758,7 @@ var require_send = __commonJS({
     SendStream.prototype.stream = function stream(path3, options) {
     SendStream.prototype.stream = function stream(path3, options) {
       var self2 = this;
       var self2 = this;
       var res = this.res;
       var res = this.res;
-      var stream2 = fs3.createReadStream(path3, options);
+      var stream2 = fs4.createReadStream(path3, options);
       this.emit("stream", stream2);
       this.emit("stream", stream2);
       stream2.pipe(res);
       stream2.pipe(res);
       function cleanup() {
       function cleanup() {
@@ -27647,8 +27647,8 @@ var require_node2 = __commonJS({
           }
           }
           break;
           break;
         case "FILE":
         case "FILE":
-          var fs3 = require("fs");
-          stream2 = new fs3.SyncWriteStream(fd2, { autoClose: false });
+          var fs4 = require("fs");
+          stream2 = new fs4.SyncWriteStream(fd2, { autoClose: false });
           stream2._type = "fs";
           stream2._type = "fs";
           break;
           break;
         case "PIPE":
         case "PIPE":
@@ -50001,7 +50001,7 @@ var require_binary2 = __commonJS({
 var require_file = __commonJS({
 var require_file = __commonJS({
   "node_modules/@apidevtools/json-schema-ref-parser/lib/resolvers/file.js"(exports2, module2) {
   "node_modules/@apidevtools/json-schema-ref-parser/lib/resolvers/file.js"(exports2, module2) {
     "use strict";
     "use strict";
-    var fs3 = require("fs");
+    var fs4 = require("fs");
     var { ono } = require_cjs();
     var { ono } = require_cjs();
     var url = require_url();
     var url = require_url();
     var { ResolverError } = require_errors();
     var { ResolverError } = require_errors();
@@ -50042,7 +50042,7 @@ var require_file = __commonJS({
             reject(new ResolverError(ono.uri(err, `Malformed URI: ${file.url}`), file.url));
             reject(new ResolverError(ono.uri(err, `Malformed URI: ${file.url}`), file.url));
           }
           }
           try {
           try {
-            fs3.readFile(path2, (err, data) => {
+            fs4.readFile(path2, (err, data) => {
               if (err) {
               if (err) {
                 reject(new ResolverError(ono(err, `Error opening file "${path2}"`), path2));
                 reject(new ResolverError(ono(err, `Error opening file "${path2}"`), path2));
               } else {
               } else {
@@ -57048,7 +57048,7 @@ var require_old = __commonJS({
   "node_modules/fs.realpath/old.js"(exports2) {
   "node_modules/fs.realpath/old.js"(exports2) {
     var pathModule = require("path");
     var pathModule = require("path");
     var isWindows = process.platform === "win32";
     var isWindows = process.platform === "win32";
-    var fs3 = require("fs");
+    var fs4 = require("fs");
     var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
     var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
     function rethrow() {
     function rethrow() {
       var callback;
       var callback;
@@ -57113,7 +57113,7 @@ var require_old = __commonJS({
         base = m[0];
         base = m[0];
         previous = "";
         previous = "";
         if (isWindows && !knownHard[base]) {
         if (isWindows && !knownHard[base]) {
-          fs3.lstatSync(base);
+          fs4.lstatSync(base);
           knownHard[base] = true;
           knownHard[base] = true;
         }
         }
       }
       }
@@ -57131,7 +57131,7 @@ var require_old = __commonJS({
         if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
         if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
           resolvedLink = cache[base];
           resolvedLink = cache[base];
         } else {
         } else {
-          var stat = fs3.lstatSync(base);
+          var stat = fs4.lstatSync(base);
           if (!stat.isSymbolicLink()) {
           if (!stat.isSymbolicLink()) {
             knownHard[base] = true;
             knownHard[base] = true;
             if (cache) cache[base] = base;
             if (cache) cache[base] = base;
@@ -57145,8 +57145,8 @@ var require_old = __commonJS({
             }
             }
           }
           }
           if (linkTarget === null) {
           if (linkTarget === null) {
-            fs3.statSync(base);
-            linkTarget = fs3.readlinkSync(base);
+            fs4.statSync(base);
+            linkTarget = fs4.readlinkSync(base);
           }
           }
           resolvedLink = pathModule.resolve(previous, linkTarget);
           resolvedLink = pathModule.resolve(previous, linkTarget);
           if (cache) cache[base] = resolvedLink;
           if (cache) cache[base] = resolvedLink;
@@ -57180,7 +57180,7 @@ var require_old = __commonJS({
         base = m[0];
         base = m[0];
         previous = "";
         previous = "";
         if (isWindows && !knownHard[base]) {
         if (isWindows && !knownHard[base]) {
-          fs3.lstat(base, function(err) {
+          fs4.lstat(base, function(err) {
             if (err) return cb(err);
             if (err) return cb(err);
             knownHard[base] = true;
             knownHard[base] = true;
             LOOP();
             LOOP();
@@ -57206,7 +57206,7 @@ var require_old = __commonJS({
         if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
         if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
           return gotResolvedLink(cache[base]);
           return gotResolvedLink(cache[base]);
         }
         }
-        return fs3.lstat(base, gotStat);
+        return fs4.lstat(base, gotStat);
       }
       }
       function gotStat(err, stat) {
       function gotStat(err, stat) {
         if (err) return cb(err);
         if (err) return cb(err);
@@ -57221,9 +57221,9 @@ var require_old = __commonJS({
             return gotTarget(null, seenLinks[id], base);
             return gotTarget(null, seenLinks[id], base);
           }
           }
         }
         }
-        fs3.stat(base, function(err2) {
+        fs4.stat(base, function(err2) {
           if (err2) return cb(err2);
           if (err2) return cb(err2);
-          fs3.readlink(base, function(err3, target) {
+          fs4.readlink(base, function(err3, target) {
             if (!isWindows) seenLinks[id] = target;
             if (!isWindows) seenLinks[id] = target;
             gotTarget(err3, target);
             gotTarget(err3, target);
           });
           });
@@ -57252,9 +57252,9 @@ var require_fs = __commonJS({
     realpath.realpathSync = realpathSync;
     realpath.realpathSync = realpathSync;
     realpath.monkeypatch = monkeypatch;
     realpath.monkeypatch = monkeypatch;
     realpath.unmonkeypatch = unmonkeypatch;
     realpath.unmonkeypatch = unmonkeypatch;
-    var fs3 = require("fs");
-    var origRealpath = fs3.realpath;
-    var origRealpathSync = fs3.realpathSync;
+    var fs4 = require("fs");
+    var origRealpath = fs4.realpath;
+    var origRealpathSync = fs4.realpathSync;
     var version = process.version;
     var version = process.version;
     var ok = /^v[0-5]\./.test(version);
     var ok = /^v[0-5]\./.test(version);
     var old = require_old();
     var old = require_old();
@@ -57292,12 +57292,12 @@ var require_fs = __commonJS({
       }
       }
     }
     }
     function monkeypatch() {
     function monkeypatch() {
-      fs3.realpath = realpath;
-      fs3.realpathSync = realpathSync;
+      fs4.realpath = realpath;
+      fs4.realpathSync = realpathSync;
     }
     }
     function unmonkeypatch() {
     function unmonkeypatch() {
-      fs3.realpath = origRealpath;
-      fs3.realpathSync = origRealpathSync;
+      fs4.realpath = origRealpath;
+      fs4.realpathSync = origRealpathSync;
     }
     }
   }
   }
 });
 });
@@ -58417,7 +58417,7 @@ var require_sync = __commonJS({
   "node_modules/glob/sync.js"(exports2, module2) {
   "node_modules/glob/sync.js"(exports2, module2) {
     module2.exports = globSync;
     module2.exports = globSync;
     globSync.GlobSync = GlobSync;
     globSync.GlobSync = GlobSync;
-    var fs3 = require("fs");
+    var fs4 = require("fs");
     var rp = require_fs();
     var rp = require_fs();
     var minimatch = require_minimatch();
     var minimatch = require_minimatch();
     var Minimatch = minimatch.Minimatch;
     var Minimatch = minimatch.Minimatch;
@@ -58596,7 +58596,7 @@ var require_sync = __commonJS({
       var lstat;
       var lstat;
       var stat;
       var stat;
       try {
       try {
-        lstat = fs3.lstatSync(abs);
+        lstat = fs4.lstatSync(abs);
       } catch (er) {
       } catch (er) {
         if (er.code === "ENOENT") {
         if (er.code === "ENOENT") {
           return null;
           return null;
@@ -58622,7 +58622,7 @@ var require_sync = __commonJS({
           return c;
           return c;
       }
       }
       try {
       try {
-        return this._readdirEntries(abs, fs3.readdirSync(abs));
+        return this._readdirEntries(abs, fs4.readdirSync(abs));
       } catch (er) {
       } catch (er) {
         this._readdirError(abs, er);
         this._readdirError(abs, er);
         return null;
         return null;
@@ -58733,7 +58733,7 @@ var require_sync = __commonJS({
       if (!stat) {
       if (!stat) {
         var lstat;
         var lstat;
         try {
         try {
-          lstat = fs3.lstatSync(abs);
+          lstat = fs4.lstatSync(abs);
         } catch (er) {
         } catch (er) {
           if (er && (er.code === "ENOENT" || er.code === "ENOTDIR")) {
           if (er && (er.code === "ENOENT" || er.code === "ENOTDIR")) {
             this.statCache[abs] = false;
             this.statCache[abs] = false;
@@ -58742,7 +58742,7 @@ var require_sync = __commonJS({
         }
         }
         if (lstat && lstat.isSymbolicLink()) {
         if (lstat && lstat.isSymbolicLink()) {
           try {
           try {
-            stat = fs3.statSync(abs);
+            stat = fs4.statSync(abs);
           } catch (er) {
           } catch (er) {
             stat = lstat;
             stat = lstat;
           }
           }
@@ -58818,7 +58818,7 @@ var require_inflight = __commonJS({
 var require_glob = __commonJS({
 var require_glob = __commonJS({
   "node_modules/glob/glob.js"(exports2, module2) {
   "node_modules/glob/glob.js"(exports2, module2) {
     module2.exports = glob;
     module2.exports = glob;
-    var fs3 = require("fs");
+    var fs4 = require("fs");
     var rp = require_fs();
     var rp = require_fs();
     var minimatch = require_minimatch();
     var minimatch = require_minimatch();
     var Minimatch = minimatch.Minimatch;
     var Minimatch = minimatch.Minimatch;
@@ -59162,7 +59162,7 @@ var require_glob = __commonJS({
       var self2 = this;
       var self2 = this;
       var lstatcb = inflight(lstatkey, lstatcb_);
       var lstatcb = inflight(lstatkey, lstatcb_);
       if (lstatcb)
       if (lstatcb)
-        fs3.lstat(abs, lstatcb);
+        fs4.lstat(abs, lstatcb);
       function lstatcb_(er, lstat) {
       function lstatcb_(er, lstat) {
         if (er && er.code === "ENOENT")
         if (er && er.code === "ENOENT")
           return cb();
           return cb();
@@ -59191,7 +59191,7 @@ var require_glob = __commonJS({
           return cb(null, c);
           return cb(null, c);
       }
       }
       var self2 = this;
       var self2 = this;
-      fs3.readdir(abs, readdirCb(this, abs, cb));
+      fs4.readdir(abs, readdirCb(this, abs, cb));
     };
     };
     function readdirCb(self2, abs, cb) {
     function readdirCb(self2, abs, cb) {
       return function(er, entries) {
       return function(er, entries) {
@@ -59337,10 +59337,10 @@ var require_glob = __commonJS({
       var self2 = this;
       var self2 = this;
       var statcb = inflight("stat\0" + abs, lstatcb_);
       var statcb = inflight("stat\0" + abs, lstatcb_);
       if (statcb)
       if (statcb)
-        fs3.lstat(abs, statcb);
+        fs4.lstat(abs, statcb);
       function lstatcb_(er, lstat) {
       function lstatcb_(er, lstat) {
         if (lstat && lstat.isSymbolicLink()) {
         if (lstat && lstat.isSymbolicLink()) {
-          return fs3.stat(abs, function(er2, stat2) {
+          return fs4.stat(abs, function(er2, stat2) {
             if (er2)
             if (er2)
               self2._stat2(f, abs, null, lstat, cb);
               self2._stat2(f, abs, null, lstat, cb);
             else
             else
@@ -60096,7 +60096,7 @@ var require_lodash3 = __commonJS({
 // node_modules/swagger-jsdoc/src/utils.js
 // node_modules/swagger-jsdoc/src/utils.js
 var require_utils5 = __commonJS({
 var require_utils5 = __commonJS({
   "node_modules/swagger-jsdoc/src/utils.js"(exports2, module2) {
   "node_modules/swagger-jsdoc/src/utils.js"(exports2, module2) {
-    var fs3 = require("fs");
+    var fs4 = require("fs");
     var path2 = require("path");
     var path2 = require("path");
     var glob = require_glob();
     var glob = require_glob();
     var mergeWith = require_lodash3();
     var mergeWith = require_lodash3();
@@ -60118,7 +60118,7 @@ var require_utils5 = __commonJS({
       return yamlParts;
       return yamlParts;
     }
     }
     function extractAnnotations(filePath, encoding = "utf8") {
     function extractAnnotations(filePath, encoding = "utf8") {
-      const fileContent = fs3.readFileSync(filePath, { encoding });
+      const fileContent = fs4.readFileSync(filePath, { encoding });
       const ext = path2.extname(filePath);
       const ext = path2.extname(filePath);
       const jsDocRegex = /\/\*\*([\s\S]*?)\*\//gm;
       const jsDocRegex = /\/\*\*([\s\S]*?)\*\//gm;
       const csDocRegex = /###([\s\S]*?)###/gm;
       const csDocRegex = /###([\s\S]*?)###/gm;
@@ -60470,7 +60470,7 @@ var require_swagger_jsdoc = __commonJS({
 // lib/index.ts
 // lib/index.ts
 var index_exports = {};
 var index_exports = {};
 __export(index_exports, {
 __export(index_exports, {
-  $$: () => $$,
+  $: () => $,
   Guid: () => Guid,
   Guid: () => Guid,
   HttpHandler: () => HttpHandler,
   HttpHandler: () => HttpHandler,
   HttpMethod: () => HttpMethod,
   HttpMethod: () => HttpMethod,
@@ -60492,10 +60492,8 @@ __export(index_exports, {
 module.exports = __toCommonJS(index_exports);
 module.exports = __toCommonJS(index_exports);
 
 
 // lib/server/Server.ts
 // lib/server/Server.ts
-var import_path = __toESM(require("path"));
 var import_fs2 = __toESM(require("fs"));
 var import_fs2 = __toESM(require("fs"));
-var import_http9 = __toESM(require("http"));
-var import_url = require("url");
+var import_http11 = __toESM(require("http"));
 var import_express3 = __toESM(require_express2());
 var import_express3 = __toESM(require_express2());
 
 
 // lib/base/http/HttpHandler.ts
 // lib/base/http/HttpHandler.ts
@@ -60679,11 +60677,11 @@ var i18nLoader = class _i18nLoader {
     this.locale = locale;
     this.locale = locale;
     this.map = {
     this.map = {
       "en_US": {
       "en_US": {
-        "org.crazydoctor.expressts.start": "org.crazydoctor.expressts server started on port {port}",
-        "org.crazydoctor.expressts.httpError.500": "Internal server error",
-        "org.crazydoctor.expressts.httpError.404": "Page {url} not found",
-        "org.crazydoctor.expressts.swagger.registered": "Swagger documentation is available on {path}",
-        "org.crazydoctor.expressts.swagger.routeGenerated": "Swagger documentation for route '{route}' generated"
+        "org.crazydoctor.extress.start": "Extress server started on port {port}",
+        "org.crazydoctor.extress.httpError.500": "Internal server error",
+        "org.crazydoctor.extress.httpError.404": "Page {url} not found",
+        "org.crazydoctor.extress.swagger.registered": "Swagger documentation is available on {path}",
+        "org.crazydoctor.extress.swagger.routeGenerated": "Swagger documentation for route '{route}' generated"
       }
       }
     };
     };
   }
   }
@@ -60730,7 +60728,7 @@ var i18nLoader = class _i18nLoader {
     return value ?? key;
     return value ?? key;
   }
   }
 };
 };
-var $$ = (key, params) => {
+var $ = (key, params) => {
   let text = i18nLoader.getInstance().get(key);
   let text = i18nLoader.getInstance().get(key);
   if (params) {
   if (params) {
     for (const param of Object.keys(params)) {
     for (const param of Object.keys(params)) {
@@ -60771,6 +60769,52 @@ var Guid = class {
   }
   }
 };
 };
 
 
+// lib/base/registry/Registry.ts
+var Registry = class _Registry {
+  constructor() {
+    this.server = null;
+  }
+  static {
+    this.httpHandlers = {};
+  }
+  async registerHttpHandlers() {
+    await this.registerRoutes();
+    await this.registerMiddlewares();
+    return this;
+  }
+  registerHttpHandler(handler) {
+    let id = Guid.new();
+    while (_Registry.httpHandlers[id] != null)
+      id = Guid.new();
+    _Registry.httpHandlers[id] = handler;
+    return this;
+  }
+  setServer(server) {
+    if (this.server != null)
+      return this;
+    return this.server = server, this;
+  }
+  getServer() {
+    return this.server;
+  }
+  static getHttpHandlers() {
+    const handlers = [];
+    const middlewareOrders = [];
+    for (const key in _Registry.httpHandlers) {
+      const handler = _Registry.httpHandlers[key];
+      if (handler instanceof Middleware) {
+        const order = handler.getOrder();
+        if (middlewareOrders.includes(order))
+          throw `Invalid middleware order number: ${handler.constructor.name}`;
+        middlewareOrders.push(order);
+      }
+      handlers.push(_Registry.httpHandlers[key]);
+    }
+    return handlers.sort((a, b) => a instanceof Middleware && b instanceof Middleware && a.getOrder() - b.getOrder() || (a instanceof Middleware && -1 || (b instanceof Middleware && 1 || 0)));
+  }
+};
+var Registry_default = Registry;
+
 // lib/middlewares/ExpressJsonMiddleware.ts
 // lib/middlewares/ExpressJsonMiddleware.ts
 var import_express = __toESM(require_express2());
 var import_express = __toESM(require_express2());
 var ExpressJsonMiddleware = class extends Middleware {
 var ExpressJsonMiddleware = class extends Middleware {
@@ -60801,7 +60845,7 @@ var InternalServerErrorHandler = class extends Middleware {
     this.route = null;
     this.route = null;
     this.action = (err, req, res, next) => {
     this.action = (err, req, res, next) => {
       this.context.logError(`${err.message}: ${err.stack}`);
       this.context.logError(`${err.message}: ${err.stack}`);
-      res.status(500 /* INTERNAL_SERVER_ERROR */).send($$("org.crazydoctor.expressts.httpError.500"));
+      res.status(500 /* INTERNAL_SERVER_ERROR */).send($("org.crazydoctor.extress.httpError.500"));
     };
     };
   }
   }
 };
 };
@@ -60813,7 +60857,7 @@ var NotFoundErrorHandler = class extends Middleware {
     this.order = 9999 /* NotFoundErrorHandler */;
     this.order = 9999 /* NotFoundErrorHandler */;
     this.route = null;
     this.route = null;
     this.action = (req, res, next) => {
     this.action = (req, res, next) => {
-      res.status(404 /* NOT_FOUND */).send($$("org.crazydoctor.expressts.httpError.404", { url: req.url }));
+      res.status(404 /* NOT_FOUND */).send($("org.crazydoctor.extress.httpError.404", { url: req.url }));
     };
     };
   }
   }
 };
 };
@@ -60823,7 +60867,7 @@ var PoweredByHeaderMiddleware = class extends Middleware {
   constructor() {
   constructor() {
     super(...arguments);
     super(...arguments);
     this.action = (req, res, next) => {
     this.action = (req, res, next) => {
-      res.setHeader("X-Powered-By", "org.crazydoctor.expressts");
+      res.setHeader("X-Powered-By", "Extress");
       next();
       next();
     };
     };
     this.order = -101 /* PoweredByHeaderMiddleware */;
     this.order = -101 /* PoweredByHeaderMiddleware */;
@@ -60887,30 +60931,97 @@ var SwaggerUiSetupMiddleware = class extends Middleware {
     if (this.context.swaggerSecurity)
     if (this.context.swaggerSecurity)
       swaggerOptions.swaggerDefinition.security = this.context.swaggerSecurity;
       swaggerOptions.swaggerDefinition.security = this.context.swaggerSecurity;
     const swaggerDocs = (0, import_swagger_jsdoc.default)(swaggerOptions);
     const swaggerDocs = (0, import_swagger_jsdoc.default)(swaggerOptions);
-    this.context.logInfo($$("org.crazydoctor.expressts.swagger.registered", { path: this.context.swaggerRoute }));
+    this.context.logInfo($("org.crazydoctor.extress.swagger.registered", { path: this.context.swaggerRoute }));
     return import_swagger_ui_express2.default.setup(swaggerDocs);
     return import_swagger_ui_express2.default.setup(swaggerDocs);
   }
   }
 };
 };
 
 
+// lib/base/registry/SystemRegistry.ts
+var SystemRegistry = class extends Registry_default {
+  constructor(config) {
+    super();
+    this.json = config.json;
+    this.urlencoded = config.urlencoded;
+    this.sessions = config.sessions;
+    this.swagger = config.swagger;
+    return this;
+  }
+  async registerRoutes() {
+    return this;
+  }
+  async registerMiddlewares() {
+    const json = this.json, urlencoded = this.urlencoded, swagger = this.swagger, sessions = this.sessions, server = this.getServer();
+    json && this.registerHttpHandler(new ExpressJsonMiddleware(server));
+    urlencoded && this.registerHttpHandler(new ExpressUrlencodedMiddleware(server));
+    sessions && this.registerHttpHandler(new SessionMiddleware(server));
+    swagger && this.registerHttpHandler(new SwaggerUiServeMiddleware(server));
+    swagger && this.registerHttpHandler(new SwaggerUiSetupMiddleware(server));
+    this.registerHttpHandler(new InternalServerErrorHandler(server));
+    this.registerHttpHandler(new NotFoundErrorHandler(server));
+    this.registerHttpHandler(new PoweredByHeaderMiddleware(server));
+    return this;
+  }
+};
+var SystemRegistry_default = SystemRegistry;
+
+// lib/base/registry/DynamicRegistry.ts
+var import_url = require("url");
+var path = __toESM(require("path"));
+var fs2 = __toESM(require("fs"));
+var DynamicRegistry = class extends Registry_default {
+  constructor(routesDir, middlewaresDir) {
+    super();
+    this.routesDir = routesDir;
+    this.middlewaresDir = middlewaresDir;
+  }
+  async registerRoutes() {
+    if (this.routesDir == null)
+      return this;
+    const routesDir = this.routesDir;
+    const files = fs2.readdirSync(routesDir, { recursive: true, encoding: "utf8" });
+    for (const file of files) {
+      if (/\.js$/.test(file)) {
+        const fileUrl = (0, import_url.pathToFileURL)(path.join(routesDir, file)).toString();
+        const RouteClass = await import(fileUrl).then((mod) => mod.default?.default ?? mod.default ?? mod);
+        if (RouteClass.prototype instanceof Route) {
+          this.registerHttpHandler(new RouteClass(this.getServer()));
+        } else throw new InvalidRouteException(fileUrl);
+      }
+    }
+    return this;
+  }
+  async registerMiddlewares() {
+    if (this.middlewaresDir == null)
+      return this;
+    const middlewaresDir = this.middlewaresDir;
+    const files = fs2.readdirSync(middlewaresDir, { recursive: true, encoding: "utf8" });
+    for (const file of files) {
+      if (/\.js$/.test(file)) {
+        const fileUrl = (0, import_url.pathToFileURL)(path.join(middlewaresDir, file)).toString();
+        const MiddlewareClass = await import(fileUrl).then((mod) => mod.default?.default ?? mod.default ?? mod);
+        if (MiddlewareClass.prototype instanceof Middleware) {
+          this.registerHttpHandler(new MiddlewareClass(this.getServer()));
+        } else throw new InvalidMiddlewareException(fileUrl);
+      }
+    }
+    return this;
+  }
+};
+var DynamicRegistry_default = DynamicRegistry;
+
 // lib/server/Server.ts
 // lib/server/Server.ts
-var Server = class {
+var Server = class _Server {
   constructor(properties) {
   constructor(properties) {
-    this.swagger = false;
-    this.json = false;
-    this.urlencoded = false;
     this.instance = (0, import_express3.default)();
     this.instance = (0, import_express3.default)();
-    this.httpServer = import_http9.default.createServer(this.instance);
+    this.httpServer = import_http11.default.createServer(this.instance);
     this.port = properties.port;
     this.port = properties.port;
     this.host = properties.host || `http://localhost:${this.port}`;
     this.host = properties.host || `http://localhost:${this.port}`;
     this.i18n = i18nLoader.getInstance();
     this.i18n = i18nLoader.getInstance();
     if (properties.locale)
     if (properties.locale)
       this.i18n.setLocale(properties.locale);
       this.i18n.setLocale(properties.locale);
     this.logger = new Logger();
     this.logger = new Logger();
-    this.httpHandlers = {};
     this.wsHandlers = properties.wsHandlers || {};
     this.wsHandlers = properties.wsHandlers || {};
     this.wsServers = {};
     this.wsServers = {};
-    this.json = properties.json || false;
-    this.urlencoded = properties.urlencoded || false;
     this.i18nPath = properties.i18nPath;
     this.i18nPath = properties.i18nPath;
     this.middlewaresPath = properties.middlewaresPath;
     this.middlewaresPath = properties.middlewaresPath;
     this.routesPath = properties.routesPath;
     this.routesPath = properties.routesPath;
@@ -60925,8 +61036,15 @@ var Server = class {
       this.swaggerRoute = properties.swagger?.route || "/api-docs";
       this.swaggerRoute = properties.swagger?.route || "/api-docs";
       this.swaggerComponents = properties.swagger?.components;
       this.swaggerComponents = properties.swagger?.components;
       this.swaggerSecurity = properties.swagger?.security;
       this.swaggerSecurity = properties.swagger?.security;
-      this.swagger = true;
     }
     }
+    this.systemRegistry = new SystemRegistry_default({
+      json: properties.json || false,
+      urlencoded: properties.urlencoded || false,
+      sessions: properties.sessions || false,
+      swagger: properties.swagger != null
+    }).setServer(this);
+    _Server.registry = _Server.registry == null ? new DynamicRegistry_default(this.routesPath, this.middlewaresPath) : _Server.registry;
+    _Server.registry.setServer(this);
     this.initialized = false;
     this.initialized = false;
   }
   }
   async init() {
   async init() {
@@ -60934,7 +61052,7 @@ var Server = class {
       this.instance.set("view engine", this.viewEngine);
       this.instance.set("view engine", this.viewEngine);
     if (this.viewsPath)
     if (this.viewsPath)
       this.instance.set("views", this.viewsPath);
       this.instance.set("views", this.viewsPath);
-    this.registerSystemMiddlewares();
+    await this.systemRegistry.registerHttpHandlers();
     await this.postInit();
     await this.postInit();
     this.initialized = true;
     this.initialized = true;
     return this;
     return this;
@@ -60942,10 +61060,7 @@ var Server = class {
   async postInit() {
   async postInit() {
     if (this.i18nPath)
     if (this.i18nPath)
       this.i18n.load(this.i18nPath);
       this.i18n.load(this.i18nPath);
-    if (this.middlewaresPath)
-      await this.registerMiddlewares(this.middlewaresPath);
-    if (this.routesPath)
-      await this.registerRoutes(this.routesPath);
+    await _Server.registry.registerHttpHandlers();
     if (this.swaggerDocsPath)
     if (this.swaggerDocsPath)
       import_fs2.default.writeFileSync(this.swaggerDocsPath, "");
       import_fs2.default.writeFileSync(this.swaggerDocsPath, "");
     if (Object.keys(this.wsHandlers).length > 0) {
     if (Object.keys(this.wsHandlers).length > 0) {
@@ -60954,20 +61069,7 @@ var Server = class {
     }
     }
   }
   }
   processHttpHandlers() {
   processHttpHandlers() {
-    const handlers = [];
-    const middlewareOrders = [];
-    for (const key in this.httpHandlers) {
-      const handler = this.httpHandlers[key];
-      if (handler instanceof Middleware) {
-        const order = handler.getOrder();
-        if (middlewareOrders.includes(order))
-          throw `Ivalid order number: ${handler.constructor.name}`;
-        middlewareOrders.push(order);
-      }
-      handlers.push(this.httpHandlers[key]);
-    }
-    handlers.sort((a, b) => a instanceof Middleware && b instanceof Middleware && a.getOrder() - b.getOrder() || (a instanceof Middleware && -1 || (b instanceof Middleware && 1 || 0)));
-    for (const handler of handlers) {
+    for (const handler of Registry_default.getHttpHandlers()) {
       if (handler instanceof Middleware)
       if (handler instanceof Middleware)
         this.addMiddleware(handler);
         this.addMiddleware(handler);
       else if (handler instanceof Route)
       else if (handler instanceof Route)
@@ -60996,8 +61098,7 @@ var Server = class {
   registerRoutesDocumentation() {
   registerRoutesDocumentation() {
     if (!this.swaggerDocsPath)
     if (!this.swaggerDocsPath)
       return this;
       return this;
-    for (const routeName in this.httpHandlers) {
-      const route = this.httpHandlers[routeName];
+    for (const route of Registry_default.getHttpHandlers()) {
       if (!(route instanceof Route))
       if (!(route instanceof Route))
         continue;
         continue;
       if (route.getRoute() == null)
       if (route.getRoute() == null)
@@ -61008,7 +61109,7 @@ var Server = class {
       if (docs.length > 0) {
       if (docs.length > 0) {
         import_fs2.default.appendFileSync(this.swaggerDocsPath, `${docs}
         import_fs2.default.appendFileSync(this.swaggerDocsPath, `${docs}
 `);
 `);
-        this.logInfo($$("org.crazydoctor.expressts.swagger.routeGenerated", { route: route.getRoute() }));
+        this.logInfo($("org.crazydoctor.extress.swagger.routeGenerated", { route: route.getRoute() }));
       }
       }
     }
     }
     return this;
     return this;
@@ -61071,50 +61172,6 @@ var Server = class {
     this.instance.post(route.getRoute(), route.getAction());
     this.instance.post(route.getRoute(), route.getAction());
     return this;
     return this;
   }
   }
-  registerSystemMiddlewares() {
-    const json = this.json, urlencoded = this.urlencoded, swagger = this.swagger;
-    json && this.appendHttpHandler(new ExpressJsonMiddleware(this));
-    urlencoded && this.appendHttpHandler(new ExpressUrlencodedMiddleware(this));
-    this.appendHttpHandler(new InternalServerErrorHandler(this));
-    this.appendHttpHandler(new NotFoundErrorHandler(this));
-    this.appendHttpHandler(new PoweredByHeaderMiddleware(this));
-    this.appendHttpHandler(new SessionMiddleware(this));
-    swagger && this.appendHttpHandler(new SwaggerUiServeMiddleware(this));
-    swagger && this.appendHttpHandler(new SwaggerUiSetupMiddleware(this));
-    return this;
-  }
-  appendHttpHandler(handler) {
-    let id = Guid.new();
-    while (this.httpHandlers[id] != null)
-      id = Guid.new();
-    this.httpHandlers[id] = handler;
-  }
-  async registerRoutes(dir) {
-    const files = import_fs2.default.readdirSync(dir, { recursive: true, encoding: "utf8" });
-    for (const file of files) {
-      if (/\.js$/.test(file)) {
-        const fileUrl = (0, import_url.pathToFileURL)(import_path.default.join(dir, file)).toString();
-        const RouteClass = await import(fileUrl).then((mod) => mod.default?.default ?? mod.default ?? mod);
-        if (RouteClass.prototype instanceof Route) {
-          this.appendHttpHandler(new RouteClass(this));
-        } else throw new InvalidRouteException(fileUrl);
-      }
-    }
-    return this;
-  }
-  async registerMiddlewares(dir) {
-    const files = import_fs2.default.readdirSync(dir, { recursive: true, encoding: "utf8" });
-    for (const file of files) {
-      if (/\.js$/.test(file)) {
-        const fileUrl = (0, import_url.pathToFileURL)(import_path.default.join(dir, file)).toString();
-        const MiddlewareClass = await import(fileUrl).then((mod) => mod.default?.default ?? mod.default ?? mod);
-        if (MiddlewareClass.prototype instanceof Middleware) {
-          this.appendHttpHandler(new MiddlewareClass(this));
-        } else throw new InvalidMiddlewareException(fileUrl);
-      }
-    }
-    return this;
-  }
   getLogger() {
   getLogger() {
     return this.logger;
     return this.logger;
   }
   }
@@ -61128,16 +61185,19 @@ var Server = class {
   getOption(key) {
   getOption(key) {
     return this.options ? this.options[key] || null : null;
     return this.options ? this.options[key] || null : null;
   }
   }
-  start(callback) {
-    if (!this.initialized)
-      throw new ServerNotInitializedException();
-    this.registerRoutesDocumentation();
-    this.processHttpHandlers();
-    const cb = () => {
-      this.logInfo($$("org.crazydoctor.expressts.start", { "port": this.port }));
-      if (callback) callback();
-    };
-    this.httpServer.listen(this.port, cb);
+  async start(callback) {
+    return this.init().then((server) => {
+      if (!this.initialized)
+        throw new ServerNotInitializedException();
+      this.registerRoutesDocumentation();
+      this.processHttpHandlers();
+      const cb = () => {
+        this.logInfo($("org.crazydoctor.extress.start", { "port": this.port }));
+        if (callback) callback();
+      };
+      this.httpServer.listen(this.port, cb);
+      return server;
+    });
   }
   }
 };
 };
 
 
@@ -61308,7 +61368,7 @@ var SwaggerParameterIn = /* @__PURE__ */ ((SwaggerParameterIn2) => {
 })(SwaggerParameterIn || {});
 })(SwaggerParameterIn || {});
 // Annotate the CommonJS export names for ESM import in node:
 // Annotate the CommonJS export names for ESM import in node:
 0 && (module.exports = {
 0 && (module.exports = {
-  $$,
+  $,
   Guid,
   Guid,
   HttpHandler,
   HttpHandler,
   HttpMethod,
   HttpMethod,

File diff suppressed because it is too large
+ 0 - 0
dist/index.js.map


BIN
extress-logo.png


+ 7 - 7
lib/base/i18n/i18n.ts

@@ -11,11 +11,11 @@ class i18nLoader {
 		this.locale = locale;
 		this.locale = locale;
 		this.map = <i18nMap>{
 		this.map = <i18nMap>{
 			'en_US': {
 			'en_US': {
-				'org.crazydoctor.expressts.start': 'org.crazydoctor.expressts server started on port {port}',
-				'org.crazydoctor.expressts.httpError.500': 'Internal server error',
-				'org.crazydoctor.expressts.httpError.404': 'Page {url} not found',
-				'org.crazydoctor.expressts.swagger.registered': 'Swagger documentation is available on {path}',
-				'org.crazydoctor.expressts.swagger.routeGenerated': 'Swagger documentation for route \'{route}\' generated'
+				'org.crazydoctor.extress.start': 'Extress server started on port {port}',
+				'org.crazydoctor.extress.httpError.500': 'Internal server error',
+				'org.crazydoctor.extress.httpError.404': 'Page {url} not found',
+				'org.crazydoctor.extress.swagger.registered': 'Swagger documentation is available on {path}',
+				'org.crazydoctor.extress.swagger.routeGenerated': 'Swagger documentation for route \'{route}\' generated'
 			}
 			}
 		};
 		};
 	}
 	}
@@ -72,7 +72,7 @@ class i18nLoader {
 	}
 	}
 }
 }
 
 
-const $$ = (key: string, params?: KeyParams): string => {
+const $ = (key: string, params?: KeyParams): string => {
 	let text = i18nLoader.getInstance().get(key);
 	let text = i18nLoader.getInstance().get(key);
 
 
 	if(params) {
 	if(params) {
@@ -85,4 +85,4 @@ const $$ = (key: string, params?: KeyParams): string => {
 	return text;
 	return text;
 };
 };
 
 
-export { i18nLoader, $$ };
+export { i18nLoader, $ };

+ 58 - 0
lib/base/registry/DynamicRegistry.ts

@@ -0,0 +1,58 @@
+import { pathToFileURL } from 'url';
+import * as path from 'path';
+import * as fs from 'fs';
+import { InvalidMiddlewareException, InvalidRouteException } from '../exceptions';
+import { Route, HttpHandler, Middleware } from '../http';
+import Registry from './Registry';
+
+class DynamicRegistry extends Registry {
+	private readonly routesDir?: string;
+	private readonly middlewaresDir?: string;
+
+	public constructor(routesDir?: string, middlewaresDir?: string) {
+		super();
+		this.routesDir = routesDir;
+		this.middlewaresDir = middlewaresDir;
+	}
+
+	protected async registerRoutes(): Promise<Registry> {
+		if(this.routesDir == null)
+			return this;
+
+		const routesDir: string = this.routesDir;
+		const files = fs.readdirSync(routesDir, { recursive: true, encoding: 'utf8' });
+
+		for(const file of files) {
+			if(/\.js$/.test(file)) {
+				const fileUrl = pathToFileURL(path.join(routesDir, file)).toString();
+				const RouteClass = await import(fileUrl).then(mod => mod.default?.default ?? mod.default ?? mod);
+				if(RouteClass.prototype instanceof Route) {
+					this.registerHttpHandler(<HttpHandler>new RouteClass(this.getServer()));
+				} else throw new InvalidRouteException(fileUrl);
+			}
+		}
+		return this;
+	}
+
+	protected async registerMiddlewares(): Promise<Registry> {
+		if(this.middlewaresDir == null)
+			return this;
+
+		const middlewaresDir: string = this.middlewaresDir;
+		const files = fs.readdirSync(middlewaresDir, { recursive: true, encoding: 'utf8' });
+		
+		for(const file of files) {
+			if(/\.js$/.test(file)) {
+				const fileUrl = pathToFileURL(path.join(middlewaresDir, file)).toString();
+				const MiddlewareClass = await import(fileUrl).then(mod => mod.default?.default ?? mod.default ?? mod);
+				if(MiddlewareClass.prototype instanceof Middleware) {
+					this.registerHttpHandler(<HttpHandler>new MiddlewareClass(this.getServer()));
+				} else throw new InvalidMiddlewareException(fileUrl);
+			}
+		}
+
+		return this;
+	}	
+}
+
+export default DynamicRegistry;

+ 56 - 0
lib/base/registry/Registry.ts

@@ -0,0 +1,56 @@
+import { Server } from '../../server';
+import { HttpHandler, Middleware } from '../http';
+import { Guid } from '../util';
+
+abstract class Registry {
+	private static httpHandlers: {[key: string]: HttpHandler} = {};
+	private server: Server | null = null;
+
+	protected abstract registerRoutes(): Promise<Registry>;
+	protected abstract registerMiddlewares(): Promise<Registry>;
+
+	public async registerHttpHandlers(): Promise<Registry> {
+		await this.registerRoutes();
+		await this.registerMiddlewares();
+		return this;
+	}
+
+	protected registerHttpHandler(handler: HttpHandler): Registry {
+		let id = Guid.new();
+		while(Registry.httpHandlers[id] != null)
+			id = Guid.new();
+		
+		Registry.httpHandlers[id] = handler;
+
+		return this;
+	}
+
+	public setServer(server: Server): Registry {
+		if(this.server != null)
+			return this;
+		return this.server = server, this;
+	}
+
+	public getServer(): Server | null {
+		return this.server;
+	}
+
+	public static getHttpHandlers(): HttpHandler[] {
+		const handlers: HttpHandler[] = [];
+		const middlewareOrders: number[] = [];
+		for(const key in Registry.httpHandlers) {
+			const handler = Registry.httpHandlers[key];
+			if(handler instanceof Middleware) {
+				const order = handler.getOrder();
+				if(middlewareOrders.includes(order))
+					throw `Invalid middleware order number: ${handler.constructor.name}`;
+				middlewareOrders.push(order);
+			}
+			handlers.push(Registry.httpHandlers[key]);
+		}
+
+		return handlers.sort((a, b) => a instanceof Middleware && b instanceof Middleware && (a.getOrder() - b.getOrder()) || (a instanceof Middleware && -1 || (b instanceof Middleware && 1 || 0)));
+	}
+}
+
+export default Registry;

+ 48 - 0
lib/base/registry/SystemRegistry.ts

@@ -0,0 +1,48 @@
+import { ExpressJsonMiddleware, ExpressUrlencodedMiddleware, InternalServerErrorHandler, NotFoundErrorHandler, PoweredByHeaderMiddleware, SessionMiddleware, SwaggerUiServeMiddleware, SwaggerUiSetupMiddleware } from '../../middlewares';
+import Registry from './Registry';
+
+type SystemRegistryConfig = {
+	json: boolean,
+	urlencoded: boolean,
+	sessions: boolean,
+	swagger: boolean
+};
+
+class SystemRegistry extends Registry {
+	private readonly json: boolean;
+	private readonly urlencoded: boolean;
+	private readonly sessions: boolean;
+	private readonly swagger: boolean;
+
+	public constructor(config: SystemRegistryConfig) {
+		super();
+
+		this.json = config.json;
+		this.urlencoded = config.urlencoded;
+		this.sessions = config.sessions;
+		this.swagger = config.swagger;
+
+		return this;
+	}
+
+	protected async registerRoutes(): Promise<Registry> {
+		return this;
+	}
+
+	protected async registerMiddlewares(): Promise<Registry> {
+		const json = this.json, urlencoded = this.urlencoded, swagger = this.swagger, sessions = this.sessions, server = this.getServer()!;
+		
+		json && this.registerHttpHandler(new ExpressJsonMiddleware(server));
+		urlencoded && this.registerHttpHandler(new ExpressUrlencodedMiddleware(server));
+		sessions && this.registerHttpHandler(new SessionMiddleware(server));
+		swagger && this.registerHttpHandler(new SwaggerUiServeMiddleware(server));
+		swagger && this.registerHttpHandler(new SwaggerUiSetupMiddleware(server));
+		this.registerHttpHandler(new InternalServerErrorHandler(server));
+		this.registerHttpHandler(new NotFoundErrorHandler(server));
+		this.registerHttpHandler(new PoweredByHeaderMiddleware(server));
+
+		return this;
+	}	
+}
+
+export default SystemRegistry;

+ 1 - 1
lib/base/websocket/WebSocketHandler.ts

@@ -8,7 +8,7 @@ abstract class WebSocketHandler {
 		ERROR: 'error'
 		ERROR: 'error'
 	};
 	};
 
 
-  public abstract onConnect: (ws: WS) => any;
+	public abstract onConnect: (ws: WS) => any;
 	public abstract onMessage: (message: string) => any;
 	public abstract onMessage: (message: string) => any;
 	public abstract onError: () => any;
 	public abstract onError: () => any;
 	public abstract onClose: (code?: number, reason?: string) => any;
 	public abstract onClose: (code?: number, reason?: string) => any;

+ 2 - 2
lib/middlewares/InternalServerErrorHandler.ts

@@ -1,5 +1,5 @@
 import { Middleware, StatusCodes, Request, Response, NextFunction } from '../base/http';
 import { Middleware, StatusCodes, Request, Response, NextFunction } from '../base/http';
-import { $$ } from '../base/i18n';
+import { $ } from '../base/i18n';
 import { MiddlewareOrder } from './MiddlewareOrder';
 import { MiddlewareOrder } from './MiddlewareOrder';
 
 
 class InternalServerErrorHandler extends Middleware {
 class InternalServerErrorHandler extends Middleware {
@@ -7,7 +7,7 @@ class InternalServerErrorHandler extends Middleware {
 	protected route = null;
 	protected route = null;
 	protected action = (err: Error, req: Request, res: Response, next: NextFunction): any => {
 	protected action = (err: Error, req: Request, res: Response, next: NextFunction): any => {
 		this.context.logError(`${err.message}: ${err.stack}`);
 		this.context.logError(`${err.message}: ${err.stack}`);
-		res.status(StatusCodes.INTERNAL_SERVER_ERROR).send($$('org.crazydoctor.expressts.httpError.500'));
+		res.status(StatusCodes.INTERNAL_SERVER_ERROR).send($('org.crazydoctor.extress.httpError.500'));
 	};
 	};
 }
 }
 
 

+ 2 - 2
lib/middlewares/NotFoundErrorHandler.ts

@@ -1,12 +1,12 @@
 import { Middleware, StatusCodes, Request, Response, NextFunction } from '../base/http';
 import { Middleware, StatusCodes, Request, Response, NextFunction } from '../base/http';
-import { $$ } from '../base/i18n';
+import { $ } from '../base/i18n';
 import { MiddlewareOrder } from './MiddlewareOrder';
 import { MiddlewareOrder } from './MiddlewareOrder';
 
 
 class NotFoundErrorHandler extends Middleware {
 class NotFoundErrorHandler extends Middleware {
 	protected order = MiddlewareOrder.NotFoundErrorHandler;
 	protected order = MiddlewareOrder.NotFoundErrorHandler;
 	protected route = null;
 	protected route = null;
 	protected action = (req: Request, res: Response, next: NextFunction): any => {
 	protected action = (req: Request, res: Response, next: NextFunction): any => {
-		res.status(StatusCodes.NOT_FOUND).send($$('org.crazydoctor.expressts.httpError.404', { url: req.url }));
+		res.status(StatusCodes.NOT_FOUND).send($('org.crazydoctor.extress.httpError.404', { url: req.url }));
 	};
 	};
 }
 }
 
 

+ 1 - 1
lib/middlewares/PoweredByHeaderMiddleware.ts

@@ -3,7 +3,7 @@ import { MiddlewareOrder } from './MiddlewareOrder';
 
 
 class PoweredByHeaderMiddleware extends Middleware {
 class PoweredByHeaderMiddleware extends Middleware {
 	protected action = (req: Request, res: Response, next: NextFunction): any => {
 	protected action = (req: Request, res: Response, next: NextFunction): any => {
-		res.setHeader('X-Powered-By', 'org.crazydoctor.expressts');
+		res.setHeader('X-Powered-By', 'Extress');
 		next();
 		next();
 	};
 	};
 	protected order = MiddlewareOrder.PoweredByHeaderMiddleware;
 	protected order = MiddlewareOrder.PoweredByHeaderMiddleware;

+ 1 - 0
lib/middlewares/SessionMiddleware.ts

@@ -2,6 +2,7 @@ import { Middleware } from '../base/http';
 import session from 'express-session';
 import session from 'express-session';
 import { Guid } from '../base/util';
 import { Guid } from '../base/util';
 import { MiddlewareOrder } from './MiddlewareOrder';
 import { MiddlewareOrder } from './MiddlewareOrder';
+
 class SessionMiddleware extends Middleware {
 class SessionMiddleware extends Middleware {
 	protected order = MiddlewareOrder.SessionMiddleware;
 	protected order = MiddlewareOrder.SessionMiddleware;
 	protected route = null;
 	protected route = null;

+ 2 - 2
lib/middlewares/SwaggerUiSetupMiddleware.ts

@@ -1,7 +1,7 @@
 import swaggerJsDoc, { OAS3Options, Options, SecurityRequirement } from 'swagger-jsdoc';
 import swaggerJsDoc, { OAS3Options, Options, SecurityRequirement } from 'swagger-jsdoc';
 import { Middleware } from '../base/http';
 import { Middleware } from '../base/http';
 import swaggerUi from 'swagger-ui-express';
 import swaggerUi from 'swagger-ui-express';
-import { $$ } from '../base/i18n';
+import { $ } from '../base/i18n';
 import { MiddlewareOrder } from './MiddlewareOrder';
 import { MiddlewareOrder } from './MiddlewareOrder';
 
 
 class SwaggerUiSetupMiddleware extends Middleware {
 class SwaggerUiSetupMiddleware extends Middleware {
@@ -35,7 +35,7 @@ class SwaggerUiSetupMiddleware extends Middleware {
 
 
 		const swaggerDocs = swaggerJsDoc(swaggerOptions as Options);
 		const swaggerDocs = swaggerJsDoc(swaggerOptions as Options);
 
 
-		this.context.logInfo($$('org.crazydoctor.expressts.swagger.registered', { path: this.context.swaggerRoute }));
+		this.context.logInfo($('org.crazydoctor.extress.swagger.registered', { path: this.context.swaggerRoute }));
 
 
 		return swaggerUi.setup(swaggerDocs);
 		return swaggerUi.setup(swaggerDocs);
 
 

+ 37 - 102
lib/server/Server.ts

@@ -1,21 +1,18 @@
-import path from 'path';
 import fs from 'fs';
 import fs from 'fs';
 import http from 'http';
 import http from 'http';
-import { pathToFileURL } from 'url';
 import express, { Express } from 'express';
 import express, { Express } from 'express';
-import { Middleware, Route, HttpMethod, HttpHandler } from '../base/http';
+import { Middleware, Route, HttpMethod } from '../base/http';
 import { RouteNotSetException } from '../base/exceptions';
 import { RouteNotSetException } from '../base/exceptions';
 import { IncorrectMethodException } from '../base/exceptions';
 import { IncorrectMethodException } from '../base/exceptions';
 import { Logger, Message } from '../base/logger';
 import { Logger, Message } from '../base/logger';
 import { ServerProperties } from './ServerProperties';
 import { ServerProperties } from './ServerProperties';
-import { i18nLoader, $$ } from '../base/i18n';
+import { i18nLoader, $ } from '../base/i18n';
 import { WebSocketServer, WebSocket as WS } from 'ws';
 import { WebSocketServer, WebSocket as WS } from 'ws';
-import { InvalidMiddlewareException } from '../base/exceptions';
-import { InvalidRouteException } from '../base/exceptions';
 import { ServerNotInitializedException } from '../base/exceptions';
 import { ServerNotInitializedException } from '../base/exceptions';
 import { WebSocketHandler } from '../base/websocket';
 import { WebSocketHandler } from '../base/websocket';
-import { Guid } from '../base/util';
-import { ExpressJsonMiddleware, ExpressUrlencodedMiddleware, InternalServerErrorHandler, NotFoundErrorHandler, PoweredByHeaderMiddleware, SessionMiddleware, SwaggerUiServeMiddleware, SwaggerUiSetupMiddleware } from '../middlewares';
+import Registry from '../base/registry/Registry';
+import SystemRegistry from '../base/registry/SystemRegistry';
+import DynamicRegistry from '../base/registry/DynamicRegistry';
 
 
 /** @sealed */
 /** @sealed */
 class Server {
 class Server {
@@ -25,7 +22,6 @@ class Server {
 	private readonly host: string;
 	private readonly host: string;
 	private readonly logger: Logger;
 	private readonly logger: Logger;
 	private i18n: i18nLoader;
 	private i18n: i18nLoader;
-	private readonly httpHandlers: {[key: string]: HttpHandler};
 	private readonly wsHandlers: {[url: string]: WebSocketHandler};
 	private readonly wsHandlers: {[url: string]: WebSocketHandler};
 	private readonly wsServers: {[url: string]: WebSocketServer};
 	private readonly wsServers: {[url: string]: WebSocketServer};
 	private initialized: boolean;
 	private initialized: boolean;
@@ -45,9 +41,8 @@ class Server {
 	private readonly swaggerApiVersion?: string;
 	private readonly swaggerApiVersion?: string;
 	private readonly swaggerRoute?: string;
 	private readonly swaggerRoute?: string;
 
 
-	private swagger: boolean = false;
-	private json: boolean = false;
-	private urlencoded: boolean = false;
+	public static registry: Registry;
+	private readonly systemRegistry: SystemRegistry;
 
 
 	public constructor(properties: ServerProperties) {
 	public constructor(properties: ServerProperties) {
 		this.instance = express();
 		this.instance = express();
@@ -58,11 +53,8 @@ class Server {
 		if(properties.locale)
 		if(properties.locale)
 			this.i18n.setLocale(properties.locale);
 			this.i18n.setLocale(properties.locale);
 		this.logger = new Logger();
 		this.logger = new Logger();
-		this.httpHandlers = {};
 		this.wsHandlers = properties.wsHandlers || {};
 		this.wsHandlers = properties.wsHandlers || {};
 		this.wsServers = {};
 		this.wsServers = {};
-		this.json = properties.json || false;
-		this.urlencoded = properties.urlencoded || false;
 		this.i18nPath = properties.i18nPath;
 		this.i18nPath = properties.i18nPath;
 		this.middlewaresPath = properties.middlewaresPath;
 		this.middlewaresPath = properties.middlewaresPath;
 		this.routesPath = properties.routesPath;
 		this.routesPath = properties.routesPath;
@@ -77,17 +69,27 @@ class Server {
 			this.swaggerRoute = properties.swagger?.route || '/api-docs';
 			this.swaggerRoute = properties.swagger?.route || '/api-docs';
 			this.swaggerComponents = properties.swagger?.components;
 			this.swaggerComponents = properties.swagger?.components;
 			this.swaggerSecurity = properties.swagger?.security;
 			this.swaggerSecurity = properties.swagger?.security;
-			this.swagger = true;
 		}
 		}
+
+		this.systemRegistry = new SystemRegistry({
+			json: properties.json || false,
+			urlencoded: properties.urlencoded || false,
+			sessions: properties.sessions || false,
+			swagger: properties.swagger != null
+		}).setServer(this) as SystemRegistry;
+
+		Server.registry = Server.registry == null ? new DynamicRegistry(this.routesPath, this.middlewaresPath) : Server.registry;
+		Server.registry.setServer(this);
+
 		this.initialized = false;
 		this.initialized = false;
 	}
 	}
 
 
-	public async init(): Promise<Server> {
+	private async init(): Promise<Server> {
 		if(this.viewEngine)
 		if(this.viewEngine)
 			this.instance.set('view engine', this.viewEngine);
 			this.instance.set('view engine', this.viewEngine);
 		if(this.viewsPath)
 		if(this.viewsPath)
 			this.instance.set('views', this.viewsPath);
 			this.instance.set('views', this.viewsPath);
-		this.registerSystemMiddlewares();
+		await this.systemRegistry.registerHttpHandlers();
 		await this.postInit();
 		await this.postInit();
 		this.initialized = true;
 		this.initialized = true;
 		return this;
 		return this;
@@ -96,10 +98,7 @@ class Server {
 	private async postInit(): Promise<void> {
 	private async postInit(): Promise<void> {
 		if(this.i18nPath)
 		if(this.i18nPath)
 			this.i18n.load(this.i18nPath);
 			this.i18n.load(this.i18nPath);
-		if(this.middlewaresPath)
-			await this.registerMiddlewares(this.middlewaresPath);
-		if(this.routesPath)
-			await this.registerRoutes(this.routesPath);
+		await Server.registry.registerHttpHandlers();
 		if(this.swaggerDocsPath)
 		if(this.swaggerDocsPath)
 			fs.writeFileSync(this.swaggerDocsPath, '');
 			fs.writeFileSync(this.swaggerDocsPath, '');
 		if(Object.keys(this.wsHandlers).length > 0) {
 		if(Object.keys(this.wsHandlers).length > 0) {
@@ -109,22 +108,7 @@ class Server {
 	}
 	}
 
 
 	private processHttpHandlers(): void {
 	private processHttpHandlers(): void {
-		const handlers: HttpHandler[] = [];
-		const middlewareOrders: number[] = [];
-		for(const key in this.httpHandlers) {
-			const handler = this.httpHandlers[key];
-			if(handler instanceof Middleware) {
-				const order = handler.getOrder();
-				if(middlewareOrders.includes(order))
-					throw `Ivalid order number: ${handler.constructor.name}`;
-				middlewareOrders.push(order);
-			}
-			handlers.push(this.httpHandlers[key]);
-		}
-
-		handlers.sort((a, b) => a instanceof Middleware && b instanceof Middleware && (a.getOrder() - b.getOrder()) || (a instanceof Middleware && -1 || (b instanceof Middleware && 1 || 0)));
-
-		for(const handler of handlers) {
+		for(const handler of Registry.getHttpHandlers()) {
 			if(handler instanceof Middleware)
 			if(handler instanceof Middleware)
 				this.addMiddleware(handler);
 				this.addMiddleware(handler);
 			else if (handler instanceof Route)
 			else if (handler instanceof Route)
@@ -157,8 +141,7 @@ class Server {
 		if(!this.swaggerDocsPath)
 		if(!this.swaggerDocsPath)
 			return this;
 			return this;
 		
 		
-		for(const routeName in this.httpHandlers) {
-			const route = this.httpHandlers[routeName];
+		for(const route of Registry.getHttpHandlers()) {
 			if(!(route instanceof Route))
 			if(!(route instanceof Route))
 				continue;
 				continue;
 
 
@@ -172,7 +155,7 @@ class Server {
 	
 	
 			if(docs.length > 0) {
 			if(docs.length > 0) {
 				fs.appendFileSync(this.swaggerDocsPath, `${docs}\n`);
 				fs.appendFileSync(this.swaggerDocsPath, `${docs}\n`);
-				this.logInfo($$('org.crazydoctor.expressts.swagger.routeGenerated', { route: route.getRoute() }));
+				this.logInfo($('org.crazydoctor.extress.swagger.routeGenerated', { route: route.getRoute() }));
 			}
 			}
 		}
 		}
 		return this;
 		return this;
@@ -245,57 +228,6 @@ class Server {
 		return this;
 		return this;
 	}
 	}
 
 
-	private registerSystemMiddlewares(): Server {
-		const json = this.json, urlencoded = this.urlencoded, swagger = this.swagger;
-		
-		json && this.appendHttpHandler(new ExpressJsonMiddleware(this));
-		urlencoded && this.appendHttpHandler(new ExpressUrlencodedMiddleware(this));
-		this.appendHttpHandler(new InternalServerErrorHandler(this));
-		this.appendHttpHandler(new NotFoundErrorHandler(this));
-		this.appendHttpHandler(new PoweredByHeaderMiddleware(this));
-		this.appendHttpHandler(new SessionMiddleware(this));
-		swagger && this.appendHttpHandler(new SwaggerUiServeMiddleware(this));
-		swagger && this.appendHttpHandler(new SwaggerUiSetupMiddleware(this));
-		return this;
-	}
-
-	private appendHttpHandler(handler: HttpHandler): void {
-		let id = Guid.new();
-		while(this.httpHandlers[id] != null)
-			id = Guid.new();
-		this.httpHandlers[id] = handler;
-	}
-
-	public async registerRoutes(dir: string): Promise<Server> {
-		const files = fs.readdirSync(dir, { recursive: true, encoding: 'utf8' });
-
-		for(const file of files) {
-			if(/\.js$/.test(file)) {
-				const fileUrl = pathToFileURL(path.join(dir, file)).toString();
-				const RouteClass = await import(fileUrl).then(mod => mod.default?.default ?? mod.default ?? mod);
-				if(RouteClass.prototype instanceof Route) {
-					this.appendHttpHandler(<HttpHandler>new RouteClass(this));
-				} else throw new InvalidRouteException(fileUrl);
-			}
-		}
-		return this;
-	}
-
-	public async registerMiddlewares(dir: string): Promise<Server> {
-		const files = fs.readdirSync(dir, { recursive: true, encoding: 'utf8' });
-
-		for(const file of files) {
-			if(/\.js$/.test(file)) {
-				const fileUrl = pathToFileURL(path.join(dir, file)).toString();
-				const MiddlewareClass = await import(fileUrl).then(mod => mod.default?.default ?? mod.default ?? mod);
-				if(MiddlewareClass.prototype instanceof Middleware) {
-					this.appendHttpHandler(<HttpHandler>new MiddlewareClass(this));
-				} else throw new InvalidMiddlewareException(fileUrl);
-			}
-		}
-		return this;
-	}
-
 	public getLogger(): Logger {
 	public getLogger(): Logger {
 		return this.logger;
 		return this.logger;
 	}
 	}
@@ -313,16 +245,19 @@ class Server {
 		return this.options ? this.options[key] || null : null;
 		return this.options ? this.options[key] || null : null;
 	}
 	}
 
 
-	public start(callback?: () => any): void {
-		if(!this.initialized)
-			throw new ServerNotInitializedException();
-		this.registerRoutesDocumentation();
-		this.processHttpHandlers();
-		const cb = (): void => {
-			this.logInfo($$('org.crazydoctor.expressts.start', { 'port': this.port }));
-			if(callback) callback();
-		};
-		this.httpServer.listen(this.port, cb);
+	public async start(callback?: () => any): Promise<Server> {
+		return this.init().then((server) => {
+			if(!this.initialized)
+				throw new ServerNotInitializedException();
+			this.registerRoutesDocumentation();
+			this.processHttpHandlers();
+			const cb = (): void => {
+				this.logInfo($('org.crazydoctor.extress.start', { 'port': this.port }));
+				if(callback) callback();
+			};
+			this.httpServer.listen(this.port, cb);
+			return server;
+		});
 	}
 	}
 }
 }
 
 

+ 3 - 2
lib/server/ServerProperties.ts

@@ -3,12 +3,13 @@ import { WebSocketHandler } from '../base/websocket';
 type ServerProperties = {
 type ServerProperties = {
 	port: number,
 	port: number,
 	host?: string,
 	host?: string,
+	middlewaresPath?: string,
+	sessions?: boolean,
+	routesPath?: string,
 	json?: boolean,
 	json?: boolean,
 	urlencoded?: boolean,
 	urlencoded?: boolean,
 	locale?: string,
 	locale?: string,
 	i18nPath?: string,
 	i18nPath?: string,
-	middlewaresPath?: string,
-	routesPath?: string,
 	viewEngine?: string,
 	viewEngine?: string,
 	viewsPath?: string,
 	viewsPath?: string,
 	swagger?: {
 	swagger?: {

+ 8 - 5
package-lock.json

@@ -1,23 +1,26 @@
 {
 {
-  "name": "org.crazydoctor.expressts",
-  "version": "1.2.0",
+  "name": "extress",
+  "version": "1.0.0",
   "lockfileVersion": 3,
   "lockfileVersion": 3,
   "requires": true,
   "requires": true,
   "packages": {
   "packages": {
     "": {
     "": {
-      "name": "org.crazydoctor.expressts",
-      "version": "1.2.0",
+      "name": "extress",
+      "version": "1.0.0",
       "dependencies": {
       "dependencies": {
         "@types/express": "^5.0.6",
         "@types/express": "^5.0.6",
         "@types/express-session": "^1.19.0",
         "@types/express-session": "^1.19.0",
-        "@types/node": "^25.6.0",
         "@types/swagger-jsdoc": "^6.0.4",
         "@types/swagger-jsdoc": "^6.0.4",
         "@types/swagger-ui-express": "^4.1.8",
         "@types/swagger-ui-express": "^4.1.8",
         "@types/ws": "^8.18.1"
         "@types/ws": "^8.18.1"
       },
       },
+      "bin": {
+        "extress": "dist/bin/extress.js"
+      },
       "devDependencies": {
       "devDependencies": {
         "@eslint/eslintrc": "^3.3.5",
         "@eslint/eslintrc": "^3.3.5",
         "@eslint/js": "^10.0.1",
         "@eslint/js": "^10.0.1",
+        "@types/node": "^25.6.0",
         "@typescript-eslint/eslint-plugin": "^8.58.2",
         "@typescript-eslint/eslint-plugin": "^8.58.2",
         "@typescript-eslint/parser": "^8.58.2",
         "@typescript-eslint/parser": "^8.58.2",
         "dts-bundle-generator": "^9.5.1",
         "dts-bundle-generator": "^9.5.1",

+ 7 - 4
package.json

@@ -1,11 +1,12 @@
 {
 {
-  "name": "org.crazydoctor.expressts",
-  "version": "1.2.0",
+  "name": "extress",
+  "version": "1.0.0",
   "devDependencies": {
   "devDependencies": {
     "@eslint/eslintrc": "^3.3.5",
     "@eslint/eslintrc": "^3.3.5",
     "@eslint/js": "^10.0.1",
     "@eslint/js": "^10.0.1",
     "@typescript-eslint/eslint-plugin": "^8.58.2",
     "@typescript-eslint/eslint-plugin": "^8.58.2",
     "@typescript-eslint/parser": "^8.58.2",
     "@typescript-eslint/parser": "^8.58.2",
+	"@types/node": "^25.6.0",
     "dts-bundle-generator": "^9.5.1",
     "dts-bundle-generator": "^9.5.1",
     "eslint": "^10.2.0",
     "eslint": "^10.2.0",
     "express": "^5.2.1",
     "express": "^5.2.1",
@@ -19,7 +20,6 @@
   "dependencies": {
   "dependencies": {
     "@types/express": "^5.0.6",
     "@types/express": "^5.0.6",
     "@types/express-session": "^1.19.0",
     "@types/express-session": "^1.19.0",
-    "@types/node": "^25.6.0",
     "@types/swagger-jsdoc": "^6.0.4",
     "@types/swagger-jsdoc": "^6.0.4",
     "@types/swagger-ui-express": "^4.1.8",
     "@types/swagger-ui-express": "^4.1.8",
     "@types/ws": "^8.18.1"
     "@types/ws": "^8.18.1"
@@ -29,9 +29,12 @@
   "files": [
   "files": [
     "dist"
     "dist"
   ],
   ],
+  "bin": "dist/bin/extress.js",
   "scripts": {
   "scripts": {
     "lint": "eslint .",
     "lint": "eslint .",
     "fixLint": "eslint . --fix",
     "fixLint": "eslint . --fix",
-    "build": "npx dts-bundle-generator --config dts.config.json && esbuild lib/index.ts --bundle --platform=node --outfile=dist/index.js --sourcemap=external --sources-content=true"
+	"buildBin": "esbuild bin/extress.ts --bundle --platform=node --minify --outfile=dist/bin/extress.js",
+	"buildSrc": "esbuild lib/index.ts --bundle --platform=node --outfile=dist/index.js --sourcemap=external --sources-content=true",
+    "build": "npx dts-bundle-generator --config dts.config.json && npm run buildSrc && npm run buildBin"
   }
   }
 }
 }

+ 4 - 3
tsconfig.json

@@ -2,14 +2,15 @@
   "compilerOptions": {
   "compilerOptions": {
     "target": "es6",
     "target": "es6",
     "module": "commonjs",
     "module": "commonjs",
-	"rootDir": "lib",
+	"rootDir": ".",
     "outDir": "types",
     "outDir": "types",
     "strict": true,
     "strict": true,
     "esModuleInterop": true,
     "esModuleInterop": true,
     "declaration": true,
     "declaration": true,
     "sourceMap": true,
     "sourceMap": true,
-	"emitDeclarationOnly": true
+	"emitDeclarationOnly": true,
+	"types": ["node"]
   },
   },
-  "include": ["lib/**/*"],
+  "include": ["lib/**/*", "bin/**/*"],
   "exclude": ["node_modules", "test"]
   "exclude": ["node_modules", "test"]
 }
 }

Some files were not shown because too many files changed in this diff