@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.
- package/README.md +14 -2
- package/dist/BootstrapServer.d.ts +13 -6
- package/dist/BootstrapServer.js +30 -23
- package/dist/BootstrapStandardServer.d.ts +2 -1
- package/dist/BootstrapStandardServer.js +6 -4
- package/dist/abstract/ServerModule.d.ts +2 -2
- package/dist/abstract/ServerService.d.ts +2 -2
- package/dist/abstract/ServerTypes.d.ts +55 -0
- package/dist/abstract/ServerTypes.js +8 -0
- package/dist/abstract/index.d.ts +1 -0
- package/dist/abstract/index.js +1 -0
- package/dist/adapters/BunAdapter.d.ts +8 -0
- package/dist/adapters/BunAdapter.js +418 -0
- package/dist/adapters/ExpressAdapter.d.ts +8 -0
- package/dist/adapters/ExpressAdapter.js +40 -0
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.js +18 -0
- package/dist/createRouter.d.ts +2 -0
- package/dist/createRouter.js +12 -0
- package/dist/decorators/Use.d.ts +2 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/modules/ControllersModule.d.ts +2 -2
- package/dist/modules/ControllersModule.js +14 -8
- package/dist/modules/CorsModule.d.ts +2 -2
- package/dist/modules/CorsModule.js +66 -2
- package/dist/modules/FileUploadModule.d.ts +4 -4
- package/dist/modules/FileUploadModule.js +43 -6
- package/dist/modules/RateLimitModule.d.ts +4 -4
- package/dist/modules/RateLimitModule.js +48 -7
- package/dist/modules/RequestContextModule.d.ts +2 -9
- package/dist/modules/RequestContextModule.js +53 -4
- package/dist/modules/RoutesModule.d.ts +4 -4
- package/dist/modules/RoutesModule.js +12 -3
- package/dist/modules/SecurityModule.d.ts +4 -4
- package/dist/modules/SecurityModule.js +43 -6
- package/dist/testing/createDecoratedTestApp.d.ts +3 -3
- package/dist/testing/createDecoratedTestApp.js +8 -4
- package/package.json +6 -7
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# TypeScript Express
|
|
1
|
+
# TypeScript Server Framework (Express + Bun)
|
|
2
2
|
|
|
3
|
-
A modular and extensible TypeScript framework for building Express
|
|
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
|
|
10
|
+
private server?;
|
|
8
11
|
private modules;
|
|
9
12
|
private services;
|
|
10
|
-
|
|
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():
|
|
17
|
-
|
|
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
|
}
|
package/dist/BootstrapServer.js
CHANGED
|
@@ -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
|
|
8
|
-
const
|
|
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.
|
|
16
|
-
this.
|
|
17
|
-
this.app.
|
|
18
|
-
this.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
113
|
-
console.log("Closing
|
|
109
|
+
if (this.server) {
|
|
110
|
+
console.log("Closing server...");
|
|
114
111
|
await new Promise((resolve) => {
|
|
115
|
-
this.
|
|
112
|
+
this.server.close(() => resolve());
|
|
116
113
|
});
|
|
117
|
-
console.log("
|
|
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(
|
|
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(
|
|
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
|
|
67
|
+
const server = new BootstrapServer_1.BootstrapServer(port, {
|
|
68
|
+
runtime: options?.runtime,
|
|
69
|
+
}).addModules(modulesToRegister);
|
|
68
70
|
if (controllersModule) {
|
|
69
|
-
|
|
71
|
+
server.addModule(controllersModule);
|
|
70
72
|
}
|
|
71
73
|
if (services) {
|
|
72
|
-
|
|
74
|
+
server.addServices(services);
|
|
73
75
|
}
|
|
74
|
-
return
|
|
76
|
+
return server;
|
|
75
77
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
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:
|
|
5
|
+
abstract init(app: ServerApp, context?: ServerContext): Promise<void> | void;
|
|
6
6
|
shutdown(): Promise<void>;
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ServerInstance } from "./ServerTypes";
|
|
2
2
|
export declare abstract class BaseServerService {
|
|
3
3
|
abstract name: string;
|
|
4
|
-
abstract start(
|
|
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 = {}));
|
package/dist/abstract/index.d.ts
CHANGED
package/dist/abstract/index.js
CHANGED
|
@@ -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
|
+
}
|