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!
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.tssind 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
/docsdie 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:
noImplicitAdditionalPropertiesdefiniert, wie sich die Schnittstelle verhalten soll, wenn unerwartete Informationen übermittelt werden. Ich bevorzuge eine frühzeitige Fehlermeldung und konfigurierethrow-on-extras.controllerPathGlobsdefiniert 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.specdefiniert, wohin die Open-API-konforme Schnittstellendokumentation gespeichert wird und mit welcher Version sie kompatibel ist.routeslegt 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.compilerOptionserlauben 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
}
}