49 OpenAPI und die Anwendung des OpenAPI-Generators (TypeScript-Node)

OpenAPI, ehemals bekannt als Swagger, ist ein Spezifikationsframework für RESTful APIs. Es ermöglicht eine standardisierte Beschreibung von APIs, wodurch die Entwicklung, Dokumentation, Visualisierung und Client-Server-Generierung vereinfacht werden. Die OpenAPI-Spezifikation definiert ein standardisiertes Interface, um RESTful APIs zu beschreiben, unabhängig von der Programmiersprache.

49.1 OpenAPI-Generator

Der OpenAPI-Generator ist ein leistungsfähiges Tool, das aus OpenAPI-Spezifikationen Code in verschiedenen Programmiersprachen generiert. Dies automatisiert die Erstellung von API-Clientbibliotheken, Server-Stubs, API-Dokumentationen und anderen Komponenten.

49.1.1 TypeScript-Node Generator

Für Projekte, die TypeScript mit Node.js verwenden, bietet der OpenAPI-Generator die Möglichkeit, Client-Bibliotheken, Server-Stubs und andere nützliche Komponenten direkt aus einer OpenAPI-Spezifikation zu generieren. Dies spart erheblich Zeit und reduziert Fehler, die bei der manuellen Codeerstellung auftreten können.

49.2 Erstellung einer package.json für ein TypeScript-Node-Projekt

Ein zentraler Bestandteil bei der Entwicklung von Node.js-Anwendungen ist die package.json Datei. Sie definiert das Projekt und seine Abhängigkeiten. Im Kontext der Verwendung des OpenAPI-Generators für ein TypeScript-Node-Projekt könnte die package.json folgendermaßen aussehen:

{
  "name": "my_project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "generate:api": "openapi-generator-cli generate -g typescript-node -i ./openapi/contract.yaml -o ./build/openapi",
    "prebuild": "npm run generate:api",
    "build": "./node_modules/.bin/tsc",
    "prestart": "npm run build",
    "start": "node ./build/src/index.js",
    "test": "jest"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@openapitools/openapi-generator-cli": "^2.9.0",
    "@types/jest": "^29.5.11",
    "@types/lodash": "^4.14.202",
    "@types/node": "^20.4.2",
    "@types/request": "^2.48.12",
    "jest": "^29.7.0",
    "ts-jest": "^29.1.2",
    "tslint": "^6.1.3",
    "typescript": "^5.3.3"
  },
  "dependencies": {
    "lodash": "^4.17.21",
    "request": "^2.88.2"
  }
}

49.3 Einführung in OpenAPI Contracts

OpenAPI Contracts, auch bekannt als OpenAPI Spezifikationen, sind formale Beschreibungen von RESTful APIs. Sie bieten eine standardisierte Darstellung von API-Endpunkten, Anfragemethoden, Parametern, Antwortstrukturen und anderen wichtigen API-Details. OpenAPI Contracts ermöglichen es, APIs konsistent zu dokumentieren, zu entwickeln und zu testen.

49.3.1 Kernkomponenten eines OpenAPI Contracts

  1. Info-Block: Enthält grundlegende Informationen über die API, wie Titel, Beschreibung und Version.
  2. Paths: Definiert die einzelnen Endpunkte der API und die zugehörigen Operationen (GET, POST, PUT, DELETE etc.), einschließlich der Parameter und Antwortstrukturen.
  3. Components: Wiederverwendbare Spezifikationen, die über den gesamten Contract hinweg genutzt werden können, wie Objektschemata oder Sicherheitsdefinitionen.

49.3.2 Beispiel: Benutzer API Contract

openapi: 3.0.0
info:
  title: Benutzer API
  description: API für Dummy-Benutzerdaten
  version: 1.0.0

paths:
  /users:
    get:
      summary: Benutzer auflisten
      responses:
        '200':
          description: Erfolgreiche Anfrage
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
    post:
      summary: Neuen Benutzer hinzufügen
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '201':
          description: Benutzer erfolgreich hinzugefügt
        '400':
          description: Ungültige Anfrage

  /users/{id}:
    get:
      summary: Benutzer abrufen
      parameters:
        - name: id
          in: path
          required: true
          description: ID des Benutzers
          schema:
            type: integer
      responses:
        '200':
          description: Erfolgreiche Anfrage
        '404':
          description: Benutzer nicht gefunden
    put:
      summary: Benutzer aktualisieren
      parameters:
        - name: id
          in: path
          required: true
          description: ID des Benutzers
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '200':
          description: Benutzer erfolgreich aktualisiert
        '404':
          description: Benutzer nicht gefunden
    delete:
      summary: Benutzer löschen
      parameters:
        - name: id
          in: path
          required: true
          description: ID des Benutzers
          schema:
            type: integer
      responses:
        '204':
          description: Benutzer erfolgreich gelöscht
        '404':
          description: Benutzer nicht gefunden

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string
        username:
          type: string
        website:
          type: string

Dieser Contract beschreibt eine API zur Verwaltung von Benutzerdaten. Nachfolgend wird erläutert, wie dieser Contract mit dem OpenAPI-Generator genutzt werden kann, um TypeScript-Node-Client-Code zu generieren.

49.4 Anwendung des generierten TypeScript-Node-Codes

Nachdem der OpenAPI-Generator verwendet wurde, um aus dem Benutzer-API-Contract TypeScript-Node-Code zu erzeugen, kann dieser Code für die Interaktion mit der API genutzt werden. Hier ist ein Beispiel für die Nutzung des generierten Codes:

49.4.1 Einbinden der generierten Module

import { DefaultApi } from '../build/openapi/api/defaultApi';
import { User } from '../build/openapi/model/user';

49.4.2 Initialisierung des API-Clients

const api = new DefaultApi('http://localhost:3000');

49.5 Abrufen von Benutzerdaten

api.usersGet()
  .then((response: { body: User[]; }) => {
    const users: Array<User> = response.body;
    console.log('Liste der Benutzer:', users);
  })
  .catch((error: any) => {
    console.error('Fehler beim Abrufen der Benutzer:', error);
  });

Dieses Beispiel zeigt, wie der generierte Client verwendet wird, um Benutzerdaten von der API abzurufen. Es demonstriert die einfache Integration und Nutzung der generierten API-Clients in einer TypeScript-Node-Anwendung. Im nächsten Schritt könnten weitere Funktionen wie das Hinzufügen, Aktualisieren oder Löschen von Benutzerdaten implementiert werden.

49.6 Erstellung eines Server Mocks für Testzwecke

Um einen Server Mock für das Testen der Benutzer API zu erstellen, wird eine Kombination aus einer Daten-Datei und dem Tool json-server verwendet.

49.6.1 Schritt 1: Erstellen der Daten-Datei db.json

Die db.json-Datei dient als Datenquelle für den Mock-Server. Sie enthält ein JSON-Objekt, das die Benutzerdaten in einem Array speichert. Hier ein Beispiel:

{
  "users": [
    {
      "id": 1,
      "name": "Max Mustermann",
      "email": "max@example.com",
      "username": "maxm",
      "website": "www.max-mustermann.com"
    },
    {
      "id": 2,
      "name": "Anna Schmidt",
      "email": "anna@example.com",
      "username": "annas",
      "website": "www.anna-schmidt.net"
    },
    {
      "id": 3,
      "name": "Peter Müller",
      "email": "peter@example.com",
      "username": "peterm",
      "website": "www.peter-mueller.org"
    },
    {
      "id": 4,
      "name": "Linda Wagner",
      "email": "linda@example.com",
      "username": "lindaw",
      "website": "www.linda-wagner.de"
    },
    {
      "id": 5,
      "name": "Tom Becker",
      "email": "tom@example.com",
      "username": "tomb",
      "website": "www.tom-becker.eu"
    },
    {
      "id": 6,
      "name": "Sophia Klein",
      "email": "sophia@example.com",
      "username": "sophiak",
      "website": "www.sophia-klein.info"
    },
    {
      "id": 7,
      "name": "Jan Hartmann",
      "email": "jan@example.com",
      "username": "janh",
      "website": "www.jan-hartmann.at"
    },
    {
      "id": 8,
      "name": "Sarah Berger",
      "email": "sarah@example.com",
      "username": "sarahb",
      "website": "www.sarah-berger.ch"
    },
    {
      "id": 9,
      "name": "Markus Fischer",
      "email": "markus@example.com",
      "username": "markusf",
      "website": "www.markus-fischer.nl"
    },
    {
      "id": 10,
      "name": "Lisa Lehmann",
      "email": "lisa@example.com",
      "username": "lisal",
      "website": "www.lisa-lehmann.be"
    }
  ]
}

49.6.2 Schritt 2: Verwendung von json-server zum Erstellen des Mock-Servers

json-server ist ein NPM-Tool, das eine vollständige Fake REST API mit minimaler Einrichtung schnell simuliert. Der folgende Befehl wird verwendet, um json-server zu starten und die db.json-Datei zu überwachen:

npx json-server --watch db.json

49.6.3 Funktion des Mock-Servers

Nach Ausführung des Befehls wird json-server:

49.6.4 Nutzen für die Entwicklung

Durch den Einsatz dieses Mock-Servers können Entwickler:

In weiteren Schritten könnte die Integration des Mock-Servers in automatisierte Tests oder die Einbindung in eine Continuous Integration/Continuous Deployment (CI/CD) Pipeline betrachtet werden.