{"_id":"@alliage/webserver-express","_rev":"4-99e116c915f1647e491f1e44eded1bdc","name":"@alliage/webserver-express","dist-tags":{"latest":"0.1.0-beta.2"},"versions":{"0.1.0-beta.0":{"name":"@alliage/webserver-express","version":"0.1.0-beta.0","author":{"name":"bo.lebon@gmail.com"},"license":"ISC","_id":"@alliage/webserver-express@0.1.0-beta.0","maintainers":[{"name":"borislebon","email":"bo.lebon@gmail.com"},{"name":"thehumblejester","email":"the.humble.jester@gmail.com"}],"homepage":"https://github.com/alliage-framework/web#readme","bugs":{"url":"https://github.com/alliage-framework/web/issues"},"dist":{"shasum":"5757d5752e3cea79c3ed50418903d10569e9d20b","tarball":"https://registry.npmjs.org/@alliage/webserver-express/-/webserver-express-0.1.0-beta.0.tgz","fileCount":28,"integrity":"sha512-7O4+3z+NPHbgSq2To/BXZ1XnTLstzS3QHhVfCGk1P9DdBIM3vtcjp2APIFHS30oRXt7+Y02RwXFotrHqJN0xhw==","signatures":[{"sig":"MEQCIFKP5mmdVMtvBTzZm2eZ3FfkbzdTP++FCnA0G+ivEuGjAiAL80efZLvbTrWKFH5m2xfpaT7WVH/9XJM0i3xdz3QzhQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":55224},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.js","gitHead":"b31bc17873915029257fb5629eea2472120c6f91","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"borislebon","email":"bo.lebon@gmail.com"},"repository":{"url":"git+https://github.com/alliage-framework/web.git","type":"git"},"_npmVersion":"lerna/6.6.2/node@v18.16.0+x64 (linux)","description":"Express adapter module for Alliage Webserver","directories":{},"_nodeVersion":"18.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"alliageManifest":{"type":"module","dependencies":["@alliage/webserver"],"installationProcedures":{"copyFiles":[["base-files/config.yaml","config/webserver-express.yaml"]]}},"devDependencies":{"@alliage/webserver":"^0.1.0-beta.0"},"peerDependencies":{"express":"^4.18.2","@alliage/framework":"^1.0.0-beta.2","@alliage/webserver":"^0.1.0-beta.0"},"_npmOperationalInternal":{"tmp":"tmp/webserver-express_0.1.0-beta.0_1683908389073_0.5261327019438284","host":"s3://npm-registry-packages"}},"0.1.0-beta.1":{"name":"@alliage/webserver-express","version":"0.1.0-beta.1","author":{"name":"bo.lebon@gmail.com"},"license":"ISC","_id":"@alliage/webserver-express@0.1.0-beta.1","maintainers":[{"name":"borislebon","email":"bo.lebon@gmail.com"}],"homepage":"https://github.com/alliage-framework/web#readme","bugs":{"url":"https://github.com/alliage-framework/web/issues"},"dist":{"shasum":"097c6ec6ec43ce215d706b330184bf39c862eb89","tarball":"https://registry.npmjs.org/@alliage/webserver-express/-/webserver-express-0.1.0-beta.1.tgz","fileCount":27,"integrity":"sha512-HKYbkVKeNYN7CvNEXOeiH3gjAg7CllFmhkxwx72pM9gNNMbD5rBV1NpZlL9+lhb91qyp/B2IdDVcEDH42NLI9A==","signatures":[{"sig":"MEQCIBaExUnglOHTB4u+2esZEzdqQBCh5Rw3QHzPzrj3VN4bAiB46mM2F2DZtTE//NmWPqEodXmfowFl69aC4Iie/RyIHA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":60352},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.js","gitHead":"fa2b5c23766c2d6ed8bc7f628f26691407e43075","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"borislebon","email":"bo.lebon@gmail.com"},"repository":{"url":"git+https://github.com/alliage-framework/web.git","type":"git"},"_npmVersion":"10.8.2","description":"Express adapter module for Alliage Webserver","directories":{},"_nodeVersion":"20.19.2","dependencies":{"json-schema-to-ts":"^3.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"alliageManifest":{"type":"module","dependencies":["@alliage/webserver"],"installationProcedures":{"copyFiles":[["base-files/config.yaml","config/webserver-express.yaml"]]}},"devDependencies":{"@alliage/webserver":"0.1.0-beta.1"},"peerDependencies":{"express":"^5.1.0","@alliage/framework":"^1.0.0-beta.3","@alliage/webserver":"0.1.0-beta.1"},"_npmOperationalInternal":{"tmp":"tmp/webserver-express_0.1.0-beta.1_1748632346505_0.1626020654212328","host":"s3://npm-registry-packages-npm-production"}},"0.1.0-beta.2":{"name":"@alliage/webserver-express","version":"0.1.0-beta.2","description":"Express adapter module for Alliage Webserver","type":"module","publishConfig":{"access":"public"},"main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"repository":{"type":"git","url":"git+https://github.com/alliage-framework/web.git"},"author":{"name":"bo.lebon@gmail.com"},"license":"ISC","bugs":{"url":"https://github.com/alliage-framework/web/issues"},"homepage":"https://github.com/alliage-framework/web#readme","alliageManifest":{"type":"module","dependencies":["@alliage/webserver"],"installationProcedures":{"copyFiles":[["base-files/config.yaml","config/webserver-express.yaml"]]}},"peerDependencies":{"@alliage/framework":"^1.0.0-beta.3","@alliage/webserver":"0.1.0-beta.2","express":"^5.1.0"},"devDependencies":{"@alliage/webserver":"0.1.0-beta.2"},"dependencies":{"json-schema-to-ts":"^3.1.1"},"_id":"@alliage/webserver-express@0.1.0-beta.2","gitHead":"4696313051fed9f147bb2db23b19f720264cbe12","_nodeVersion":"20.19.5","_npmVersion":"10.8.2","dist":{"integrity":"sha512-asBR76BoJpArSAyr/gevyb8YLoLNGiY3PwtmUsd9lNphlBhtDiEyV39TuzX/Bf+orF+eIWDsRsF43TCvPdxHVw==","shasum":"bbc283ebd2ef8a4e8b0944581162db1211ef7ad2","tarball":"https://registry.npmjs.org/@alliage/webserver-express/-/webserver-express-0.1.0-beta.2.tgz","fileCount":27,"unpackedSize":60712,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGxwNgxjKvzTVh21YiShfgW3oF0zVaTMti9utIjLkvNGAiEAqT14M2+p2iMO0z6yxagZxI0ki59iDL3icXkyWR0Z834="}]},"_npmUser":{"name":"borislebon","email":"bo.lebon@gmail.com"},"directories":{},"maintainers":[{"name":"borislebon","email":"bo.lebon@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/webserver-express_0.1.0-beta.2_1758477480615_0.287758739033821"},"_hasShrinkwrap":false}},"time":{"created":"2023-05-12T16:19:49.017Z","modified":"2025-09-21T17:58:01.037Z","0.1.0-beta.0":"2023-05-12T16:19:49.248Z","0.1.0-beta.1":"2025-05-30T19:12:26.677Z","0.1.0-beta.2":"2025-09-21T17:58:00.838Z"},"bugs":{"url":"https://github.com/alliage-framework/web/issues"},"author":{"name":"bo.lebon@gmail.com"},"license":"ISC","homepage":"https://github.com/alliage-framework/web#readme","repository":{"type":"git","url":"git+https://github.com/alliage-framework/web.git"},"description":"Express adapter module for Alliage Webserver","maintainers":[{"name":"borislebon","email":"bo.lebon@gmail.com"}],"readme":"# Alliage Webserver Express\n\nExpress.js adapter for the Alliage Webserver module, providing full Express.js integration with the Alliage framework.\n\n## Dependencies\n\n- [@alliage/webserver](../webserver/) - Core webserver functionality\n- [express](https://expressjs.com/) - Express.js framework (peer dependency)\n\n## Installation\n\nFirst, install the Express adapter:\n\n```bash\nyarn add @alliage/webserver-express express\n```\n\nOr with npm:\n\n```bash\nnpm install @alliage/webserver-express express\n```\n\n## Registration\n\nIf you've already installed [@alliage/module-installer](https://github.com/alliage-framework/core/beta/main/packages/module-installer), simply run:\n\n```bash\nnpx alliage-scripts install @alliage/webserver-express\n```\n\nOtherwise, update your `alliage-modules.json` file:\n\n```json\n{\n  \"@alliage/webserver\": {\n    \"module\": \"@alliage/webserver\",\n    \"deps\": [\n      \"@alliage/config-loader\",\n      \"@alliage/module-installer\", \n      \"@alliage/process-manager\"\n    ],\n    \"envs\": []\n  },\n  \"@alliage/webserver-express\": {\n    \"module\": \"@alliage/webserver-express\",\n    \"deps\": [\"@alliage/webserver\"],\n    \"envs\": []\n  }\n}\n```\n\n## Configuration\n\nUpon installation, a `config/webserver-express.yaml` file will be created with default Express settings:\n\n```yaml\n# Express settings. See http://expressjs.com/en/api.html#app.settings.table\nsettings:\n  x-powered-by: false\n```\n\n### Express Settings\n\nThe `settings` object accepts any valid Express.js application settings. Common settings include:\n\n```yaml\nsettings:\n  # Security\n  x-powered-by: false           # Hide Express signature\n  \n  # Performance  \n  etag: strong                  # ETag generation (\"weak\", \"strong\", false)\n  \n  # Views\n  view engine: ejs             # Template engine\n  view cache: true             # Cache compiled views in production\n  views: ./views               # Views directory\n  \n  # Environment\n  env: production              # Environment mode\n  \n  # Trust proxy settings\n  trust proxy: true            # Trust proxy headers\n  \n  # JSON parsing\n  json escape: true            # Escape JSON responses\n  json replacer: null          # JSON.stringify replacer\n  json spaces: 0               # JSON formatting spaces\n  \n  # URL encoding\n  query parser: extended       # Query string parser (\"simple\", \"extended\", false)\n  \n  # Case sensitivity\n  case sensitive routing: false # Case-sensitive routing\n  strict routing: false        # Strict routing (trailing slashes)\n  \n  # Subdomain offset\n  subdomain offset: 2          # Number of dot-separated parts to remove for subdomain\n```\n\nSee the [Express documentation](http://expressjs.com/en/api.html#app.settings.table) for a complete list of available settings.\n\n## Basic Usage\n\nOnce registered, the Express adapter will automatically handle HTTP requests for your Alliage controllers:\n\n```typescript\nimport {\n  AbstractController,\n  AbstractRequest,\n  AbstractResponse,\n  Get,\n  Post\n} from '@alliage/webserver';\nimport { Service } from '@alliage/service-loader';\n\n@Service('api-controller')\nexport default class ApiController extends AbstractController {\n  @Get('/api/health')\n  async healthCheck(request: AbstractRequest, response: AbstractResponse) {\n    response.setBody({ status: 'ok', timestamp: Date.now() });\n  }\n\n  @Post('/api/users')\n  async createUser(request: AbstractRequest, response: AbstractResponse) {\n    const userData = request.getBody();\n    // Process with full Express request/response features\n    response.setStatus(201).setBody({ user: userData });\n  }\n}\n```\n\n## Using Express Native Middlewares\n\nThe Express adapter provides a utility function to integrate Express middlewares with Alliage Webserver's middleware system.\n\n### `createNativeMiddleware` Function\n\nThe `createNativeMiddleware` function is the core utility for wrapping Express middlewares to work within the Alliage framework. It creates an Alliage Webserver-compatible middleware from an Express middleware.\n\n#### Function Signature\n\n```typescript\nfunction createNativeMiddleware<T extends any[]>(\n  middleware: (...args: T) => ExpressMiddleware | ExpressMiddleware,\n  options?: NativeMiddlewareOptions<T>\n): AbstractMiddleware\n```\n\n#### Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `middleware` | `(...args: T) => ExpressMiddleware \\| ExpressMiddleware` | ✅ | The Express middleware function or constructor. Can be a direct middleware function (like `helmet()`) or a middleware constructor (like `rateLimit`) |\n| `options` | `NativeMiddlewareOptions<T>` | ❌ | Configuration options for the middleware wrapper |\n\n#### Options Interface\n\n```typescript\ninterface NativeMiddlewareOptions<T extends any[]> {\n  requestPhase?: REQUEST_PHASE;\n  applyBefore?: AbstractMiddleware[];\n  applyAfter?: AbstractMiddleware[];\n  args?: (...injectedDeps: any[]) => T;\n}\n```\n\n#### Options Properties\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `requestPhase` | `REQUEST_PHASE` | `REQUEST_PHASE.PRE_CONTROLLER` | Defines when in the request lifecycle the middleware should execute |\n| `applyBefore` | `AbstractMiddleware[]` | `[]` | Array of middleware instances that this middleware should run before |\n| `applyAfter` | `AbstractMiddleware[]` | `[]` | Array of middleware instances that this middleware should run after |\n| `args` | `(...injectedDeps: any[]) => T` | `undefined` | Function that receives injected dependencies and returns arguments to pass to the middleware constructor |\n\n#### Request Phases\n\nThe `REQUEST_PHASE` enum defines when the middleware executes:\n\n| Phase | Description |\n|-------|-------------|\n| `PRE_REQUEST` | Before any request processing begins |\n| `PRE_CONTROLLER` | After request processing but before controller execution |\n| `POST_CONTROLLER` | After controller execution but before response finalization |\n| `POST_REQUEST` | After response finalization |\n\n#### Return Value\n\nReturns an `AbstractMiddleware` instance that can be registered with the Alliage service loader and will be automatically integrated into the request processing pipeline.\n\n#### Usage Patterns\n\n**Direct Middleware Function:**\n```typescript\n// For middleware that's already configured\ncreateNativeMiddleware(helmet())\n```\n\n**Middleware Constructor with Arguments:**\n```typescript\n// For middleware that needs configuration\ncreateNativeMiddleware(rateLimit, {\n  args: () => [{ windowMs: 15 * 60 * 1000, max: 100 }]\n})\n```\n\n**Middleware with Dependency Injection:**\n```typescript\n// For middleware that needs injected dependencies\ncreateNativeMiddleware(cors, {\n  args: (config: CorsConfig) => [config]\n})\n```\n\n**Middleware with Ordering:**\n```typescript\n// For middleware that needs specific execution order\ncreateNativeMiddleware(compression(), {\n  applyAfter: [HelmetMiddleware]\n})\n```\n\n### Creating Native Middleware Wrappers\n\nUse the `createNativeMiddleware` function to wrap Express middlewares:\n\n```typescript\n// src/middlewares/CompressionMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { REQUEST_PHASE } from '@alliage/webserver';\nimport { Service } from '@alliage/service-loader';\nimport compression from 'compression';\nimport HelmetMiddleware from './HelmetMiddleware';\n\n// Simple middleware wrapper\nexport default Service('compression-middleware')(\n  createNativeMiddleware(compression())\n);\n```\n\n```typescript\n// src/middlewares/CorsMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { REQUEST_PHASE } from '@alliage/webserver';\nimport { Service } from '@alliage/service-loader';\nimport cors from 'cors';\n\n// Middleware with configuration\nexport default Service('cors-middleware')(\n  createNativeMiddleware(cors(), {\n    requestPhase: REQUEST_PHASE.PRE_CONTROLLER\n  })\n);\n```\n\n```typescript\n// src/middlewares/RateLimitMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { REQUEST_PHASE } from '@alliage/webserver';\nimport { Service } from '@alliage/service-loader';\nimport rateLimit from 'express-rate-limit';\n\n// Middleware with constructor arguments\nexport default Service('rate-limit-middleware')(\n  createNativeMiddleware(rateLimit, {\n    requestPhase: REQUEST_PHASE.PRE_CONTROLLER,\n    args: () => [{\n      windowMs: 15 * 60 * 1000, // 15 minutes\n      max: 100, // limit each IP to 100 requests per windowMs\n      message: 'Too many requests from this IP'\n    }]\n  })\n);\n```\n\n### Dependency Injection with Middlewares\n\nYou can inject dependencies into middleware configuration using constructor parameters:\n\n```typescript\n// src/middlewares/ConfigurableRateLimitMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { REQUEST_PHASE } from '@alliage/webserver';\nimport { Service, parameter } from '@alliage/service-loader';\nimport rateLimit from 'express-rate-limit';\n\n// Middleware that receives configuration via dependency injection\nexport default Service('rate-limit-middleware', [\n  parameter('rate-limit-config') // Inject configuration\n])(\n  createNativeMiddleware(rateLimit, {\n    requestPhase: REQUEST_PHASE.PRE_CONTROLLER,\n    args: (config: { windowMs: number; max: number; message: string }) => [{\n      windowMs: config.windowMs,\n      max: config.max,\n      message: config.message\n    }]\n  })\n);\n```\n\n```typescript\n// src/middlewares/SessionMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { REQUEST_PHASE } from '@alliage/webserver';\nimport { Service, parameter } from '@alliage/service-loader';\nimport session from 'express-session';\nimport HelmetMiddleware from './HelmetMiddleware';\n\nexport default Service('session-middleware', [\n  parameter('session-secret')\n])(\n  createNativeMiddleware(session, {\n    requestPhase: REQUEST_PHASE.PRE_CONTROLLER,\n    applyAfter: [HelmetMiddleware],\n    args: (secretKey: string) => [{\n      secret: secretKey,\n      resave: false,\n      saveUninitialized: false,\n      cookie: { secure: false, maxAge: 3600000 }\n    }]\n  })\n);\n```\n\n### Advanced Native Middleware Integration\n\nFor complex scenarios, you can specify ordering and error handling:\n\n```typescript\n// src/middlewares/HelmetMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { REQUEST_PHASE } from '@alliage/webserver';\nimport { Service } from '@alliage/service-loader';\nimport helmet from 'helmet';\n\nexport default Service('helmet-middleware')(\n  createNativeMiddleware(helmet(), {\n    requestPhase: REQUEST_PHASE.PRE_CONTROLLER,\n  })\n);\n```\n\n## Express-Specific Features\n\n### Accessing Express Request/Response\n\nWithin controllers and middlewares, you can access the native Express request and response objects:\n\n```typescript\nimport { AbstractController, AbstractRequest, AbstractResponse, Get } from '@alliage/webserver';\nimport { Service } from '@alliage/service-loader';\nimport { Request as ExpressRequest, Response as ExpressResponse } from 'express';\n\n@Service('express-controller')\nexport default class ExpressController extends AbstractController {\n  @Get('/express-features')\n  async useExpressFeatures(request: AbstractRequest, response: AbstractResponse) {\n    // Access native Express objects\n    const expressReq = request.getNativeRequest<ExpressRequest>();\n    const expressRes = response.getNativeResponse<ExpressResponse>();\n    \n    // Use Express-specific features\n    const userAgent = expressReq.get('User-Agent');\n    const acceptsHtml = expressReq.accepts('html');\n    \n    // Express response methods\n    expressRes.cookie('lastVisit', Date.now());\n    \n    response.setBody({\n      userAgent,\n      acceptsHtml,\n      path: expressReq.path,\n      query: expressReq.query\n    });\n  }\n}\n```\n\n### Template Rendering\n\nIf you've configured a view engine, you can render templates:\n\n```typescript\nimport { AbstractController, AbstractRequest, AbstractResponse, Get } from '@alliage/webserver';\nimport { Service } from '@alliage/service-loader';\n\n@Service('template-controller')\nexport default class TemplateController extends AbstractController {\n  @Get('/dashboard')\n  async dashboard(request: AbstractRequest, response: AbstractResponse) {\n    const expressRes = response.getNativeResponse();\n    \n    // Render template with Express\n    expressRes.render('dashboard', {\n      title: 'Dashboard',\n      user: request.getExtraPayload('user')\n    });\n  }\n}\n```\n\n### File Downloads\n\n```typescript\nimport { AbstractController, AbstractRequest, AbstractResponse, Get } from '@alliage/webserver';\nimport { Service } from '@alliage/service-loader';\nimport path from 'path';\n\n@Service('download-controller')\nexport default class DownloadController extends AbstractController {\n  @Get('/download/:filename')\n  async downloadFile(request: AbstractRequest, response: AbstractResponse) {\n    const { filename } = request.getParams();\n    const expressRes = response.getNativeResponse();\n    \n    const filePath = path.join(process.cwd(), 'files', filename);\n    \n    // Express file download\n    expressRes.download(filePath, (err) => {\n      if (err) {\n        response.setStatus(404).setBody({ error: 'File not found' });\n      }\n    });\n  }\n}\n```\n\n## Performance Considerations\n\n### Production Settings\n\nFor production environments, configure Express with optimized settings:\n\n```yaml\n# config/webserver-express.yaml\nsettings:\n  # Disable X-Powered-By header\n  x-powered-by: false\n  \n  # Enable view caching\n  view cache: true\n  \n  # Optimize JSON\n  json escape: true\n  json spaces: 0\n  \n  # Trust reverse proxy\n  trust proxy: true\n  \n  # Set environment\n  env: production\n```\n\n### Middleware Ordering\n\nOrder middlewares for optimal performance:\n\n1. **Security middlewares** (helmet, cors) - First\n2. **Compression** - Early, before large responses\n3. **Logging** - Early, to capture all requests\n4. **Rate limiting** - Before expensive operations\n5. **Authentication** - Before protected routes\n6. **Body parsing** - Before controllers that need body data\n7. **Static files** - Last, as fallback\n\n```typescript\n// Example ordering with applyBefore/applyAfter\n// src/middlewares/HelmetMiddleware.ts\nexport default Service('helmet-middleware')(\n  createNativeMiddleware(helmet())\n);\n\n// src/middlewares/CompressionMiddleware.ts\nimport HelmetMiddleware from './HelmetMiddleware';\n\nexport default Service('compression-middleware')(\n  createNativeMiddleware(compression(), {\n    applyAfter: [HelmetMiddleware]\n  })\n);\n\n// src/middlewares/LoggingMiddleware.ts  \nimport CompressionMiddleware from './CompressionMiddleware';\n\nexport default Service('logging-middleware')(\n  createNativeMiddleware(morgan('combined'), {\n    applyAfter: [CompressionMiddleware]\n  })\n);\n```\n\n## Running the Server\n\nStart your application with the Express adapter:\n\n```bash\n# Development\nnpx alliage-scripts start web\n\n# Production with PM2\npm2 start \"npx alliage-scripts start web\" --name \"my-app\"\n\n# With custom port\nnpx alliage-scripts start web --port 3000\n```\n\n## Complete Example\n\nHere's a complete example showing Express adapter usage with various third-party middlewares and dependency injection:\n\n```typescript\n// src/controllers/ApiController.ts\nimport {\n  AbstractController,\n  AbstractRequest,\n  AbstractResponse,\n  Get,\n  Post\n} from '@alliage/webserver';\nimport { Service, instanceOf } from '@alliage/service-loader';\nimport { UserService } from '../services/UserService';\n\n@Service('api-controller', [instanceOf(UserService)])\nexport default class ApiController extends AbstractController {\n  constructor(private userService: UserService) {\n    super();\n  }\n\n  @Get('/api/users')\n  async getUsers(request: AbstractRequest, response: AbstractResponse) {\n    const users = await this.userService.findAll();\n    response.setBody({ users });\n  }\n\n  @Post('/api/users')\n  async createUser(request: AbstractRequest, response: AbstractResponse) {\n    const userData = request.getBody();\n    const user = await this.userService.create(userData);\n    response.setStatus(201).setBody({ user });\n  }\n}\n\n// src/middlewares/SecurityMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { Service } from '@alliage/service-loader';\nimport helmet from 'helmet';\n\nexport default Service('helmet-middleware')(\n  createNativeMiddleware(helmet())\n);\n\n// src/middlewares/CorsMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { Service, parameter } from '@alliage/service-loader';\nimport cors from 'cors';\nimport SecurityMiddleware from './SecurityMiddleware';\n\nexport default Service('cors-middleware', [\n  parameter('cors-config')\n])(\n  createNativeMiddleware(cors, {\n    applyAfter: [SecurityMiddleware],\n    args: (config: { origin: string[]; credentials: boolean }) => [config]\n  })\n);\n\n// src/middlewares/CompressionMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { Service } from '@alliage/service-loader';\nimport compression from 'compression';\nimport CorsMiddleware from './CorsMiddleware';\n\nexport default Service('compression-middleware')(\n  createNativeMiddleware(compression(), {\n    applyAfter: [CorsMiddleware]\n  })\n);\n\n// src/middlewares/JsonParserMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { Service } from '@alliage/service-loader';\nimport bodyParser from 'body-parser';\n\nexport default Service('json-parser-middleware')(\n  createNativeMiddleware(bodyParser.json, {\n    args: () => [{ strict: true, limit: '10mb' }]\n  })\n);\n\n// src/middlewares/UrlEncodedMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { Service } from '@alliage/service-loader';\nimport express from 'express';\n\nexport default Service('url-encoded-middleware')(\n  createNativeMiddleware(express.urlencoded, {\n    args: () => [{ extended: true, limit: '10mb' }]\n  })\n);\n\n// src/middlewares/ConfigurableJsonParserMiddleware.ts\nimport { createNativeMiddleware } from '@alliage/webserver-express';\nimport { Service, parameter } from '@alliage/service-loader';\nimport bodyParser from 'body-parser';\n\n// With dependency injection for configuration\nexport default Service('json-parser-middleware', [\n  parameter('body-parser-config')\n])(\n  createNativeMiddleware(bodyParser.json, {\n    args: (config: { strict: boolean; limit: string }) => [config]\n  })\n);\n```\n\n### Configuration Files\n\nYou'll also need to configure the dependency injection parameters:\n\n```yaml\n# config/cors.yaml\norigin:\n  - \"http://localhost:3000\"\n  - \"https://yourdomain.com\"\ncredentials: true\n\n# config/body-parser.yaml\nstrict: true\nlimit: \"10mb\"\n```\n\nAnd register them in your module:\n\n```typescript\n// src/YourModule.ts\nimport { AbstractModule } from '@alliage/framework';\nimport { CONFIG_EVENTS, loadConfig, validators } from '@alliage/config-loader';\n\nexport default class YourModule extends AbstractModule {\n  getEventHandlers() {\n    return {\n      [CONFIG_EVENTS.LOAD]: [\n        loadConfig('cors-config', validators.jsonSchema({\n          type: 'object',\n          properties: {\n            origin: { type: 'array', items: { type: 'string' } },\n            credentials: { type: 'boolean' }\n          },\n          required: ['origin', 'credentials']\n        })),\n        loadConfig('body-parser-config', validators.jsonSchema({\n          type: 'object',\n          properties: {\n            strict: { type: 'boolean' },\n            limit: { type: 'string' }\n          },\n          required: ['strict', 'limit']\n        }))\n      ]\n    };\n  }\n}\n```\n\nThis Express adapter provides full compatibility with the Express.js ecosystem while maintaining the benefits of Alliage Webserver's module system and dependency injection.","readmeFilename":"README.md"}