@abejarano/ts-express-server 1.7.6 → 1.7.7

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 CHANGED
@@ -1,25 +1,22 @@
1
- # TypeScript Server Framework (Express + Bun)
1
+ # TypeScript Server Framework (Bun)
2
2
 
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.
3
+ Un framework TypeScript moderno y modular para construir APIs en Bun con una arquitectura limpia, extensible y enfocada en productividad. Separa responsabilidades en modulos, servicios y controladores con decoradores, incluye middlewares esenciales listos para usar y mantiene una experiencia tipada end-to-end.
4
4
 
5
5
  ## Features
6
6
 
7
- - 🏗️ **Modular Architecture**: Build your server using reusable modules
8
- - 🚀 **Service Management**: Integrate background services that start with your server
9
- - 📦 **Built-in Modules**: Pre-configured modules for common functionality
10
- - 🔄 **Graceful Shutdown**: Proper cleanup and shutdown handling
11
- - ⚡ **Priority System**: Control module initialization order
12
- - 🛡️ **Type Safety**: Full TypeScript support with strong typing
13
- - 🔧 **Configurable**: Highly customizable modules and services
14
- - 🎨 **Decorators**: Clean and declarative controller definition
15
- - ⚙️ **Runtime Choice**: Run on Express (Node) or Bun via `ServerRuntime`
7
+ - 🏗️ **Arquitectura modular**: arma el servidor con modulos reutilizables y reemplazables
8
+ - 🚀 **Servicios de fondo**: inicia procesos y workers junto al servidor
9
+ - 📦 **Modulos incluidos**: CORS, seguridad, rate limit, uploads y contexto de request
10
+ - 🔄 **Apagado limpio**: shutdown ordenado y seguro para modulos/servicios
11
+ - ⚡ **Prioridades**: control total del orden de inicializacion
12
+ - 🛡️ **Type safety real**: tipado fuerte en request, response y decoradores
13
+ - 🔧 **Configurable**: cambia o desactiva piezas sin romper el core
14
+ - 🎨 **Decoradores**: controladores claros, declarativos y faciles de testear
16
15
 
17
16
  ## Installation
18
17
 
19
18
  ```bash
20
- npm install @abejarano/ts-express-server
21
- # or
22
- yarn add @abejarano/ts-express-server
19
+ bun add @abejarano/ts-express-server
23
20
  ```
24
21
 
25
22
  ## Documentation
@@ -33,17 +30,21 @@ yarn add @abejarano/ts-express-server
33
30
  - [API Reference](docs/api-reference.md)
34
31
  - [Examples](docs/examples.md)
35
32
 
36
- ## Runtime Selection
33
+ ## File uploads
37
34
 
38
- ```typescript
39
- import { BootstrapServer } from "@abejarano/ts-express-server";
35
+ Uploads are disabled unless `FileUploadModule` is registered. Configure limits and MIME allowlists through the module:
40
36
 
41
- const server = new BootstrapServer(3000, { runtime: "bun" });
42
- server.start();
37
+ ```typescript
38
+ import { FileUploadModule } from "@abejarano/ts-express-server";
39
+
40
+ const fileUpload = new FileUploadModule({
41
+ maxBodyBytes: 10 * 1024 * 1024,
42
+ maxFileBytes: 10 * 1024 * 1024,
43
+ maxFiles: 10,
44
+ allowedMimeTypes: ["image/*", "application/pdf"],
45
+ });
43
46
  ```
44
47
 
45
- You can also use `ServerRuntime.Bun` and `ServerRuntime.Express` if you prefer the enum.
46
-
47
48
  ## Contributing
48
49
 
49
50
  1. Fork the repository
@@ -1,7 +1,6 @@
1
1
  import { BaseServerModule, BaseServerService } from "./abstract";
2
- import { ServerAdapter, ServerApp, ServerInstance, ServerRuntime } from "./abstract";
2
+ import { ServerAdapter, ServerApp, ServerInstance } from "./abstract";
3
3
  export interface BootstrapServerOptions {
4
- runtime?: ServerRuntime;
5
4
  adapter?: ServerAdapter;
6
5
  }
7
6
  export declare class BootstrapServer {
@@ -29,5 +28,4 @@ export declare class BootstrapServer {
29
28
  private initializeServices;
30
29
  private initializeServerModules;
31
30
  private setupGracefulShutdown;
32
- private createAdapter;
33
31
  }
@@ -1,14 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BootstrapServer = void 0;
4
- const abstract_1 = require("./abstract");
5
4
  const adapters_1 = require("./adapters");
6
5
  class BootstrapServer {
7
6
  constructor(port, options) {
8
7
  this.modules = [];
9
8
  this.services = [];
10
9
  this.port = port;
11
- this.adapter = options?.adapter ?? this.createAdapter(options?.runtime);
10
+ this.adapter = options?.adapter ?? new adapters_1.BunAdapter();
12
11
  this.runtime = this.adapter.runtime;
13
12
  this.app = this.adapter.createApp();
14
13
  this.adapter.configure(this.app, port);
@@ -170,11 +169,5 @@ class BootstrapServer {
170
169
  process.on("SIGINT", () => shutdown("SIGINT"));
171
170
  process.on("SIGTERM", () => shutdown("SIGTERM"));
172
171
  }
173
- createAdapter(runtime) {
174
- if (runtime === abstract_1.ServerRuntime.Bun) {
175
- return new adapters_1.BunAdapter();
176
- }
177
- return new adapters_1.ExpressAdapter();
178
- }
179
172
  }
180
173
  exports.BootstrapServer = BootstrapServer;
@@ -1,8 +1,8 @@
1
1
  import { BootstrapServer } from "./BootstrapServer";
2
- import { ControllersModule, RoutesModule } from "./modules";
3
- import { BaseServerModule, BaseServerService, ServerRuntime } from "./abstract";
2
+ import { ControllersModule } from "./modules";
3
+ import { BaseServerModule, BaseServerService, ServerAdapter } from "./abstract";
4
4
  export interface BootstrapStandardServerOptions {
5
- runtime?: ServerRuntime;
5
+ adapter?: ServerAdapter;
6
6
  modules?: {
7
7
  cors?: BaseServerModule | false;
8
8
  security?: BaseServerModule | false;
@@ -13,9 +13,6 @@ export interface BootstrapStandardServerOptions {
13
13
  };
14
14
  services?: BaseServerService[];
15
15
  }
16
- export declare function BootstrapStandardServer(port: number, module: RoutesModule | ControllersModule, services?: BaseServerService[]): BootstrapServer;
17
- export declare function BootstrapStandardServer(port: number, module: RoutesModule | ControllersModule, services: BaseServerService[], options: BootstrapStandardServerOptions): BootstrapServer;
18
- export declare function BootstrapStandardServer(port: number, module: RoutesModule | ControllersModule, options: BootstrapStandardServerOptions): BootstrapServer;
19
- export declare function BootstrapStandardServer(port: number, routes: RoutesModule, controllersModule: ControllersModule, services?: BaseServerService[]): BootstrapServer;
20
- export declare function BootstrapStandardServer(port: number, routes: RoutesModule, controllersModule: ControllersModule, services: BaseServerService[], options: BootstrapStandardServerOptions): BootstrapServer;
21
- export declare function BootstrapStandardServer(port: number, routes: RoutesModule, controllersModule: ControllersModule, options: BootstrapStandardServerOptions): BootstrapServer;
16
+ export declare function BootstrapStandardServer(port: number, module: ControllersModule, services?: BaseServerService[]): BootstrapServer;
17
+ export declare function BootstrapStandardServer(port: number, module: ControllersModule, services: BaseServerService[], options: BootstrapStandardServerOptions): BootstrapServer;
18
+ export declare function BootstrapStandardServer(port: number, module: ControllersModule, options: BootstrapStandardServerOptions): BootstrapServer;
@@ -3,27 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BootstrapStandardServer = BootstrapStandardServer;
4
4
  const BootstrapServer_1 = require("./BootstrapServer");
5
5
  const modules_1 = require("./modules");
6
- function BootstrapStandardServer(port, arg2, arg3, arg4, arg5) {
7
- let routesModule;
6
+ function BootstrapStandardServer(port, arg2, arg3, arg4) {
8
7
  let controllersModule;
9
8
  let services;
10
9
  let options;
11
- const setControllersModule = (module) => {
12
- if (controllersModule && controllersModule !== module) {
13
- throw new Error("ControllersModule provided multiple times. Pass a single instance only.");
14
- }
15
- controllersModule = module;
16
- };
17
- if (arg2 instanceof modules_1.RoutesModule) {
18
- routesModule = arg2;
19
- }
20
- else if (arg2 instanceof modules_1.ControllersModule) {
21
- setControllersModule(arg2);
22
- routesModule = new modules_1.RoutesModule();
23
- }
24
- else {
25
- throw new Error("Invalid second argument. Must be RoutesModule or ControllersModule");
26
- }
10
+ controllersModule = arg2;
27
11
  const addServices = (value) => {
28
12
  if (!value?.length) {
29
13
  return;
@@ -34,10 +18,6 @@ function BootstrapStandardServer(port, arg2, arg3, arg4, arg5) {
34
18
  if (!value) {
35
19
  return;
36
20
  }
37
- if (value instanceof modules_1.ControllersModule) {
38
- setControllersModule(value);
39
- return;
40
- }
41
21
  if (Array.isArray(value)) {
42
22
  addServices(value);
43
23
  return;
@@ -46,9 +26,8 @@ function BootstrapStandardServer(port, arg2, arg3, arg4, arg5) {
46
26
  };
47
27
  processOptionalArg(arg3);
48
28
  processOptionalArg(arg4);
49
- processOptionalArg(arg5);
50
29
  addServices(options?.services);
51
- const modulesToRegister = [routesModule];
30
+ const modulesToRegister = [controllersModule];
52
31
  const preset = options?.modules;
53
32
  const registerModule = (factory, override) => {
54
33
  if (override === false) {
@@ -65,11 +44,8 @@ function BootstrapStandardServer(port, arg2, arg3, arg4, arg5) {
65
44
  modulesToRegister.push(...preset.extra);
66
45
  }
67
46
  const server = new BootstrapServer_1.BootstrapServer(port, {
68
- runtime: options?.runtime,
47
+ adapter: options?.adapter,
69
48
  }).addModules(modulesToRegister);
70
- if (controllersModule) {
71
- server.addModule(controllersModule);
72
- }
73
49
  if (services) {
74
50
  server.addServices(services);
75
51
  }
@@ -1,6 +1,4 @@
1
- import type fileUpload from "express-fileupload";
2
1
  export declare enum ServerRuntime {
3
- Express = "express",
4
2
  Bun = "bun"
5
3
  }
6
4
  export type NextFunction = (err?: unknown) => void;
@@ -48,7 +46,7 @@ export type BunMultipartFile = {
48
46
  arrayBuffer(): Promise<ArrayBuffer>;
49
47
  lastModified?: number;
50
48
  };
51
- export type ServerFile = BunMultipartFile | fileUpload.UploadedFile;
49
+ export type ServerFile = BunMultipartFile;
52
50
  export type ServerFiles = Record<string, ServerFile | ServerFile[]>;
53
51
  export type ServerHandlerInput = ServerHandler | ServerHandler[] | ServerRouter;
54
52
  export interface ServerRouter {
@@ -3,6 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ServerRuntime = void 0;
4
4
  var ServerRuntime;
5
5
  (function (ServerRuntime) {
6
- ServerRuntime["Express"] = "express";
7
6
  ServerRuntime["Bun"] = "bun";
8
7
  })(ServerRuntime || (exports.ServerRuntime = ServerRuntime = {}));
@@ -138,7 +138,8 @@ class BunResponse {
138
138
  ? filename
139
139
  : path_1.default.basename(safePath);
140
140
  this.headers.set("content-disposition", `attachment; filename="${sanitizeFilename(resolvedName)}"`);
141
- this.rawResponse = new Response(Bun.file(safePath));
141
+ const fileBuffer = (0, fs_1.readFileSync)(safePath);
142
+ this.rawResponse = new Response(fileBuffer);
142
143
  this.ended = true;
143
144
  this.resolveEnd?.();
144
145
  callback?.();
@@ -512,6 +513,12 @@ const createMultipartBodyParser = (app) => {
512
513
  if (!contentType.includes("multipart/form-data")) {
513
514
  return next();
514
515
  }
516
+ if (app.get("fileUploadEnabled") !== true) {
517
+ res
518
+ .status(415)
519
+ .json({ message: "File uploads are disabled. Enable FileUploadModule." });
520
+ return;
521
+ }
515
522
  const options = normalizeMultipartOptions(app.get("multipart"));
516
523
  const lengthHeader = req.headers["content-length"];
517
524
  const contentLength = parseContentLength(lengthHeader);
@@ -986,16 +993,8 @@ function resolveCookieDefaults(input) {
986
993
  }
987
994
  function resolveTrustProxySetting(app) {
988
995
  const input = app.get("trustProxy");
989
- const allowInsecure = app.get("allowInsecureTrustProxy") === true ||
990
- process?.env?.ALLOW_INSECURE_TRUST_PROXY === "true";
991
- if (input === true) {
992
- if (!allowInsecure) {
993
- throw new Error("Invalid trustProxy=true. Use CIDR allowlist or set allowInsecureTrustProxy=true explicitly.");
994
- }
995
- return true;
996
- }
997
- if (input === false) {
998
- return false;
996
+ if (typeof input === "boolean") {
997
+ throw new Error("Invalid trustProxy boolean. Use a CIDR allowlist or a custom trust function instead.");
999
998
  }
1000
999
  if (Array.isArray(input) && input.every((entry) => typeof entry === "string")) {
1001
1000
  return input;
@@ -1,2 +1 @@
1
1
  export * from "./BunAdapter";
2
- export * from "./ExpressAdapter";
@@ -15,4 +15,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./BunAdapter"), exports);
18
- __exportStar(require("./ExpressAdapter"), exports);
package/dist/index.d.ts CHANGED
@@ -4,7 +4,6 @@ export type { BootstrapServerOptions } from "./BootstrapServer";
4
4
  export { BootstrapStandardServer } from "./BootstrapStandardServer";
5
5
  export type { BootstrapStandardServerOptions } from "./BootstrapStandardServer";
6
6
  export * from "./adapters";
7
- export * from "./createRouter";
8
7
  export * from "./modules";
9
8
  export * from "./abstract";
10
9
  export * from "./decorators";
package/dist/index.js CHANGED
@@ -21,7 +21,6 @@ Object.defineProperty(exports, "BootstrapServer", { enumerable: true, get: funct
21
21
  var BootstrapStandardServer_1 = require("./BootstrapStandardServer");
22
22
  Object.defineProperty(exports, "BootstrapStandardServer", { enumerable: true, get: function () { return BootstrapStandardServer_1.BootstrapStandardServer; } });
23
23
  __exportStar(require("./adapters"), exports);
24
- __exportStar(require("./createRouter"), exports);
25
24
  __exportStar(require("./modules"), exports);
26
25
  __exportStar(require("./abstract"), exports);
27
26
  __exportStar(require("./decorators"), exports);
@@ -24,7 +24,7 @@ class ControllersModule extends abstract_1.BaseServerModule {
24
24
  if (!basePath) {
25
25
  return;
26
26
  }
27
- const adapter = context?.adapter ?? new adapters_1.ExpressAdapter();
27
+ const adapter = context?.adapter ?? new adapters_1.BunAdapter();
28
28
  const router = adapter.createRouter();
29
29
  // Create a single controller instance per controller class (singleton pattern)
30
30
  const controllerInstance = new ControllerClass();
@@ -109,7 +109,7 @@ class ControllersModule extends abstract_1.BaseServerModule {
109
109
  break;
110
110
  }
111
111
  });
112
- // Fallbacks for common Express arguments when not explicitly decorated
112
+ // Fallbacks for common handler arguments when not explicitly decorated
113
113
  if (args[0] === undefined) {
114
114
  args[0] = req;
115
115
  }
@@ -1,11 +1,11 @@
1
1
  import { BaseServerModule } from "../abstract";
2
2
  import { ServerApp, ServerContext } from "../abstract";
3
- import cors from "cors";
3
+ import type { CorsOptions } from "cors";
4
4
  export declare class CorsModule extends BaseServerModule {
5
5
  name: string;
6
6
  priority: number;
7
7
  private corsOptions;
8
- constructor(corsOptions?: cors.CorsOptions);
8
+ constructor(corsOptions?: CorsOptions);
9
9
  getModuleName(): string;
10
10
  init(app: ServerApp, context?: ServerContext): void;
11
11
  }
@@ -1,12 +1,7 @@
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.CorsModule = void 0;
7
4
  const abstract_1 = require("../abstract");
8
- const abstract_2 = require("../abstract");
9
- const cors_1 = __importDefault(require("cors"));
10
5
  class CorsModule extends abstract_1.BaseServerModule {
11
6
  constructor(corsOptions) {
12
7
  super();
@@ -24,11 +19,6 @@ class CorsModule extends abstract_1.BaseServerModule {
24
19
  return this.name;
25
20
  }
26
21
  init(app, context) {
27
- const runtime = context?.runtime ?? abstract_2.ServerRuntime.Express;
28
- if (runtime === abstract_2.ServerRuntime.Express) {
29
- app.use((0, cors_1.default)(this.corsOptions));
30
- return;
31
- }
32
22
  app.use(createCorsMiddleware(this.corsOptions));
33
23
  }
34
24
  }
@@ -1,6 +1,16 @@
1
1
  import { BaseServerModule } from "../abstract";
2
- import { ServerApp, ServerContext } from "../abstract";
3
- import type { Options as FileUploadOptions } from "express-fileupload";
2
+ import { BunMultipartFile, ServerApp, ServerContext } from "../abstract";
3
+ export type FileUploadOptions = {
4
+ maxBodyBytes?: number;
5
+ maxFileBytes?: number;
6
+ maxFiles?: number;
7
+ maxFields?: number;
8
+ maxFieldBytes?: number;
9
+ maxFieldsBytes?: number;
10
+ allowedMimeTypes?: string[];
11
+ allowedFileSignatures?: Array<"png" | "jpg" | "jpeg" | "pdf">;
12
+ validateFile?: (file: BunMultipartFile) => boolean | Promise<boolean>;
13
+ };
4
14
  export declare class FileUploadModule extends BaseServerModule {
5
15
  name: string;
6
16
  priority: number;
@@ -2,28 +2,19 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FileUploadModule = void 0;
4
4
  const abstract_1 = require("../abstract");
5
- const abstract_2 = require("../abstract");
6
5
  class FileUploadModule extends abstract_1.BaseServerModule {
7
6
  constructor(fileUploadOptions) {
8
7
  super();
9
8
  this.name = "FileUpload";
10
9
  this.priority = -60;
11
- this.fileUploadOptions = fileUploadOptions || {
12
- limits: { fileSize: 50 * 1024 * 1024 },
13
- useTempFiles: true,
14
- tempFileDir: "/tmp/",
15
- };
10
+ this.fileUploadOptions = fileUploadOptions ?? {};
16
11
  }
17
12
  getModuleName() {
18
13
  return this.name;
19
14
  }
20
15
  init(app, context) {
21
- const runtime = context?.runtime ?? abstract_2.ServerRuntime.Express;
22
- if (runtime === abstract_2.ServerRuntime.Express) {
23
- const fileUpload = require("express-fileupload");
24
- app.use(fileUpload(this.fileUploadOptions));
25
- return;
26
- }
16
+ app.set?.("fileUploadEnabled", true);
17
+ app.set?.("multipart", this.fileUploadOptions);
27
18
  }
28
19
  }
29
20
  exports.FileUploadModule = FileUploadModule;
@@ -1,6 +1,13 @@
1
1
  import { BaseServerModule } from "../abstract";
2
2
  import { ServerApp, ServerContext } from "../abstract";
3
- import type { Options as RateLimitOptions } from "express-rate-limit";
3
+ export type RateLimitOptions = {
4
+ windowMs?: number;
5
+ limit?: number;
6
+ max?: number;
7
+ standardHeaders?: boolean;
8
+ legacyHeaders?: boolean;
9
+ message?: string | Record<string, unknown>;
10
+ };
4
11
  export declare class RateLimitModule extends BaseServerModule {
5
12
  name: string;
6
13
  priority: number;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RateLimitModule = void 0;
4
4
  const abstract_1 = require("../abstract");
5
- const abstract_2 = require("../abstract");
6
5
  class RateLimitModule extends abstract_1.BaseServerModule {
7
6
  constructor(limiterOptions) {
8
7
  super();
@@ -19,14 +18,6 @@ class RateLimitModule extends abstract_1.BaseServerModule {
19
18
  return this.name;
20
19
  }
21
20
  init(app, context) {
22
- const runtime = context?.runtime ?? abstract_2.ServerRuntime.Express;
23
- if (runtime === abstract_2.ServerRuntime.Express) {
24
- const rateLimitModule = require("express-rate-limit");
25
- const rateLimit = rateLimitModule.default ?? rateLimitModule;
26
- const limiter = rateLimit(this.limiterOptions);
27
- app.use(limiter);
28
- return;
29
- }
30
21
  app.use(createRateLimitMiddleware(this.limiterOptions));
31
22
  }
32
23
  }
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SecurityModule = void 0;
4
4
  const abstract_1 = require("../abstract");
5
- const abstract_2 = require("../abstract");
6
5
  class SecurityModule extends abstract_1.BaseServerModule {
7
6
  constructor(helmetOptions) {
8
7
  super();
@@ -27,13 +26,6 @@ class SecurityModule extends abstract_1.BaseServerModule {
27
26
  return this.name;
28
27
  }
29
28
  init(app, context) {
30
- const runtime = context?.runtime ?? abstract_2.ServerRuntime.Express;
31
- if (runtime === abstract_2.ServerRuntime.Express) {
32
- const helmetModule = require("helmet");
33
- const helmet = helmetModule.default ?? helmetModule;
34
- app.use(helmet(this.helmetOptions));
35
- return;
36
- }
37
29
  app.use(createSecurityMiddleware(this.helmetOptions));
38
30
  }
39
31
  }
@@ -3,5 +3,4 @@ export * from "./ControllersModule";
3
3
  export * from "./FileUploadModule";
4
4
  export * from "./RateLimitModule";
5
5
  export * from "./RequestContextModule";
6
- export * from "./RoutesModule";
7
6
  export * from "./SecurityModule";
@@ -19,5 +19,4 @@ __exportStar(require("./ControllersModule"), exports);
19
19
  __exportStar(require("./FileUploadModule"), exports);
20
20
  __exportStar(require("./RateLimitModule"), exports);
21
21
  __exportStar(require("./RequestContextModule"), exports);
22
- __exportStar(require("./RoutesModule"), exports);
23
22
  __exportStar(require("./SecurityModule"), exports);
@@ -1,6 +1,6 @@
1
1
  import type { BootstrapServer } from "../BootstrapServer";
2
2
  import { ControllersModule } from "../modules";
3
- import { BaseServerService, ServerApp, ServerRuntime } from "../abstract";
3
+ import { BaseServerService, ServerApp } from "../abstract";
4
4
  import { BootstrapStandardServerOptions } from "../BootstrapStandardServer";
5
5
  type ControllerClass<T = any> = new (...args: any[]) => T;
6
6
  export interface DecoratedTestAppOptions {
@@ -9,7 +9,6 @@ export interface DecoratedTestAppOptions {
9
9
  port?: number;
10
10
  services?: BaseServerService[];
11
11
  standardOptions?: BootstrapStandardServerOptions;
12
- runtime?: ServerRuntime;
13
12
  }
14
13
  export interface DecoratedTestAppResult {
15
14
  app: ServerApp;
@@ -12,7 +12,7 @@ const mergeOptions = (base, override) => {
12
12
  ...(override.services ?? []),
13
13
  ];
14
14
  return {
15
- runtime: override.runtime ?? base.runtime,
15
+ adapter: override.adapter ?? base.adapter,
16
16
  services: mergedServices.length ? mergedServices : undefined,
17
17
  modules: {
18
18
  ...(base.modules ?? {}),
@@ -34,7 +34,6 @@ async function createDecoratedTestApp(options) {
34
34
  const mergedOptions = mergeOptions(baseOptions, standardOptions);
35
35
  const server = (0, BootstrapStandardServer_1.BootstrapStandardServer)(port, moduleInstance, {
36
36
  ...mergedOptions,
37
- runtime: options.runtime ?? mergedOptions.runtime,
38
37
  });
39
38
  await server.initialize();
40
39
  return {
package/package.json CHANGED
@@ -1,41 +1,33 @@
1
1
  {
2
2
  "name": "@abejarano/ts-express-server",
3
3
  "author": "angel bejarano / angel.bejarano@jaspesoft.com",
4
- "version": "1.7.6",
4
+ "version": "1.7.7",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "files": [
8
8
  "dist"
9
9
  ],
10
10
  "scripts": {
11
- "build": "tsc -p tsconfig.json",
12
- "clean": "rimraf dist",
13
- "prepare": "yarn build",
14
- "prebuild": "yarn clean",
15
- "format": "prettier --write .",
16
- "format:check": "prettier --check .",
17
- "typecheck": "tsc --noEmit",
18
- "prepack": "yarn build",
19
- "version:patch": "npm version patch",
20
- "version:minor": "npm version minor",
21
- "version:major": "npm version major",
22
- "test": "jest",
23
- "test:watch": "jest --watch",
24
- "test:coverage": "jest --coverage"
11
+ "build": "bun run tsc -p tsconfig.json",
12
+ "clean": "rm -rf dist",
13
+ "prepare": "bun run build",
14
+ "prebuild": "bun run clean",
15
+ "format": "bun run prettier --write .",
16
+ "format:check": "bun run prettier --check .",
17
+ "typecheck": "bun run tsc --noEmit",
18
+ "prepack": "bun run build",
19
+ "test": "bun test",
20
+ "test:watch": "bun test --watch",
21
+ "test:coverage": "bun test --coverage"
25
22
  },
26
23
  "keywords": [
27
24
  "server",
28
25
  "modular",
29
- "express"
26
+ "bun"
30
27
  ],
31
28
  "license": "MIT",
32
29
  "dependencies": {
33
- "body-parser": "^2.2.1",
34
- "cookie-parser": "^1.4.7",
35
30
  "cors": "^2.8.5",
36
- "express": "^5.2.1",
37
- "express-fileupload": "^1.5.2",
38
- "express-rate-limit": "^8.2.1",
39
31
  "helmet": "^8.1.0",
40
32
  "reflect-metadata": "^0.2.2",
41
33
  "uuid": "^13.0.0"
@@ -43,24 +35,14 @@
43
35
  "devDependencies": {
44
36
  "@semantic-release/changelog": "^6.0.3",
45
37
  "@semantic-release/git": "^10.0.1",
46
- "@types/body-parser": "^1.19.6",
47
- "@types/cookie-parser": "^1.4.9",
48
38
  "@types/cors": "^2.8.19",
49
- "@types/express": "^5.0.6",
50
- "@types/express-fileupload": "^1.5.1",
51
- "@types/jest": "^30.0.0",
52
- "@types/node": "^25.0.3",
53
- "@types/supertest": "^6.0.3",
54
- "jest": "^30.2.0",
39
+ "bun-types": "^1.3.5",
55
40
  "prettier": "^3.6.2",
56
- "rimraf": "^6.0.1",
57
41
  "semantic-release": "^25.0.2",
58
- "supertest": "^7.1.4",
59
- "ts-jest": "^29.4.5",
60
42
  "typescript": "^5.9.3"
61
43
  },
62
44
  "engines": {
63
- "node": ">=20"
45
+ "bun": ">=1.3.5"
64
46
  },
65
47
  "repository": {
66
48
  "type": "git",
@@ -1,8 +0,0 @@
1
- import { ServerAdapter, ServerApp, ServerInstance, ServerRouter, ServerRuntime } from "../abstract/ServerTypes";
2
- export declare class ExpressAdapter 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
- }
@@ -1,65 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExpressAdapter = void 0;
4
- const ServerTypes_1 = require("../abstract/ServerTypes");
5
- let expressModule = null;
6
- const getExpressModule = () => {
7
- if (!expressModule) {
8
- expressModule = require("express");
9
- }
10
- return expressModule;
11
- };
12
- class ExpressAdapter {
13
- constructor() {
14
- this.runtime = ServerTypes_1.ServerRuntime.Express;
15
- }
16
- createApp() {
17
- const express = getExpressModule();
18
- return express();
19
- }
20
- createRouter() {
21
- const express = getExpressModule();
22
- return express.Router();
23
- }
24
- configure(app, port) {
25
- const expressApp = app;
26
- const express = getExpressModule();
27
- const bodyParser = require("body-parser");
28
- const cookieParser = require("cookie-parser");
29
- const jsonParser = express.json();
30
- expressApp.use((req, res, next) => {
31
- if (!shouldParseJson(req)) {
32
- return next();
33
- }
34
- return jsonParser(req, res, next);
35
- });
36
- expressApp.use(bodyParser.urlencoded({ extended: true }));
37
- expressApp.use(cookieParser());
38
- expressApp.set("port", port);
39
- expressApp.set("trust proxy", 1);
40
- }
41
- listen(app, port, onListen) {
42
- const expressApp = app;
43
- return expressApp.listen(port, onListen);
44
- }
45
- }
46
- exports.ExpressAdapter = ExpressAdapter;
47
- const shouldParseJson = (req) => {
48
- const method = String(req.method || "").toUpperCase();
49
- if (method === "GET" || method === "HEAD") {
50
- return false;
51
- }
52
- const lengthHeader = req.headers?.["content-length"];
53
- if (lengthHeader === undefined) {
54
- return true;
55
- }
56
- const value = Array.isArray(lengthHeader) ? lengthHeader[0] : lengthHeader;
57
- if (!value) {
58
- return true;
59
- }
60
- const parsed = Number.parseInt(value, 10);
61
- if (Number.isNaN(parsed)) {
62
- return true;
63
- }
64
- return parsed > 0;
65
- };
@@ -1,2 +0,0 @@
1
- import { ServerRuntime, ServerRouter } from "./abstract";
2
- export declare const createRouter: (runtime?: ServerRuntime) => ServerRouter;
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createRouter = void 0;
4
- const abstract_1 = require("./abstract");
5
- const adapters_1 = require("./adapters");
6
- const createRouter = (runtime = abstract_1.ServerRuntime.Express) => {
7
- if (runtime === abstract_1.ServerRuntime.Bun) {
8
- return new adapters_1.BunAdapter().createRouter();
9
- }
10
- return new adapters_1.ExpressAdapter().createRouter();
11
- };
12
- exports.createRouter = createRouter;
@@ -1,17 +0,0 @@
1
- import { BaseServerModule } from "../abstract";
2
- import { ServerApp, ServerContext, ServerHandler, ServerRouter } from "../abstract";
3
- export interface RouteConfig {
4
- path: string;
5
- router: ServerRouter;
6
- middleware?: ServerHandler[] | ServerHandler;
7
- }
8
- export declare class RoutesModule extends BaseServerModule {
9
- name: string;
10
- priority: number;
11
- private routes;
12
- constructor(routes?: RouteConfig[]);
13
- getModuleName(): string;
14
- addRoute(route: RouteConfig): void;
15
- addRoutes(routes: RouteConfig[]): void;
16
- init(app: ServerApp, context?: ServerContext): void;
17
- }
@@ -1,43 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RoutesModule = void 0;
4
- const abstract_1 = require("../abstract");
5
- const abstract_2 = require("../abstract");
6
- class RoutesModule extends abstract_1.BaseServerModule {
7
- constructor(routes = []) {
8
- super();
9
- this.name = "Routes";
10
- this.priority = 10; // Executed after basic middlewares
11
- this.routes = routes;
12
- }
13
- getModuleName() {
14
- return this.name;
15
- }
16
- addRoute(route) {
17
- this.routes.push({
18
- ...route,
19
- });
20
- }
21
- addRoutes(routes) {
22
- this.routes.push(...routes);
23
- }
24
- init(app, context) {
25
- if (context?.runtime === abstract_2.ServerRuntime.Bun) {
26
- console.warn("[RoutesModule] Express routers are not supported on Bun. Migrate to decorated controllers for Bun runtime.");
27
- }
28
- this.routes.forEach(({ path, router, middleware }) => {
29
- const middlewareList = Array.isArray(middleware)
30
- ? middleware
31
- : middleware
32
- ? [middleware]
33
- : [];
34
- if (middlewareList.length > 0) {
35
- app.use(path, ...middlewareList, router);
36
- }
37
- else {
38
- app.use(path, router);
39
- }
40
- });
41
- }
42
- }
43
- exports.RoutesModule = RoutesModule;