@abejarano/ts-express-server 1.5.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +14 -2
  2. package/dist/BootstrapServer.d.ts +13 -6
  3. package/dist/BootstrapServer.js +30 -23
  4. package/dist/BootstrapStandardServer.d.ts +2 -1
  5. package/dist/BootstrapStandardServer.js +6 -4
  6. package/dist/abstract/ServerModule.d.ts +2 -2
  7. package/dist/abstract/ServerService.d.ts +2 -2
  8. package/dist/abstract/ServerTypes.d.ts +55 -0
  9. package/dist/abstract/ServerTypes.js +8 -0
  10. package/dist/abstract/index.d.ts +1 -0
  11. package/dist/abstract/index.js +1 -0
  12. package/dist/adapters/BunAdapter.d.ts +8 -0
  13. package/dist/adapters/BunAdapter.js +418 -0
  14. package/dist/adapters/ExpressAdapter.d.ts +8 -0
  15. package/dist/adapters/ExpressAdapter.js +40 -0
  16. package/dist/adapters/index.d.ts +2 -0
  17. package/dist/adapters/index.js +18 -0
  18. package/dist/createRouter.d.ts +2 -0
  19. package/dist/createRouter.js +12 -0
  20. package/dist/decorators/Use.d.ts +2 -2
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.js +2 -0
  23. package/dist/modules/ControllersModule.d.ts +2 -2
  24. package/dist/modules/ControllersModule.js +14 -8
  25. package/dist/modules/CorsModule.d.ts +2 -2
  26. package/dist/modules/CorsModule.js +66 -2
  27. package/dist/modules/FileUploadModule.d.ts +4 -4
  28. package/dist/modules/FileUploadModule.js +43 -6
  29. package/dist/modules/RateLimitModule.d.ts +4 -4
  30. package/dist/modules/RateLimitModule.js +48 -7
  31. package/dist/modules/RequestContextModule.d.ts +2 -9
  32. package/dist/modules/RequestContextModule.js +53 -4
  33. package/dist/modules/RoutesModule.d.ts +4 -4
  34. package/dist/modules/RoutesModule.js +12 -3
  35. package/dist/modules/SecurityModule.d.ts +4 -4
  36. package/dist/modules/SecurityModule.js +43 -6
  37. package/dist/testing/createDecoratedTestApp.d.ts +3 -3
  38. package/dist/testing/createDecoratedTestApp.js +8 -4
  39. package/package.json +6 -7
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # TypeScript Express Server Framework
1
+ # TypeScript Server Framework (Express + Bun)
2
2
 
3
- A modular and extensible TypeScript framework for building Express.js servers with a clean architecture pattern that separates concerns between server modules and services.
3
+ A modular and extensible TypeScript framework for building Express or Bun servers with a clean architecture pattern that separates concerns between server modules and services.
4
4
 
5
5
  ## Features
6
6
 
@@ -12,6 +12,7 @@ A modular and extensible TypeScript framework for building Express.js servers wi
12
12
  - 🛡️ **Type Safety**: Full TypeScript support with strong typing
13
13
  - 🔧 **Configurable**: Highly customizable modules and services
14
14
  - 🎨 **Decorators**: Clean and declarative controller definition
15
+ - ⚙️ **Runtime Choice**: Run on Express (Node) or Bun via `ServerRuntime`
15
16
 
16
17
  ## Installation
17
18
 
@@ -32,6 +33,17 @@ yarn add @abejarano/ts-express-server
32
33
  - [API Reference](docs/api-reference.md)
33
34
  - [Examples](docs/examples.md)
34
35
 
36
+ ## Runtime Selection
37
+
38
+ ```typescript
39
+ import { BootstrapServer } from "@abejarano/ts-express-server";
40
+
41
+ const server = new BootstrapServer(3000, { runtime: "bun" });
42
+ server.start();
43
+ ```
44
+
45
+ You can also use `ServerRuntime.Bun` and `ServerRuntime.Express` if you prefer the enum.
46
+
35
47
  ## Contributing
36
48
 
37
49
  1. Fork the repository
@@ -1,20 +1,26 @@
1
- import { Express } from "express";
2
- import { Server as HttpServer } from "http";
3
1
  import { BaseServerModule, BaseServerService } from "./abstract";
2
+ import { ServerAdapter, ServerApp, ServerInstance, ServerRuntime } from "./abstract";
3
+ export interface BootstrapServerOptions {
4
+ runtime?: ServerRuntime;
5
+ adapter?: ServerAdapter;
6
+ }
4
7
  export declare class BootstrapServer {
5
8
  private readonly app;
6
9
  private readonly port;
7
- private httpServer?;
10
+ private server?;
8
11
  private modules;
9
12
  private services;
10
- constructor(port: number);
13
+ private readonly adapter;
14
+ private readonly runtime;
15
+ constructor(port: number, options?: BootstrapServerOptions);
11
16
  removeModule(moduleName: string): BootstrapServer;
12
17
  addModule(module: BaseServerModule): BootstrapServer;
13
18
  addModules(modules: BaseServerModule[]): BootstrapServer;
14
19
  addService(service: BaseServerService): BootstrapServer;
15
20
  addServices(services: BaseServerService[]): BootstrapServer;
16
- getApp(): Express;
17
- getHttpServer(): HttpServer | undefined;
21
+ getApp(): ServerApp;
22
+ getServer(): ServerInstance | undefined;
23
+ getHttpServer(): ServerInstance | undefined;
18
24
  initialize(): Promise<void>;
19
25
  start(): Promise<void>;
20
26
  gracefulShutdown(): Promise<void>;
@@ -23,4 +29,5 @@ export declare class BootstrapServer {
23
29
  private initializeServices;
24
30
  private initializeServerModules;
25
31
  private setupGracefulShutdown;
32
+ private createAdapter;
26
33
  }
@@ -1,23 +1,17 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.BootstrapServer = void 0;
7
- const express_1 = __importDefault(require("express"));
8
- const body_parser_1 = __importDefault(require("body-parser"));
9
- const cookie_parser_1 = __importDefault(require("cookie-parser"));
4
+ const abstract_1 = require("./abstract");
5
+ const adapters_1 = require("./adapters");
10
6
  class BootstrapServer {
11
- constructor(port) {
7
+ constructor(port, options) {
12
8
  this.modules = [];
13
9
  this.services = [];
14
10
  this.port = port;
15
- this.app = (0, express_1.default)();
16
- this.app.use(express_1.default.json());
17
- this.app.use(body_parser_1.default.urlencoded({ extended: true }));
18
- this.app.use((0, cookie_parser_1.default)());
19
- this.app.set("port", port);
20
- this.app.set("trust proxy", 1);
11
+ this.adapter = options?.adapter ?? this.createAdapter(options?.runtime);
12
+ this.runtime = this.adapter.runtime;
13
+ this.app = this.adapter.createApp();
14
+ this.adapter.configure(this.app, port);
21
15
  }
22
16
  removeModule(moduleName) {
23
17
  this.modules = this.modules.filter((m) => m.getModuleName() !== moduleName);
@@ -60,8 +54,11 @@ class BootstrapServer {
60
54
  getApp() {
61
55
  return this.app;
62
56
  }
57
+ getServer() {
58
+ return this.server;
59
+ }
63
60
  getHttpServer() {
64
- return this.httpServer;
61
+ return this.server;
65
62
  }
66
63
  async initialize() {
67
64
  await this.initializeServerModules();
@@ -69,12 +66,12 @@ class BootstrapServer {
69
66
  async start() {
70
67
  await this.initializeServerModules();
71
68
  return new Promise((resolve) => {
72
- this.httpServer = this.app.listen(this.port, () => {
69
+ this.server = this.adapter.listen(this.app, this.port, () => {
73
70
  console.log(`Server running on port ${this.port}`);
74
71
  this.setupGracefulShutdown();
75
72
  resolve();
76
73
  });
77
- this.initializeServices(this.httpServer);
74
+ this.initializeServices(this.server);
78
75
  });
79
76
  }
80
77
  async gracefulShutdown() {
@@ -109,12 +106,12 @@ class BootstrapServer {
109
106
  }
110
107
  }
111
108
  // Close HTTP server
112
- if (this.httpServer) {
113
- console.log("Closing HTTP server...");
109
+ if (this.server) {
110
+ console.log("Closing server...");
114
111
  await new Promise((resolve) => {
115
- this.httpServer.close(() => resolve());
112
+ this.server.close(() => resolve());
116
113
  });
117
- console.log("HTTP server closed");
114
+ console.log("Server closed");
118
115
  }
119
116
  console.log("Graceful shutdown completed. Exiting...");
120
117
  process.exit(0);
@@ -131,11 +128,11 @@ class BootstrapServer {
131
128
  hasModule(moduleClass) {
132
129
  return this.modules.some((m) => m instanceof moduleClass);
133
130
  }
134
- async initializeServices(http) {
131
+ async initializeServices(server) {
135
132
  console.log("Starting services...");
136
133
  for (const service of this.services) {
137
134
  try {
138
- await service.start(http);
135
+ await service.start(server);
139
136
  console.log(`Service started: ${service.name}`);
140
137
  }
141
138
  catch (error) {
@@ -149,9 +146,13 @@ class BootstrapServer {
149
146
  // Sort modules by priority (lower number = higher priority)
150
147
  this.modules.sort((a, b) => (a.priority || 0) - (b.priority || 0));
151
148
  console.log("Initializing server modules in priority order:");
149
+ const context = {
150
+ runtime: this.runtime,
151
+ adapter: this.adapter,
152
+ };
152
153
  for (const module of this.modules) {
153
154
  try {
154
- await module.init(this.app);
155
+ await module.init(this.app, context);
155
156
  console.log(`Module initialized: ${module.getModuleName()}`);
156
157
  }
157
158
  catch (error) {
@@ -169,5 +170,11 @@ class BootstrapServer {
169
170
  process.on("SIGINT", () => shutdown("SIGINT"));
170
171
  process.on("SIGTERM", () => shutdown("SIGTERM"));
171
172
  }
173
+ createAdapter(runtime) {
174
+ if (runtime === abstract_1.ServerRuntime.Bun) {
175
+ return new adapters_1.BunAdapter();
176
+ }
177
+ return new adapters_1.ExpressAdapter();
178
+ }
172
179
  }
173
180
  exports.BootstrapServer = BootstrapServer;
@@ -1,7 +1,8 @@
1
1
  import { BootstrapServer } from "./BootstrapServer";
2
2
  import { ControllersModule, RoutesModule } from "./modules";
3
- import { BaseServerModule, BaseServerService } from "./abstract";
3
+ import { BaseServerModule, BaseServerService, ServerRuntime } from "./abstract";
4
4
  export interface BootstrapStandardServerOptions {
5
+ runtime?: ServerRuntime;
5
6
  modules?: {
6
7
  cors?: BaseServerModule | false;
7
8
  security?: BaseServerModule | false;
@@ -64,12 +64,14 @@ function BootstrapStandardServer(port, arg2, arg3, arg4, arg5) {
64
64
  if (preset?.extra?.length) {
65
65
  modulesToRegister.push(...preset.extra);
66
66
  }
67
- const expressServer = new BootstrapServer_1.BootstrapServer(port).addModules(modulesToRegister);
67
+ const server = new BootstrapServer_1.BootstrapServer(port, {
68
+ runtime: options?.runtime,
69
+ }).addModules(modulesToRegister);
68
70
  if (controllersModule) {
69
- expressServer.addModule(controllersModule);
71
+ server.addModule(controllersModule);
70
72
  }
71
73
  if (services) {
72
- expressServer.addServices(services);
74
+ server.addServices(services);
73
75
  }
74
- return expressServer;
76
+ return server;
75
77
  }
@@ -1,7 +1,7 @@
1
- import { Express } from "express";
1
+ import { ServerApp, ServerContext } from "./ServerTypes";
2
2
  export declare abstract class BaseServerModule {
3
3
  priority: number;
4
4
  abstract getModuleName(): string;
5
- abstract init(app: Express): Promise<void> | void;
5
+ abstract init(app: ServerApp, context?: ServerContext): Promise<void> | void;
6
6
  shutdown(): Promise<void>;
7
7
  }
@@ -1,6 +1,6 @@
1
- import { Server as HttpServer } from "http";
1
+ import { ServerInstance } from "./ServerTypes";
2
2
  export declare abstract class BaseServerService {
3
3
  abstract name: string;
4
- abstract start(http: HttpServer): Promise<void> | void;
4
+ abstract start(server: ServerInstance): Promise<void> | void;
5
5
  stop(): Promise<void>;
6
6
  }
@@ -0,0 +1,55 @@
1
+ export declare enum ServerRuntime {
2
+ Express = "express",
3
+ Bun = "bun"
4
+ }
5
+ export type NextFunction = (err?: unknown) => void;
6
+ export type ServerHandler = (req: any, res: any, next: NextFunction) => any;
7
+ export interface ServerRequest {
8
+ method: string;
9
+ path: string;
10
+ originalUrl?: string;
11
+ params: Record<string, string>;
12
+ query: Record<string, string | string[]>;
13
+ headers: Record<string, string | string[] | undefined>;
14
+ body?: unknown;
15
+ files?: unknown;
16
+ cookies?: Record<string, string>;
17
+ ip?: string;
18
+ requestId?: string;
19
+ raw?: unknown;
20
+ }
21
+ export interface ServerResponse {
22
+ status(code: number): this;
23
+ json(body: unknown): void | Promise<void>;
24
+ send(body: unknown): void | Promise<void>;
25
+ set(name: string, value: string): this;
26
+ header(name: string, value: string): this;
27
+ end(body?: unknown): void | Promise<void>;
28
+ }
29
+ export type ServerHandlerInput = ServerHandler | ServerHandler[] | ServerRouter;
30
+ export interface ServerRouter {
31
+ use(pathOrHandler: string | ServerHandlerInput, ...handlers: ServerHandlerInput[]): void;
32
+ get(path: string, ...handlers: ServerHandler[]): void;
33
+ post(path: string, ...handlers: ServerHandler[]): void;
34
+ put(path: string, ...handlers: ServerHandler[]): void;
35
+ delete(path: string, ...handlers: ServerHandler[]): void;
36
+ patch(path: string, ...handlers: ServerHandler[]): void;
37
+ }
38
+ export interface ServerApp extends ServerRouter {
39
+ set?(key: string, value: unknown): void;
40
+ listen?(port: number, callback?: () => void): unknown;
41
+ }
42
+ export type ServerInstance = {
43
+ close(callback?: () => void): void;
44
+ };
45
+ export interface ServerAdapter {
46
+ runtime: ServerRuntime;
47
+ createApp(): ServerApp;
48
+ createRouter(): ServerRouter;
49
+ configure(app: ServerApp, port: number): void;
50
+ listen(app: ServerApp, port: number, onListen: () => void): ServerInstance;
51
+ }
52
+ export interface ServerContext {
53
+ runtime: ServerRuntime;
54
+ adapter: ServerAdapter;
55
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServerRuntime = void 0;
4
+ var ServerRuntime;
5
+ (function (ServerRuntime) {
6
+ ServerRuntime["Express"] = "express";
7
+ ServerRuntime["Bun"] = "bun";
8
+ })(ServerRuntime || (exports.ServerRuntime = ServerRuntime = {}));
@@ -1,2 +1,3 @@
1
1
  export * from "./ServerService";
2
2
  export * from "./ServerModule";
3
+ export * from "./ServerTypes";
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./ServerService"), exports);
18
18
  __exportStar(require("./ServerModule"), exports);
19
+ __exportStar(require("./ServerTypes"), exports);
@@ -0,0 +1,8 @@
1
+ import { ServerAdapter, ServerApp, ServerInstance, ServerRouter, ServerRuntime } from "../abstract/ServerTypes";
2
+ export declare class BunAdapter implements ServerAdapter {
3
+ runtime: ServerRuntime;
4
+ createApp(): ServerApp;
5
+ createRouter(): ServerRouter;
6
+ configure(app: ServerApp, _port: number): void;
7
+ listen(app: ServerApp, port: number, onListen: () => void): ServerInstance;
8
+ }