routing-controllers Documentation

Create structured, declarative and beautifully organized class-based controllers with heavy decorators usage in Express / Koa using TypeScript and Routing...

RAW Doc

File: CHANGELOG.md

Changelog and release notes

[0.11.3](https://github.com/typestack/routing-controllers/compare/v0.11.2...v0.11.3) (2025-09-05)

Changed

  • update dependencies to fix security vulnerabilities
  • update various dev-dependencies

[0.11.2](https://github.com/typestack/routing-controllers/compare/v0.11.1...v0.11.2) (2025-03-04)

Changed

  • Reverted CurrentUserChecker generic

[0.11.1](https://github.com/typestack/routing-controllers/compare/v0.11.0...v0.11.1) (2025-02-18)

Changed

  • Fixed Render decorator for Koa

[0.11.0](https://github.com/typestack/routing-controllers/compare/v0.10.4...v0.11.0) (2025-02-14)

Changed

  • cookie package updated to 1.0.2 from 0.5.0
  • glob package updated to 11.0.0 from 10.2.2
  • reflect-metadata package updated to 0.2.2 from 0.1.13
  • Introduced UnprocessableEntityError
  • Dropped support for node versions below 20

[0.10.4](https://github.com/typestack/routing-controllers/compare/v0.10.3...v0.10.4) (2023-04-17)

Changed

  • glob package updated to 10.1.0 from 10.2.2

Fixed

  • Fixed koa trailing slash handling
  • Fixed controller method inheritance

[0.10.3](https://github.com/typestack/routing-controllers/compare/v0.10.2...v0.10.3) (2023-04-17)

Changed

  • glob package updated to 10.1.0 from 8.1.0
  • koa package updated to 2.14.2 from 2.14.1
  • koa-bodyparse package updated to 4.4.0 from 4.3.0
  • updated various dev dependencies

Fixed

  • Fixed koa uploaded file accessor

[0.10.2](https://github.com/typestack/routing-controllers/compare/v0.10.1...v0.10.2) (2023-03-06)

Changed

  • glob package updated to 8.1.0 from 8.0.3
  • body-parser package updated to 1.20.2 from 1.20.1
  • multer package updated to 1.4.5-lts.1 from 1.4.4
    • Note: This fixes vulnerability CVE-2022-24434
  • updated various dev dependencies

Fixed

  • Added normalization to glob pattern resolver to fix Windows paths

[0.10.1](https://github.com/typestack/routing-controllers/compare/v0.10.0...v0.10.1) (2023-01-13)

Changed

  • class-validator package updated to 0.14.0 from 0.13.2
    • Note: class-validator 0.14.0 enables forbidUnknownValues by default, but this is overridden in routing-controllers to prevent a breaking change. You can still enable it like before.
  • koa package updated to 2.14.1 from 2.13.4
  • updated various dev dependencies

[0.10.0](https://github.com/typestack/routing-controllers/compare/v0.9.0...v0.10.0) (2022-12-9)

Added

  • isArray option for @QueryParam

Changed

  • class-transformer package updated to 0.5.1 from 0.3.1
  • class-validator package updated to 0.13.2 from 0.12.2
  • cookie package updated to 0.5.0 from 0.4.0
  • glob package updated to 8.0.3 from 7.1.4
  • express package updated to 4.18.2 from 4.17.1 and moved to optionalDependencies
  • express-session package updated to 1.17.1 from 1.17.3 and moved to optionalDependencies
  • body-parser package updated to 1.20.1 from 1.19.0
  • multer package updated to 1.4.4 from 1.4.2
  • koa package updated to 2.13.4 from 2.8.2
  • koa-multer package replaced with @koa/multer
  • koa-router package replaced with @koa/router
  • updated various dev dependencies

Fixed

  • Fixed parsing uuid as route parameter
  • Fixed target property not set during controller inheritance
  • Fixed NaN check for number route parameters
  • Added missing null value handling in parameters
  • Fixed middlewares not using the defined route prefix

0.9.0

Features

  • Add support for wildcard "all" routes (ref [#536])
  • Controller inheritance - Added missing tests, code samples, and updated documentation (ref [#578][#301])
  • Added a useResponseClassTransformer global option (ref [#329])
  • Through [#329], it should now be possible to use classTransformer only for input (ref [#179])
  • Added support for controller inheritance (ref [#147])
  • Update all dependencies and changed it to use npm auto-update patches and minor versions (ex.: "class-validator": "^0.12.2", instead of "class-validator": "0.12.2" (ref [#550])
  • Updated project tooling (ref [##618])

Fixes

  • Input-validation bypass vulnerability (ref [#518])
  • Fixed issue that would cause multiple route executions per request (ref [#568])
  • Fixed export of SessionParam at index (ref [#526])
  • Through [#536], it should now prevent conflicts in routes names (ref [#547])
  • Through [#568], it should now prevent a single request triggering multiple route executions that would cause Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client issue. (ref [#491])
  • Fixed order of global interceptors (ref [#543])
  • Fixed incorrect handling of rejected promises from Middleware.use() (ref [#438])
  • Through [#329], it should fix performance issue with big json result (ref [#226])
  • Through [#329], it should fix problem with mongoose model serialization (ref [#149])
  • Local ValidationOptions are not overwriting global defaults (ref [#618])

Documentation

  • Added TypeDI service decorator to example in README (ref [#643])
  • Translate document to Chinese (ref [#574])
  • Fix typo in README (ref [#571])
  • Add another example for using the response directly (ref [#546])

0.8.0 [BREAKING CHANGES]

Features

  • extract generic @Session() deocorator into @SessionParam() and @Session() (ref [#335][#348][#407])
  • restore/introduce @QueryParams() and @Params() missing decorators options (ref [#289][#289])
  • normalize param object properties (for "queries", "headers", "params" and "cookies"), with this change you can easily validate query/path params using class-validator (ref [#289][#289])
  • improved params normalization, converting to primitive types is now more strict and can throw ParamNormalizationError (e.g. when number is expected but an invalid string (NaN) has been received) (ref [#289][#289])

0.7.7

Features

  • feat(ErrorHandling): add support for custom toJSON method in errors (ref #325)

Fixes

  • fixed inconsistent roles parameter in authorizationChecker (ref #308)

0.7.6

Fixes

  • fixed bugs with undefined result code behaviour

0.7.5

Fixes

  • fixed bugs with undefined result code behaviour

0.7.4

Fixes

  • fixed bugs with undefined result code behaviour

0.7.3

Features

  • Support for returning Buffer and streams from action handler (controller's method) (ref #285)
  • Custom driver support (ref #276)

Fixes

  • Directly calling response bug (ref #286)
  • Missing parameter in @BodyParam error message (ref #284)
  • Sync and async auth checker bug (ref (ref #283)
  • Handling different content-type responses in JsonController (ref #277)

0.7.2

Fixes

  • Using @Authorization decorator with Koa caused 404 responses (ref #240)
  • Allow throwing custom errors in authorizationChecker (ref #233)
  • check auth permissions before accepting files for upload (ref #251)

0.7.0 [BREAKING CHANGES]

  • some routing-controllers options has been changed and renamed
  • returned validation error value signature has changed
  • controllers and middlewares now can be specified in routing-controllers options
  • MiddlewareInterface was removed and instead ExpressMiddlewareInterface or KoaMiddlewareInterface should be used
  • ErrorMiddlewareInterface was renamed to ExpressErrorMiddlewareInterface
  • per-controller and per-action middlewares used in @UseBefore and @UseAfter now should not be marked with @Middleware decorator
  • @MiddlewareGlobalBefore() and @MiddlewareGlobalAfter() were removed and instead new signatures should be used: @Middleware({ type: "before" }) and @Middleware({ type: "after" })
  • named some decorator parameter names
  • added few new decorators to get all parameters like @QueryParams, @Params, @HeaderParams etc.
  • added @Authorized and @CurrentUser decorators
  • added new @Ctx decorator to use context with koa
  • @NullResultCode has been renamed to @OnNull, now supports error classes
  • @UndefinedResultCode has been renamed to @OnUndefined, now supports error classes
  • @EmptyResultCode has been removed. Use @OnUndefined decorator instead and return concrete types in your controllers.
  • added ability to create custom decorators
  • enabled validation by default
  • multiple bug fixes
  • codebase refactoring
  • removed JsonResponse and TextResponse decorators

0.6.10

Features

  • added integration with class-transform-validator for deserialization and auto validation request parameters

0.6.2

Features

  • made interceptors to support promises

0.6.1

Features

  • added interceptors support

0.6.0 [BREAKING CHANGES]

Features

  • middleware and error handlers support
  • everything packed into "routing-controllers" main export
  • added few more new decorators

Fixes

  • fixed multiple issues with param decorators
  • fixed multiple bugs
  • refactored core

Removals

  • removed parseJson from @Body decorator
  • removed ActionOptions
  • removed responseType from action options and added @JsonResponse and @TextResponse decorators

0.5.0

  • renamed package from controllers.ts to routing-controllers
  • added integration with constructor-utils for serialization and deserialization

File: codecov.yml

coverage:
range: 70..100
round: down
precision: 2
status:
default:
threshold: 3
comment: off
ignore:

  • testing/**/*.ts
  • src/**/*.interface.ts

File: package.json

{
"name": "routing-controllers",
"private": false,
"version": "0.11.3",
"description": "Create structured, declarative and beautifully organized class-based controllers with heavy decorators usage for Express / Koa using TypeScript.",
"author": "TypeStack contributors",
"license": "MIT",
"sideEffects": false,
"main": "./cjs/index.js",
"module": "./esm2015/index.js",
"es2015": "./esm2015/index.js",
"typings": "./types/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/typestack/routing-controllers.git"
},
"tags": [
"express",
"express.js",
"typescript",
"typescript-express",
"typescript-express.js",
"express-controllers",
"controllers"
],
"scripts": {
"build": "npm run build:cjs",
"build:clean": "rimraf build",
"build:es2015": "tsc --project tsconfig.prod.esm2015.json",
"build:cjs": "tsc --project tsconfig.prod.cjs.json",
"build:types": "tsc --project tsconfig.prod.types.json",
"prettier:fix": "prettier --write "/*.{ts,md}"",
"prettier:check": "prettier --check "
/.{ts,md}"",
"lint:fix": "eslint --max-warnings 0 --fix src/**/
.ts",
"lint:check": "eslint --max-warnings 0 src/**/*.ts",
"test": "jest --verbose --runInBand",
"test:watch": "jest --watch",
"test:ci": "jest --runInBand --no-cache --coverage --verbose",
"test:debug": "NODE_ENV= node --inspect=0.0.0.0:20001 ./node_modules/.bin/jest --colors --runInBand --no-coverage --watch"
},
"dependencies": {
"cookie": "^1.0.2",
"glob": "^11.1.0",
"reflect-metadata": "^0.2.2",
"template-url": "^1.0.0"
},
"peerDependencies": {
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1"
},
"devDependencies": {
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.31.0",
"@koa/cors": "^5.0.0",
"@koa/ejs": "^5.1.0",
"@types/express": "^5.0.0",
"@types/express-session": "^1.18.2",
"@types/jest": "^29.5.14",
"@types/koa": "^2.15.0",
"@types/koa__ejs": "^5.1.0",
"@types/multer": "^2.0.0",
"@types/node": "^16.18.3",
"@types/serve-static": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^8.25.0",
"@typescript-eslint/parser": "^8.38.0",
"axios": "^1.8.2",
"body-parser": "^1.20.4",
"chakram": "^1.5.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"cors": "^2.8.5",
"eslint": "^9.10.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jest": "^28.11.1",
"form-data": "^4.0.4",
"handlebars": "^4.7.8",
"http-status-codes": "^2.3.0",
"husky": "^9.1.7",
"jest": "^29.7.0",
"koa-convert": "^2.0.0",
"koa-session": "^6.4.0",
"lint-staged": "^16.1.4",
"multer": "^2.0.2",
"mustache-express": "^1.3.2",
"prettier": "^3.6.2",
"rimraf": "^6.0.1",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"ts-node-dev": "^2.0.0",
"typedi": "^0.10.0",
"typescript": "^5.7.2"
},
"optionalDependencies": {
"@koa/multer": "^3.0.2",
"@koa/router": "^13.1.1",
"body-parser": "^1.20.4",
"express": "^4.22.1",
"express-session": "^1.18.2",
"koa": "^3.0.3",
"koa-bodyparser": "^4.4.1",
"multer": "^2.0.2"
}
}


File: tsconfig.json

{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"target": "es2018",
"lib": ["es2018"],
"outDir": "build/node",
"rootDir": "./src",
"strict": true,
"sourceMap": true,
"inlineSources": true,
"removeComments": false,
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"forceConsistentCasingInFileNames": true
},
"exclude": ["build", "node_modules", "sample", "/*.spec.ts", "test/"]
}


File: tsconfig.prod.cjs.json

{
"extends": "./tsconfig.prod.json",
"compilerOptions": {
"module": "CommonJS",
"outDir": "build/cjs"
},
}


File: tsconfig.prod.esm2015.json

{
"extends": "./tsconfig.prod.json",
"compilerOptions": {
"module": "ES2015",
"outDir": "build/esm2015",
},
}


File: tsconfig.prod.json

{
"extends": "./tsconfig.json",
"compilerOptions": {
"strict": false,
"declaration": false,
},
}


File: tsconfig.prod.types.json

{
"extends": "./tsconfig.prod.json",
"compilerOptions": {
"declaration": true,
"emitDeclarationOnly": true,
"outDir": "build/types",
},
}


File: tsconfig.spec.json

{
"extends": "./tsconfig.json",
"compilerOptions": {
"strict": false,
"strictPropertyInitialization": false,
"sourceMap": true,
"removeComments": true,
"noImplicitAny": false,
"allowSyntheticDefaultImports": true,
},
"exclude": ["node_modules"]
}


File: .prettierrc.yml

printWidth: 120
tabWidth: 2
useTabs: false
semi: true
singleQuote: true
trailingComma: es5
bracketSpacing: true
arrowParens: avoid


File: test/resources/sample-text-file.txt

Hello World!


File: .github/dependabot.yml

version: 2
updates:

  • package-ecosystem: npm
    directory: "/"
    schedule:
    interval: daily
    time: "10:00"
    timezone: Europe/Budapest
    open-pull-requests-limit: 5
    versioning-strategy: increase
    commit-message:
    prefix: build
    include: scope

File: .github/semantic.yml

titleAndCommits: true
allowMergeCommits: false
scopes:

  • deps
  • deps-dev
    types:
  • feat
  • fix
  • docs
  • style
  • refactor
  • perf
  • test
  • build
  • ci
  • chore
  • revert
  • merge

File: .github/workflows/auto-approve-dependabot-workflow.yml

name: Dependabot auto-merge
on:
pull_request_target
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: 'Auto approve PR by Dependabot'
uses: hmarr/[email protected]
with:
github-token: "${{ secrets.TYPESTACK_BOT_TOKEN }}"
- name: 'Comment merge command'
uses: actions/github-script@v3
with:
github-token: ${{secrets.TYPESTACK_BOT_TOKEN }}
script: |
await github.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: '@dependabot squash and merge'
})


File: .github/workflows/continuous-deployment-workflow.yml

name: CD
on:
release:
types: [created]
jobs:
publish:
name: Publish to NPM
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 'lts/*'
registry-url: https://registry.npmjs.org
- run: npm ci --ignore-scripts
- run: npm run prettier:check
- run: npm run lint:check
- run: npm run test:ci
- run: npm run build:es2015
- run: npm run build:cjs
- run: npm run build:types
- run: cp LICENSE build/LICENSE
- run: cp README.md build/README.md
- run: jq 'del(.devDependencies) | del(.scripts)' package.json > build/package.json
- run: npm publish ./build
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}


File: .github/workflows/continuous-integration-workflow.yml

name: CI
on: [push, pull_request]
jobs:
checks:
name: Linters
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 'lts/'
- run: npm ci --ignore-scripts
- run: npm run prettier:check
- run: npm run lint:check
tests:
name: Tests
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['lts/
', 'current']
fail-fast: false
steps:
- uses: actions/checkout@v3
- name: Setting up Node.js (v${{ matrix.node-version }}.x)
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci --ignore-scripts
- run: npm run test:ci
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
if: ${{ matrix.node-version == 'current' }}
with:
file: ./coverage/clover.xml
token: ${{ secrets.CODECOV_TOKEN }}
commit: ${{ github.sha }}
branch: ${{ github.ref }}
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 'lts/*'
- run: npm ci --ignore-scripts
- run: npm run build:es2015
- run: npm run build:cjs
- run: npm run build:types


File: .github/workflows/lock-closed-issues-workflow.yml

name: 'Lock inactive threads'
on:
schedule:
- cron: '0 0 * * *'
jobs:
lock:
name: Lock closed issues
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v2
with:
github-token: ${{ github.token }}
issue-lock-inactive-days: 30
pr-lock-inactive-days: 30
issue-lock-comment: >
This issue has been automatically locked since there
has not been any recent activity after it was closed.
Please open a new issue for related bugs.
pr-lock-comment: >
This pull request has been automatically locked since there
has not been any recent activity after it was closed.
Please open a new issue for related bugs.