Node.js mit TSOA

In Vorbereitung auf den vierten Node.js-Testtipps-Artikel über erweiterte Schnittstellentests will ich zuerst die notwendigen Grundlagen schaffen: Ich zeige, wie TSOA eingerichtet und mit Express verknüpft wird. Die dazugehörige Konfiguration gemäß meinen Best Practices findest du im Artikel. Legen wir los!

4 Minuten

In diesem Artikel erkläre ich, wie TSOA in Node.js eingerichtet wird. Mit Hilfe dieses Pakets erzeugen wir zum einen die swagger.json und zum anderen die Routendefinition.

  • In der autogenerierten Routendefinition routes.ts sind alle Details enthalten, die Express für die Schnittstellendefinition benötigt. Wir müssen uns nicht mehr manuell um das Einbinden einzelner Routen kümmern → eine kleine Automatisierung, die Fehler vorsorglich verhindert.
  • Die JSON-Datei ist eine Open-API-Version-3-konforme Schnittstellendefinition, die wir nutzen können, um z.B. unter der Route /docs die Dokumentation abzulegen. Das ist besonders interessant, wenn wir im Rahmen eines SaaS-Dienstes anderen Entwicklern die Arbeit mit unserem Produkt erleichtern wollen. Gleichzeitig ist die Dokumentation im eigenen Team wertvoll: Die Frontend- und App-Entwickelnden können damit auch arbeiten, ohne in den Backend-Code zu schauen.

TSOA Installation

Nachdem verstanden ist, wofür wir das Ganze benötigen, starten wir mit der Installation des notwendigen NPM-Pakets:

npm install tsoa

Als Nächstes empfehle ich dir, in der package.json im Bereich scripts Anpassungen vorzunehmen. Einerseits einen Befehl zum manuellen Anstoßen der Erzeugung der Routendefinition und der JSON-Datei. Den führen wir aus, wenn wir im Code an den Routen etwas ändern, um es für die lokale Entwicklung bereitzustellen. Andererseits die Erzeugung als Schritt vor dem Start des Builds. Damit gewährleisten wir, dass in der Build-Pipeline stets die aktuelle Routendefinition verwendet wird.

{
  "scripts": {
    "build": "rimraf ./dist && npm run tsoa:gen && pkgroll",
    "tsoa:gen": "tsoa spec-and-routes"
  }
}

TSOA Konfiguration

Damit TSOA weiß, was es tun soll, konfigurieren wir die entsprechende Einstellung in der Datei tsoa.json. Dabei empfehle ich dir Folgendes:

  • noImplicitAdditionalProperties definiert, wie sich die Schnittstelle verhalten soll, wenn unerwartete Informationen übermittelt werden. Ich bevorzuge eine frühzeitige Fehlermeldung und konfiguriere throw-on-extras.
  • controllerPathGlobs definiert die TypeScript-Dateien, die TSOA nach der Routendefinition durchsucht, um daraus die automatische Definition zu erstellen. Für mich hat sich das Namensschema mit der Endung „Controller“ bewährt.
  • spec definiert, wohin die Open-API-konforme Schnittstellendokumentation gespeichert wird und mit welcher Version sie kompatibel ist.
  • routes legt fest, wo die automatisch generierte Routendefinition gespeichert wird, sodass wir sie von dort aus in Express einbinden können. Wenn wir die Authentifizierung mit TSOA abbilden wollen, können wir dafür ein passendes Modul einbinden. Hierauf gehe ich in einem späteren Artikel ein.
  • compilerOptions erlauben die Definition von Pfaden, wie ich sie für die absoluten Importe in der TsConfig nutze. Die gleiche Definition ist hier einzutragen.

Meine Konfiguration definiert sich wie folgt:

{  
  "entryFile": "src/index.ts",  
  "noImplicitAdditionalProperties": "throw-on-extras",  
  "controllerPathGlobs": [  
    "src/**/*Controller.ts"  
  ],  
  "spec": {  
    "outputDirectory": "dist",  
    "specVersion": 3  
  },  
  "routes": {  
    "routesDir": "src",  
    "authenticationModule": "./src/services/AuthMiddleware.ts"  
  },  
  "compilerOptions": {  
    "baseUrl": ".",  
    "paths": {  
      "@/*": [  
        "src/*"  
      ]  
    }  
  }  
}

TSOA in Express einbinden

Für die Einbindung in Express bietet uns TSOA einen praktischen Export an. Dafür benötigt es lediglich folgende Zeilen.

import { RegisterRoutes } from '@/routes'

// ...
const app = express()
RegisterRoutes(app)
// ....

Routen mit TSOA entwickeln

In der TSOA-Konfiguration haben wir festgelegt, dass wir Controller-Dateien erstellen. Ich habe es mir angewöhnt, für einen Endpunkt einen passend benannten Ordner mit der dazugehörigen Controller-Datei zu erstellen. Für den Endpunkt /users gibt es /src/users mit der Datei UserController.ts. Die Struktur des Controllers ist folgende:

import { Controller } from '@tsoa/runtime'  
import { Get, Request, Route } from 'tsoa'
import UserRepository from '@/users/UserRepository'

type UserGetResponse = {
   firstName: string  
   lastName: string
}

Route('users')
export class UserController extends Controller {  
  @Get()
  public async getAll(@Request() req: Request): Promise<UserGetResponse[]> {
      return UserRepository.getAll()
  }

  // ... other routes
}

Beispielhafte /src/users/UserController.ts-Datei

Fazit

TSOA ist erfolgreich eingerichtet. Die Routen- und Open-API-Definitionen werden erzeugt. Damit ist alles vorbereitet, um wichtige Features von TSOA einzubinden:

  • Validierung des Request-Bodys
  • Definition von Header-Daten
  • Authentifizierung mit Rollen

Mit diesen Punkten fahre ich im nächsten Artikel fort. Bis dahin viel Spaß beim Verfeinern deiner Express-App.


Update 13.12.2025 11:30 Uhr
Um TSOA zum Laufen zu bekommen, muss noch eine Konfiguration in der tsconfig.js vorgenommen werden, die ich nicht erwähnt habe:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true // is not required unless you use custom middleware 
  }
}
call to action background image

Abonniere meinen Newsletter

Erhalte einmal im Monat Nachrichten aus den Bereichen Softwareentwicklung und Kommunikation gespikt mit Buch- und Linkempfehlungen.