Kolumne: Per Anhalter durch den JavaScript-Dschungel

tsoa: API-Dokumentation für Node.js

tsoa: API-Dokumentation für Node.js

Kolumne: Per Anhalter durch den JavaScript-Dschungel

tsoa: API-Dokumentation für Node.js


JavaScript ist ja bekanntlich eher der Wilde Westen der Webentwicklung. Doch trotz der Abwesenheit von Recht und Gesetz gibt es ein paar Dinge, an die sich selbst die wildesten Entwickler:innen halten sollten. Dazu zählen eine konsistente Struktur, Dokumentation und Tests.

Natürlich ist das alles Standard in vernünftigen Applikationen, dennoch findet man in viel zu vielen Applikationen viel zu wenig davon. Deshalb werfen wir jetzt einmal einen Blick auf tsoa – ein Werkzeug, das gleich mehrere sinnvolle Erweiterungen für Node-Applikationen mitbringt: TypeScript, API-Dokumentation und Dependency Injection, um nur einige zu nennen.

tsoa – es steht übrigens für „TypeScript and Open API“ – ist ein Framework, das auf anderen Frameworks aufbaut. Es ist also nicht eigenständig nutzbar und somit am ehesten noch mit Nest vergleichbar. tsoa unterstützt aktuell Express, hapi und Koa als Basisframeworks.

Aller Anfang ist leicht

Beim Set-up müssen Sie grundsätzlich nichts Besonderes beachten. Wie bei nahezu jeder Node.js-Applikation geht es mit einem leeren Verzeichnis los, in dem Sie mit npm init -y eine neue package.json-Datei erstellen. Anschließend sorgen Sie dafür, dass alle Abhängigkeiten installiert sind. Das erreichen Sie mit den beiden Kommandos npm add tsoa express swagger-ui-express und npm add -D typescript @types/node @types/express @ types/swagger-ui-express. Im letzten Schritt konfigurieren Sie TypeScript (mit npx tsc --init) und tsoa. Für Letzteres erzeugen Sie im Wurzelverzeichnis Ihrer Applikation eine Datei mit dem Namen tsoa.json. Listing 1 enthält den Quellcode dieser Datei.

Listing 1: Konfiguration für tsoa

{
  "entryFile": "src/index.ts",
  "noImplicitAdditionalProperties": "throw-on-extras",
  "controllerPathGlobs": ["src/**/*.controller.ts"],
  "spec": {
    "outputDirectory": "build",
    "specVersion": 3
  },
  "routes": {
    "routesDir": "build"
  }
}

Mit dieser Konfiguration geht tsoa davon aus, dass sich der Quellcode Ihrer Applikation in einem Verzeichnis mit dem Namen src befindet und dort die index.ts-Datei den Startpunkt darstellt. Die Controller-Dateien, mit denen Sie Ihre Endpunkte definieren, enden auf .controller.ts. tsoa erzeugt die Ausgabe im build-Verzeichnis. Dieser Build-Prozess ist allein schon deshalb notwendig, weil Ihre Applikation in TypeScript entwickelt wird und Node diesen Quellcode nicht direkt ausführen kann, ohne über jede Menge Syntaxfehler zu stolpern. Der Einstieg in die Applikation hat im Gegensatz dazu nur wenige Überraschungen parat, wie Sie in Listing 2 sehen können.

Listing 2: Einstieg in die Applikation

import express, { Request, Response } from 'express';
import { RegisterRoutes } from '../build/routes';
import swaggerUi from 'swagger-ui-express';
 
const app = express();
 
app.use(express.json());
 
app.use(
  '/api',
  swaggerUi.serve,
  async (request: Request, response: Response) => {
    return response.send(
      swaggerUi.generateHTML(await import('../build/swagger.json'))
    );
  }
);
 
RegisterRoutes(app);
 
app.listen(8080, () =>
  console.log('server is listening to http://localhost:8080')
);

Grundsätzlich implementieren Sie mit tsoa und in unserem Fall Express eine ganz gewöhnliche Applikation und können dort beliebige Middlewarefunktionen registrieren, wie ...