One place for hosting & domains

      Prisma

      Erstellen einer REST-API mit Prisma und PostgreSQL


      Der Autor hat den Diversity in Tech Fund dazu ausgewählt, eine Spende im Rahmen des Programms Write for DOnations zu erhalten.

      Einführung

      Prisma ist ein Open-Source-basiertes Datenbank-Toolkit. Es besteht aus drei Haupttools:

      • Prisma Client: Ein automatisch generierter und typensicherer Query Builder für Node.js und TypeScript.
      • Prisma Migrate: Ein deklaratives Modellierungs- und Migrationssystem für Daten.
      • Prisma Studio: Eine GUI zum Anzeigen und Bearbeiten von Daten in Ihrer Datenbank.

      Diese Tools dienen dazu, die Produktivität von Anwendungsentwicklern in ihren Datenbank-Workflows zu steigern. Einer der größten Vorteile von Prisma ist die Ebene der Abstraktion, die möglich ist: Anstatt komplexe SQL-Abfragen oder Schemamigrationen zu erstellen, können Anwendungsentwickler bei der Arbeit mit ihrer Datenbank unter Verwendung von Prisma Daten intuitiver verwalten.

      In diesem Tutorial erstellen Sie eine REST-API für eine kleine Blogging-Anwendung in TypeScript mithilfe von Prisma und eine PostgreSQL-Datenbank. Sie werden Ihre PostgreSQL-Datenbank mit Docker lokal einrichten und die REST-API mit Express implementieren. Am Ende des Tutorials verfügen Sie über einen Webserver, der auf Ihrem Rechner lokal ausgeführt wird und auf verschiedene HTTP-Anfragen reagieren sowie Daten in der Datenbank lesen und schreiben kann.

      Voraussetzungen

      Dieses Tutorial setzt Folgendes voraus:

      Grundlegende Vertrautheit mit TypeScript und REST-APIs ist hilfreich, für dieses Tutorial jedoch nicht erforderlich.

      Schritt 1 — Erstellen Ihres TypeScript-Projekts

      In diesem Schritt werden Sie mit npm ein einfaches TypeScript-Projekt einrichten. Dieses Projekt wird als Grundlage für die REST-API dienen, die Sie im Laufe dieses Tutorials erstellen werden.

      Erstellen Sie zunächst ein neues Verzeichnis für Ihr Projekt:

      Navigieren Sie als Nächstes in das Verzeichnis und initialisieren Sie ein leeres npm-Projekt. Beachten Sie, dass die Option -y hier bedeutet, dass Sie die interaktiven Eingabeaufforderungen des Befehls überspringen. Um die Eingabeaufforderungen zu durchlaufen, entfernen Sie -y aus dem Befehl:

      Weitere Details zu diesen Eingabeaufforderungen finden Sie in Schritt 1 unter Verwenden von Node.js-Modulen mit npm und package.json.

      Sie erhalten eine Ausgabe, die der folgenden ähnelt und die Standardantworten umfasst:

      Output

      Wrote to /.../my-blog/package.json: { "name": "my-blog", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

      Dieser Befehl erstellt eine minimale package.json-Datei, die Sie als Konfigurationsdatei für Ihr npm-Projekt verwenden können. Sie sind nun bereit, TypeScript in Ihrem Projekt zu konfigurieren.

      Führen Sie den folgenden Befehl für eine einfache TypeScript-Einrichtung aus:

      • npm install typescript ts-node @types/node --save-dev

      Dadurch werden drei Pakete als Entwicklungsabhängigkeiten in Ihrem Projekt installiert:

      • typescript: Die TypeScript-Toolchain.
      • ts-node: Ein Paket zum Ausführen von TypeScript-Anwendungen ohne vorherige Kompilierung in JavaScript.
      • @types/node: Die TypeScript-Typdefinitionen für Node.js.

      Die letzte Aufgabe besteht darin, eine tsconfig.json-Datei hinzuzufügen, um sicherzustellen, dass TypeScript für die von Ihnen erstellte Anwendung richtig konfiguriert ist.

      Führen Sie den folgenden Befehl aus, um die Datei zu erstellen:

      Fügen Sie in der Datei den folgenden JSON-Code hinzu:

      my-blog/tsconfig.json

      {
        "compilerOptions": {
          "sourceMap": true,
          "outDir": "dist",
          "strict": true,
          "lib": ["esnext"],
          "esModuleInterop": true
        }
      }
      

      Speichern und schließen Sie die Datei.

      Dies ist eine Standard- und Minimalkonfiguration für ein TypeScript-Projekt. Wenn Sie mehr über die einzelnen Eigenschaften der Konfigurationsdatei erfahren möchten, können Sie die TypeScript-Dokumentation konsultieren.

      Sie haben Ihr einfaches TypeScript-Projekt mit npm eingerichtet. Als Nächstes werden Sie Ihre PostgreSQL-Datenbank mit Docker einrichten und Prisma damit verbinden.

      Schritt 2 — Einrichten von Prisma mit PostgreSQL

      In diesem Schritt installieren Sie die Prisma-CLI , erstellen Ihre erste Prisma-Schemadatei, richten PostgreSQL mit Docker ein und verbinden Prisma damit. Das Prisma-Schema ist die wichtigste Konfigurationsdatei für Ihr Prisma-Setup und enthält das Datenbankschema.

      Installieren Sie zunächst die Prisma-CLI mit dem folgenden Befehl:

      • npm install @prisma/cli --save-dev

      Als bewährte Praxis wird empfohlen, die Prisma-CLI in Ihrem Projekt lokal zu installieren (und nicht im Rahmen einer globalen Installation). Dadurch lassen sich Versionskonflikte vermeiden, falls Sie mehr als ein Prisma-Projekt auf Ihrem Rechner verwenden.

      Als Nächstes richten Sie mit Docker Ihre PostgreSQL-Datenbank ein. Erstellen Sie mit dem folgenden Befehl eine neue Docker Compose-Datei:

      Fügen Sie der neu erstellten Datei den folgenden Code hinzu:

      my-blog/docker-compose.yml

      version: '3.8'
      services:
        postgres:
          image: postgres:10.3
          restart: always
          environment:
            - POSTGRES_USER=sammy
            - POSTGRES_PASSWORD=your_password
          volumes:
            - postgres:/var/lib/postgresql/data
          ports:
            - '5432:5432'
      volumes:
        postgres:
      

      Diese Docker Compose-Datei konfiguriert eine PostgreSQL-Datenbank, auf die über Port 5432 des Docker-Containers zugegriffen werden kann. Beachten Sie außerdem, dass die Anmeldedaten für die Datenbank aktuell sammy (Benutzer) und your_password (Passwort) lauten. Sie können diese Anmeldedaten in Ihren bevorzugten Benutzer und Ihr bevorzugtes Passwort ändern. Speichern und schließen Sie die Datei.

      Fahren Sie nun fort und starten Sie den PostgreSQL-Datenbankserver mit dem folgenden Befehl:

      Die Ausgabe dieses Befehls wird in etwa wie folgt aussehen:

      Output

      Pulling postgres (postgres:10.3)... 10.3: Pulling from library/postgres f2aa67a397c4: Pull complete 6de83ca23e55: Pull complete . . . Status: Downloaded newer image for postgres:10.3 Creating my-blog_postgres_1 ... done

      Sie können mit folgendem Befehl überprüfen, ob der Datenbankserver ausgeführt wird:

      Dadurch erhalten Sie eine Aufgabe, die in etwa wie folgt aussieht:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8547f8e007ba postgres:10.3 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp my-blog_postgres_1

      Nachdem der Datenbankserver ausgeführt wird, können Sie nun Ihr Prisma-Setup erstellen. Führen Sie den folgenden Befehl über die Prisma-CLI aus:

      Dadurch erhalten Sie folgende Ausgabe:

      Output

      ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor.

      Beachten Sie, dass Sie als bewährte Praxis allen Aufrufen der Prisma-CLI npx voranstellen sollten. Dadurch wird sichergestellt, dass Sie Ihre lokale Installation verwenden.

      Nachdem Sie den Befehl ausgeführt haben, erstellt die Prisma-CLI in Ihrem Projekt einen neuen Ordner namens prisma. Er enthält die folgenden zwei Dateien:

      • schema.prisma: Die Hauptkonfigurationsdatei für Ihr Prisma-Projekt (schließt Ihr Datenmodell mit ein).
      • .env: Eine dotenv-Datei zum Definieren Ihrer Datenbankverbindungs-URL.

      Um sicherzustellen, dass Prisma den Speicherort Ihrer Datenbank kennt, öffnen Sie die Datei .env und passen Sie die Umgebungsvariable DATABASE_URL an.

      Öffnen Sie zunächst die .env-Datei:

      Jetzt können Sie die Umgebungsvariable wie folgt setzen:

      my-blog/prisma/.env

      DATABASE_URL="postgresql://sammy:your_password@localhost:5432/my-blog?schema=public"
      

      Ändern Sie die Anmeldedaten für die Datenbank unbedingt auf jene, die Sie in der Docker Compose-Datei angegeben haben. Um mehr über das Format der Verbindungs-URL zu erfahren, besuchen Sie die Prisma-Dokumentation.

      Wenn Sie damit fertig sind, speichern und schließen Sie die Datei.

      In diesem Schritt haben Sie Ihre PostgreSQL-Datenbank mit Docker eingerichtet, die Prisma-CLI installiert und Prisma über eine Umgebungsvariable mit der Datenbank verbunden. Im nächsten Abschnitt definieren Sie Ihr Datenmodell und erstellen Ihre Datenbanktabellen.

      Schritt 3 — Definieren des Datenmodells und Erstellen von Datenbanktabellen

      In diesem Schritt definieren Sie Ihr Datenmodell in der Prisma-Schemadatei. Dieses Datenmodell wird dann mit Prisma Migrate der Datenbank zugeordnet; dadurch werden die SQL-Anweisungen generiert und gesendet, um die Tabellen zu erstellen, die Ihrem Datenmodell entsprechen. Da Sie eine Blogging-Anwendung erstellen, werden die wichtigsten Entitäten der Anwendung Benutzer und Beiträge sein.

      Prisma verwendet seine eigene Datenmodellierungssprache zum Definieren der Form Ihrer Anwendungsdaten.

      Öffnen Sie zunächst Ihre schema.prisma-Datei mit dem folgenden Befehl:

      • nano prisma/schema.prisma

      Fügen Sie nun folgende Modelldefinitionen hinzu. Sie können die Modelle am Ende der Datei platzieren, unmittelbar nach dem generator client-Block:

      my-blog/prisma/schema.prisma

      . . .
      model User {
        id    Int     @default(autoincrement()) @id
        email String  @unique
        name  String?
        posts Post[]
      }
      
      model Post {
        id        Int     @default(autoincrement()) @id
        title     String
        content   String?
        published Boolean @default(false)
        author    User?   @relation(fields: [authorId], references: tag:www.digitalocean.com,2005:/community/tutorials/how-to-build-a-rest-api-with-prisma-and-postgresql-de)
        authorId  Int?
      }
      

      Speichern und schließen Sie die Datei.

      Sie definieren zwei Modelle namens User und Post. Jedes von ihnen verfügt über eine Reihe vonFeldern, die die Eigenschaften des Modells darstellen. Die Modelle werden Datenbanktabellen zugeordnet; die Felder stellen die einzelnen Spalten dar.

      Beachten Sie außerdem, dass es eine one-to-many-Beziehung zwischen den beiden Modellen gibt, die von den Beziehungsfeldern posts und author in User und Post angegeben werden. Das bedeutet, dass ein Benutzer mit verschiedenen Beiträgen verknüpft sein kann.

      Nach Implementierung dieser Modelle können Sie nun unter Verwendung von Prisma Migrate die entsprechenden Tabellen in der Datenbank erstellen. Führen Sie in Ihrem Terminal folgenden Befehl aus:

      • npx prisma migrate save --experimental --create-db --name "init"

      Dieser Befehl erstellt in Ihrem Dateisystem eine neue Migration. Hier finden Sie einen kurzen Überblick über die drei Optionen, die dem Befehl bereitgestellt werden:

      • --experimental: Erforderlich, da Prisma Migrate derzeit in einem experimentellen Zustand ist.
      • --create-db: Ermöglicht Prisma Migrate die Erstellung der Datenbank mit dem Namen my-blog, die in der Verbindungs-URL angegeben ist.
      • --name "init": Gibt den Namen der Migration an (wird zum Benennen des Migrationsordners verwendet, der in Ihrem Dateisystem erstellt wird).

      Die Ausgabe dieses Befehls wird in etwa wie folgt aussehen:

      Output

      New datamodel: // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id Int @default(autoincrement()) @id email String @unique name String? posts Post[] } model Post { id Int @default(autoincrement()) @id title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: tag:www.digitalocean.com,2005:/community/tutorials/how-to-build-a-rest-api-with-prisma-and-postgresql-de) authorId Int? } Prisma Migrate just created your migration 20200811140708-init in migrations/ └─ 20200811140708-init/ └─ steps.json └─ schema.prisma └─ README.md

      Sie können die Migrationsdateien erkunden, die im Verzeichnis prisma/migrations erstellt wurden.

      Um die Migration für Ihre Datenbank auszuführen und die Tabellen für Ihre Prisma-Modelle zu erstellen, führen Sie in Ihrem Terminal folgenden Befehl aus:

      • npx prisma migrate up --experimental

      Sie erhalten die folgende Ausgabe:

      Output

      . . . Checking the datasource for potential data loss... Database Changes: Migration Database actions Status 20200811140708-init 2 CreateTable statements. Done 🚀 You can get the detailed db changes with prisma migrate up --experimental --verbose Or read about them here: ./migrations/20200811140708-init/README.md 🚀 Done with 1 migration in 206ms.

      Prisma Migrate generiert nun die SQL-Anweisungen, die für die Migration erforderlich sind, und sendet sie an die Datenbank. Im Folgenden sehen Sie die SQL-Anweisungen, die die Tabellen erstellt haben:

      CREATE TABLE "public"."User" (
        "id" SERIAL,
        "email" text  NOT NULL ,
        "name" text   ,
        PRIMARY KEY ("id")
      )
      
      CREATE TABLE "public"."Post" (
        "id" SERIAL,
        "title" text  NOT NULL ,
        "content" text   ,
        "published" boolean  NOT NULL DEFAULT false,
        "authorId" integer   ,
        PRIMARY KEY ("id")
      )
      
      CREATE UNIQUE INDEX "User.email" ON "public"."User"("email")
      
      ALTER TABLE "public"."Post" ADD FOREIGN KEY ("authorId")REFERENCES "public"."User"("id") ON DELETE SET NULL ON UPDATE CASCADE
      

      In diesem Schritt haben Sie mit Prisma Migrate Ihr Datenmodell im Prisma-Schema definiert und die jeweiligen Datenbanktabellen erstellt. Im nächsten Schritt installieren Sie Prisma Client in Ihrem Projekt, damit Sie die Datenbank abfragen können.

      Schritt 4 — Erkunden von Prisma Client-Abfragen in einem einfachen Skript

      Prisma Client ist ein automatisch generierter und typensicherer Query Builder, mit dem Sie aus einer Node.js- oder TypeScript-Anwendung Daten in einer Datenbank programmatisch lesen und schreiben können. Sie werden ihn für Datenbankzugriff in Ihren REST-API-Routen verwenden, indem Sie traditionelle ORMs, einfache SQL-Abfragen, benutzerdefinierte Datenzugriffsebenen oder andere Methoden zur Kommunikation mit einer Datenbank ersetzen.

      In diesem Schritt installieren Sie Prisma Client und lernen die Abfragen kennen, die Sie damit senden können. Bevor Sie in den nächsten Schritten die Routen für Ihre REST-API implementieren, werden Sie zunächst einige der Prisma Client-Abfragen in einem einfachen ausführbaren Skript erkunden.

      Zuerst installieren Sie Prisma Client in Ihrem Projekt, indem Sie Ihr Terminal öffnen und das Prisma Client npm-Paket installieren:

      • npm install @prisma/client

      Erstellen Sie als Nächstes ein neues Verzeichnis namens src, das Ihre Quelldateien enthalten wird:

      Erstellen Sie nun in dem neuen Verzeichnis eine TypeScript-Datei:

      Alle Prisma Client-Abfragen geben promises (Zusagen) zurück, auf die Sie in Ihrem Code warten können. Dazu müssen Sie die Abfragen in einer async-Funktion senden.

      Fügen Sie den folgenden Codebaustein mit einer async-Funktion hinzu, die in Ihrem Skript ausgeführt wird:

      my-blog/src/index.ts

      import { PrismaClient } from '@prisma/client'
      
      const prisma = new PrismaClient()
      
      async function main() {
        // ... your Prisma Client queries will go here
      }
      
      main()
        .catch((e) => console.error(e))
        .finally(async () => await prisma.disconnect())
      

      Hier finden Sie einen kurzen Überblick über den Codebaustein:

      1. Sie importieren den PrismaClient-Konstruktor aus dem zuvor installierten @prisma/client npm-Paket.
      2. Sie instanziieren PrismaClient, indem Sie den Konstrukteur aufrufen, und erhalten eine Instanz namens prisma.
      3. Sie definieren eine async-Funktion namens main, wo Sie als Nächstes Ihre Prisma Client-Abfragen hinzufügen werden.
      4. Sie rufen die main-Funktion auf, fangen dabei alle möglichen Ausnahmen ab und stellen sicher, dass Prisma Client alle offenen Datenbankverbindungen schließt, indem Sie prisma.disconnect() aufrufen.

      Nach Implementierung der main-Funktion können Sie mit dem Hinzufügen von Prisma Client-Abfragen in das Skript beginnen. Passen Sie index.ts wie folgt an:

      my-blog/src/index.ts

      import { PrismaClient } from '@prisma/client'
      
      const prisma = new PrismaClient()
      
      async function main() {
        const newUser = await prisma.user.create({
          data: {
            name: 'Alice',
            email: '[email protected]',
            posts: {
              create: {
                title: 'Hello World',
              },
            },
          },
        })
        console.log('Created new user: ', newUser)
      
        const allUsers = await prisma.user.findMany({
          include: { posts: true },
        })
        console.log('All users: ')
        console.dir(allUsers, { depth: null })
      }
      
      main()
        .catch((e) => console.error(e))
        .finally(async () => await prisma.disconnect())
      

      In diesem Code verwenden Sie zwei Prisma Client-Abfragen:

      • create: Erstellt einen neuen User-Eintrag. Beachten Sie, dass Sie in Wahrheit ein nested write verwenden, was bedeutet, dass Sie in derselben Abfrage sowohl einen User– als auch einen Post-Eintrag erstellen.
      • findMany: Liest alle vorhandenen User-Einträge aus der Datenbank. Sie geben die include-Option an, wodurch zusätzlich auch die entsprechenden Post-Einträge für die einzelnen User-Einträge geladen werden.

      Führen Sie das Skript nun mit dem folgenden Befehl aus:

      Sie erhalten in Ihrem Terminal folgende Ausgabe:

      Output

      Created new user: { id: 1, email: '[email protected]', name: 'Alice' } [ { id: 1, email: '[email protected]', name: 'Alice', posts: [ { id: 1, title: 'Hello World', content: null, published: false, authorId: 1 } ] }

      Anmerkung: Wenn Sie eine Datenbank-GUI verwenden, können Sie überprüfen, ob die Daten erstellt wurden, indem Sie sich die Tabellen User und Post ansehen. Alternativ können Sie die Daten in Prisma Studio erkunden, indem Sie npx prisma studio --experimental ausführen.

      Sie haben Prisma Client nun verwendet, um Daten in Ihrer Datenbank zu lesen und zu schreiben. In den verbleibenden Schritten wenden Sie dieses neue Wissen an, um die Routen für eine beispielhafte REST-API zu implementieren.

      Schritt 5 — Implementieren Ihrer ersten REST-API-Route

      In diesem Schritt installieren Sie Express in Ihrer Anwendung. Express ist ein beliebtes Webframework für Node.js, das Sie zur Implementierung der REST-API-Routen in diesem Projekt verwenden werden. Die erste Route, die Sie implementieren werden, erlaubt es, mithilfe einer GET-Anfrage alle Benutzer von der API abzurufen. Die Benutzerdaten werden mit Prisma Client aus der Datenbank abgerufen.

      Installieren Sie dann Express mit dem folgenden Befehl:

      Da Sie TypeScript verwenden, sollten Sie die jeweiligen Typen auch als Entwicklungsabhängigkeiten installieren. Führen Sie dazu folgenden Befehl aus:

      • npm install @types/express --save-dev

      Nach Implementierung der Abhängigkeiten können Sie Ihre Express-Anwendung einrichten.

      Öffnen Sie dazu erneut Ihre zentrale Quelldatei:

      Löschen Sie nun den ganzen Code in index.ts und ersetzen Sie ihn durch Folgendes, um Ihre REST-API zu starten:

      my-blog/src/index.ts

      import { PrismaClient } from '@prisma/client'
      import express from 'express'
      
      const prisma = new PrismaClient()
      const app = express()
      
      app.use(express.json())
      
      // ... your REST API routes will go here
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Hier finden Sie eine kurze Aufschlüsselung des Codes:

      1. Sie importieren PrismaClient und express aus den jeweiligen npm-Paketen.
      2. Sie instanziieren PrismaClient, indem Sie den Konstruktor aufrufen, und erhalten eine Instanz namens prisma.
      3. Sie erstellen Ihre Express-Anwendung, indem Sie express() aufrufen.
      4. Sie fügen die Middleware express.json() hinzu, um sicherzustellen, dass Express JSON-Daten ordnungsgemäß verarbeiten kann.
      5. Sie starten den Server unter Port 3000.

      Jetzt können Sie Ihre erste Route implementieren. Fügen Sie zwischen den Aufrufen für app.use und app.listen folgenden Code hinzu:

      my-blog/src/index.ts

      . . .
      app.use(express.json())
      
      app.get('/users', async (req, res) => {
        const users = await prisma.user.findMany()
        res.json(users)
      })
      
      app.listen(3000, () =>
      console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Speichern und schließen Sie anschließend Ihre Datei. Starten Sie dann mit dem folgenden Befehl Ihren lokalen Webserver:

      Sie erhalten die folgende Ausgabe:

      Output

      REST API server ready at: http://localhost:3000

      Um auf die Route /users zuzugreifen, können Sie Ihren Browser auf http://localhost:3000/users oder einen anderen HTTP-Client verweisen.

      In diesem Tutorial testen Sie alle REST-API-Routen mit curl (einem Terminal-basierten HTTP-Client).

      Anmerkung: Wenn Sie lieber einen GUI-basierten HTTP-Client verwenden, können Sie Alternativen wie Postwoman oder den Advanced REST Client verwenden.

      Öffnen Sie zum Testen Ihrer Route ein neues Terminalfenster oder eine Registerkarte (damit Ihr lokaler Webserver weiter ausgeführt werden kann) und führen Sie folgenden Befehl aus:

      • curl http://localhost:3000/users

      Sie erhalten die im vorherigen Schritt erstellten User-Daten:

      Output

      [{"id":1,"email":"[email protected]","name":"Alice"}]

      Beachten Sie, dass das posts-Array diesmal nicht enthalten ist. Das liegt daran, dass Sie die Option include nicht an den findMany-Aufruf in der Implementierung der Route /users übergeben.

      Sie haben unter /users Ihre erste REST-API-Route implementiert. Im nächsten Schritt implementieren Sie die verbleibenden REST-API-Routen, um Ihrer API weitere Funktionen hinzuzufügen.

      Schritt 6 — Implementieren der verbleibenden REST-API-Routen

      In diesem Schritt implementieren Sie die verbleibenden REST-API-Routen für Ihre Blogging-Anwendung. Am Ende wird Ihr Webserver verschiedene GET-, POST-, PUT– und DELETE-Anfragen bereitstellen.

      Hier finden Sie einen Überblick über die verschiedenen Routen, die Sie implementieren werden:

      HTTP-MethodeRouteBeschreibung
      GET/feedRuft alle veröffentlichten Beiträge ab.
      GET/post/:idRuft einen einzelnen Beitrag anhand seiner ID ab.
      POST/userErstellt einen neuen Benutzer.
      POST/postErstellt einen neuen Beitrag (als Entwurf).
      PUT/post/publish/:idSetzt das published-Feld eines Beitrags auf true.
      DELETEpost/:idLöscht einen Beitrag anhand seiner ID.

      Fahren Sie fort und implementieren Sie zunächst die verbleibenden GET-Routen.

      Öffnen Sie die Datei index.ts mit dem folgenden Befehl:

      Fügen Sie dann im Anschluss an die Implementierung der Route /users folgenden Code hinzu:

      my-blog/src/index.ts

      . . .
      
      app.get('/feed', async (req, res) => {
        const posts = await prisma.post.findMany({
          where: { published: true },
          include: { author: true }
        })
        res.json(posts)
      })
      
      app.get(`/post/:id`, async (req, res) => {
        const { id } = req.params
        const post = await prisma.post.findOne({
          where: { id: Number(id) },
        })
        res.json(post)
      })
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Speichern und schließen Sie Ihre Datei.

      Dieser Code implementiert die API-Routen für zwei GET-Anfragen:

      • /feed: Gibt eine Liste mit veröffentlichten Beiträgen zurück.
      • /post/:id: Gibt einen einzelnen Beitrag anhand seiner ID zurück.

      Prisma Client wird in beiden Implementierungen verwendet. In der Implementierung der Route /feed filtert die Abfrage, die Sie mit Prisma Client senden, nach allen Post-Einträgen, bei denen die Spalte published den Wert true enthält. Außerdem nutzt die Prisma Client-Abfrage include, um die entsprechenden author-Informationen für die einzelnen Beiträge abzurufen. In der Implementierung der Route /post/:id übergeben Sie die ID, die aus dem URL-Pfad abgerufen wird, um einen bestimmten Post-Eintrag aus der Datenbank zu lesen.

      Sie können den Server anhalten, indem Sie auf Ihrer Tastatur Strg+C drücken. Starten Sie dann den Server neu:

      Um die Route /feed zu testen, können Sie folgenden curl-Befehl verwenden:

      • curl http://localhost:3000/feed

      Da noch keine Beiträge veröffentlicht wurden, ist die Antwort ein leeres Array:

      Output

      []

      Um die Route /post/:id zu testen, können Sie folgenden curl-Befehl verwenden:

      • curl http://localhost:3000/post/1

      Dadurch wird der von Ihnen ursprünglich erstellte Beitrag zurückgegeben:

      Output

      {"id":1,"title":"Hello World","content":null,"published":false,"authorId":1}

      Implementieren Sie als Nächstes die beiden POST-Routen. Fügen Sie nach den Implementierungen der drei GET-Routen folgenden Code zu index.ts hinzu:

      my-blog/src/index.ts

      . . .
      
      app.post(`/user`, async (req, res) => {
        const result = await prisma.user.create({
          data: { ...req.body },
        })
        res.json(result)
      })
      
      app.post(`/post`, async (req, res) => {
        const { title, content, authorEmail } = req.body
        const result = await prisma.post.create({
          data: {
            title,
            content,
            published: false,
            author: { connect: { email: authorEmail } },
          },
        })
        res.json(result)
      })
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Wenn Sie damit fertig sind, speichern und schließen Sie die Datei.

      Dieser Code implementiert die API-Routen für zwei POST-Anfragen:

      • /user: Erstellt in der Datenbank einen neuen Benutzer.
      • /post: Erstellt in der Datenbank einen neuen Beitrag.

      Wie zuvor wird in beiden Implementierungen Prisma Client verwendet. In der Implementierung der Route /user übergeben Sie die Werte aus dem Haupttext der HTTP-Anfrage an die Prisma Client-Abfrage create.

      Die Route /post ist etwas aufwendiger: Hier können Sie die Werte aus dem Haupttext der HTTP-Anfrage nicht direkt übergeben; stattdessen müssen Sie sie zunächst manuell extrahieren, um sie dann an die Prisma Client-Abfrage zu übergeben. Der Grund dafür besteht darin, dass die Struktur von JSON im Haupttext der Anfrage nicht mit der Struktur übereinstimmt, die Prisma Client erwartet. Daher müssen Sie die erwartete Struktur manuell einrichten.

      Sie können die neuen Routen testen, indem Sie den Server mit Strg+C anhalten. Starten Sie dann den Server neu:

      Um über die Route /user einen neuen Benutzer zu erstellen, können Sie mit curl folgende POST-Anfrage senden:

      • curl -X POST -H "Content-Type: application/json" -d '{"name":"Bob", "email":"[email protected]"}' http://localhost:3000/user

      Dadurch wird in der Datenbank ein neuer Benutzer erstellt und folgende Ausgabe ausgedruckt:

      Output

      {"id":2,"email":"[email protected]","name":"Bob"}

      Um über die Route /post einen neuen Beitrag zu erstellen, können Sie mit curl folgende POST-Anfrage senden:

      • curl -X POST -H "Content-Type: application/json" -d '{"title":"I am Bob", "authorEmail":"[email protected]"}' http://localhost:3000/post

      Dadurch wird in der Datenbank ein neuer Beitrag erstellt und unter Verwendung der E-Mail-Adresse [email protected] mit dem Benutzer verbunden. Sie erhalten die folgende Ausgabe:

      Output

      {"id":2,"title":"I am Bob","content":null,"published":false,"authorId":2}

      Schließlich können Sie die Routen PUT und DELETE implementieren.

      Öffnen Sie die Datei index.ts mit dem folgenden Befehl:

      Fügen Sie dann nach der Implementierung der beiden POST-Routen den hervorgehobenen Code hinzu:

      my-blog/src/index.ts

      . . .
      
      app.put('/post/publish/:id', async (req, res) => {
        const { id } = req.params
        const post = await prisma.post.update({
          where: { id: Number(id) },
          data: { published: true },
        })
        res.json(post)
      })
      
      app.delete(`/post/:id`, async (req, res) => {
        const { id } = req.params
        const post = await prisma.post.delete({
          where: { id: Number(id) },
        })
        res.json(post)
      })
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Speichern und schließen Sie Ihre Datei.

      Dieser Code implementiert die API-Routen für eine PUT– sowie eine DELETE-Anfrage.

      • /post/publish/:id (PUT): Veröffentlicht einen Beitrag anhand seiner ID.
      • /post/:id (DELETE) Löscht einen Beitrag anhand seiner ID.

      Erneut wird Prisma Client in beiden Implementierungen verwendet. In der Implementierung der Route /post/publish/:id wird die ID des zu veröffentlichenden Beitrags von der URL abgerufen und an die update-Abfrage von Prisma Client übergeben. Die Implementierung der Route /post/:id zum Löschen eines Beitrags in der Datenbank ruft außerdem die Beitrags-ID aus der URL ab und übergibt sie an die delete-Abfrage von Prisma Client.

      Halten Sie den Server mit Strg+C auf Ihrer Tastatur erneut an. Starten Sie dann den Server neu:

      Sie können die Route PUT mit dem folgenden curl-Befehl testen:

      • curl -X PUT http://localhost:3000/post/publish/2

      Dadurch wird der Beitrag mit einem ID-Wert von 2 veröffentlicht. Wenn Sie die Anfrage /feed neu senden, wird dieser Beitrag nun in die Antwort aufgenommen.

      Abschließend können Sie die Route DELETE mit dem folgenden curl-Befehl testen:

      • curl -X DELETE http://localhost:3000/post/1

      Dadurch wird der Beitrag mit dem ID-Wert von 1 gelöscht. Um zu überprüfen, ob der Beitrag mit dieser ID gelöscht wurde, können Sie erneut eine GET-Anfrage an die Route /post/1 senden.

      In diesem Schritt haben Sie die verbleibenden REST-API-Routen für Ihre Blogging-Anwendung implementiert. Die API reagiert nun auf verschiedene GET-, POST-, PUT– und DELETE-Anfragen und implementiert Funktionen zum Lesen und Schreiben von Daten in der Datenbank.

      Zusammenfassung

      In diesem Artikel haben Sie eine REST-API mit einer Reihe von verschiedenen Routen erstellt, um Benutzer- und Beitragsdaten für eine beispielhafte Blogging-Anwendung zu erstellen, zu lesen, zu aktualisieren und zu löschen. Innerhalb der API-Routen haben Sie den Prisma Client zum Senden der entsprechenden Abfragen an Ihre Datenbank verwendet.

      Als Nächstes können Sie weitere API-Routen implementieren oder Ihr Datenbankschema mithilfe von Prisma Migrate erweitern. Konsultieren Sie die Prisma-Dokumentation, um mehr über verschiedene Aspekte von Prisma zu erfahren und einige sofort einsatzbereite Beispielprojekte zu erkunden (im Repository prisma-examples). Verwenden Sie dazu Tools wie GraphQL oder grPC APIs.



      Source link

      How To Build a REST API with Prisma and PostgreSQL


      The author selected the Diversity in Tech Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Prisma is an open source database toolkit. It consists of three main tools:

      • Prisma Client: An auto-generated and type-safe query builder for Node.js and TypeScript.
      • Prisma Migrate: A declarative data modeling and migration system.
      • Prisma Studio: A GUI to view and edit data in your database.

      These tools aim to increase an application developer’s productivity in their database workflows. One of the top benefits of Prisma is the level of abstraction it provides: Instead of figuring out complex SQL queries or schema migrations, application developers can reason about their data in a more intuitive way when using Prisma to work with their database.

      In this tutorial, you will build a REST API for a small blogging application in TypeScript using Prisma and a PostgreSQL database. You will set up your PostgreSQL database locally with Docker and implement the REST API routes using Express. At the end of the tutorial, you will have a web server running locally on your machine that can respond to various HTTP requests and read and write data in the database.

      Prerequisites

      This tutorial assumes the following:

      Basic familiarity with TypeScript and REST APIs is helpful but not required for this tutorial.

      Step 1 — Creating Your TypeScript Project

      In this step, you will set up a plain TypeScript project using npm. This project will be the foundation for the REST API you’re going to build throughout the course of this tutorial.

      First, create a new directory for your project:

      Next, navigate into the directory and initialize an empty npm project. Note that the -y option here means that you’re skipping the interactive prompts of the command. To run through the prompts, remove -y from the command:

      For more details on these prompts, you can follow Step 1 in How To Use Node.js Modules with npm and package.json.

      You’ll receive output similar to the following with the default responses in place:

      Output

      Wrote to /.../my-blog/package.json: { "name": "my-blog", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

      This command creates a minimal package.json file that you use as the configuration file for your npm project. You’re now ready to configure TypeScript in your project.

      Execute the following command for a plain TypeScript setup:

      • npm install typescript ts-node @types/node --save-dev

      This installs three packages as development dependencies in your project:

      • typescript: The TypeScript toolchain.
      • ts-node: A package to run TypeScript applications without prior compilation to JavaScript.
      • @types/node: The TypeScript type definitions for Node.js.

      The last thing to do is to add a tsconfig.json file to ensure TypeScript is properly configured for the application you’re going to build.

      First, run the following command to create the file:

      Add the following JSON code into the file:

      my-blog/tsconfig.json

      {
        "compilerOptions": {
          "sourceMap": true,
          "outDir": "dist",
          "strict": true,
          "lib": ["esnext"],
          "esModuleInterop": true
        }
      }
      

      Save and exit the file.

      This is a standard and minimal configuration for a TypeScript project. If you want to learn about the individual properties of the configuration file, you can look them up in the TypeScript documentation.

      You’ve set up your plain TypeScript project using npm. Next you’ll set up your PostgreSQL database with Docker and connect Prisma to it.

      Step 2 — Setting Up Prisma with PostgreSQL

      In this step, you will install the Prisma CLI, create your initial Prisma schema file, and set up PostgreSQL with Docker and connect Prisma to it. The Prisma schema is the main configuration file for your Prisma setup and contains your database schema.

      Start by installing the Prisma CLI with the following command:

      • npm install @prisma/cli --save-dev

      As a best practice, it is recommended to install the Prisma CLI locally in your project (as opposed to a global installation). This helps avoid version conflicts in case you have more than one Prisma project on your machine.

      Next, you’ll set up your PostgreSQL database using Docker. Create a new Docker Compose file with the following command:

      Now add the following code to the newly created file:

      my-blog/docker-compose.yml

      version: '3.8'
      services:
        postgres:
          image: postgres:10.3
          restart: always
          environment:
            - POSTGRES_USER=sammy
            - POSTGRES_PASSWORD=your_password
          volumes:
            - postgres:/var/lib/postgresql/data
          ports:
            - '5432:5432'
      volumes:
        postgres:
      

      This Docker Compose file configures a PostgreSQL database that can be accessed via port 5432 of the Docker container. Also note that the database credentials are currently set as sammy (user) and your_password (password). Feel free to adjust these credentials to your preferred user and password. Save and exit the file.

      With this setup in place, go ahead and launch the PostgreSQL database server with the following command:

      The output of this command will be similar to this:

      Output

      Pulling postgres (postgres:10.3)... 10.3: Pulling from library/postgres f2aa67a397c4: Pull complete 6de83ca23e55: Pull complete . . . Status: Downloaded newer image for postgres:10.3 Creating my-blog_postgres_1 ... done

      You can verify that the database server is running with the following command:

      This will output something similar to this:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8547f8e007ba postgres:10.3 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp my-blog_postgres_1

      With the database server running, you can now create your Prisma setup. Run the following command from the Prisma CLI:

      This will print the following output:

      Output

      ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor.

      Note that as a best practice, you should prefix all invocations of the Prisma CLI with npx. This ensures your local installation is being used.

      After you ran the command, the Prisma CLI created a new folder called prisma in your project. It contains the following two files:

      • schema.prisma: The main configuration file for your Prisma project (will include your data model).
      • .env: A dotenv file to define your database connection URL.

      To make sure Prisma knows about the location of your database, open the .env file and adjust the DATABASE_URL environment variable.

      First open the .env file:

      Now you can set the environment variable as follows:

      my-blog/prisma/.env

      DATABASE_URL="postgresql://sammy:your_password@localhost:5432/my-blog?schema=public"
      

      Make sure to change the database credentials to the ones you specified in the Docker Compose file. To learn more about the format of the connection URL, visit the Prisma docs.

      Once you’re done, save and exit the file.

      In this step, you set up your PostgreSQL database with Docker, installed the Prisma CLI, and connected Prisma to the database via an environment variable. In the next section, you’ll define your data model and create your database tables.

      Step 3 — Defining Your Data Model and Creating Database Tables

      In this step, you will define your data model in the Prisma schema file. This data model will then be mapped to the database with Prisma Migrate, which will generate and send the SQL statements for creating the tables that correspond to your data model. Since you’re building a blogging application, the main entities of the application will be users and posts.

      Prisma uses its own data modeling language to define the shape of your application data.

      First, open your schema.prisma file with the following command:

      • nano prisma/schema.prisma

      Now, add the following model definitions to it. You can place the models at the bottom of the file, right after the generator client block:

      my-blog/prisma/schema.prisma

      . . .
      model User {
        id    Int     @default(autoincrement()) @id
        email String  @unique
        name  String?
        posts Post[]
      }
      
      model Post {
        id        Int     @default(autoincrement()) @id
        title     String
        content   String?
        published Boolean @default(false)
        author    User?   @relation(fields: [authorId], references: tag:www.digitalocean.com,2005:/community/tutorials/how-to-build-a-rest-api-with-prisma-and-postgresql)
        authorId  Int?
      }
      

      Save and exit the file.

      You are defining two models, called User and Post. Each of these has a number of fields that represent the properties of the model. The models will be mapped to database tables; the fields represent the individual columns.

      Also note that there’s a one-to-many relation between the two models, specified by the posts and author relation fields on User and Post. This means that one user can be associated with many posts.

      With these models in place, you can now create the corresponding tables in the database using Prisma Migrate. In your terminal run the following command:

      • npx prisma migrate save --experimental --create-db --name "init"

      This command creates a new migration on your filesystem. Here’s a quick overview of the three options that are provided to the command:

      • --experimental: Required because Prisma Migrate is currently in an experimental state.
      • --create-db: Enables Prisma Migrate to create the database named my-blog that’s specified in the connection URL.
      • --name "init": Specifies the name of the migration (will be used to name the migration folder that’s created on your filesystem).

      The output of this command will be similar to this:

      Output

      New datamodel: // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id Int @default(autoincrement()) @id email String @unique name String? posts Post[] } model Post { id Int @default(autoincrement()) @id title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: tag:www.digitalocean.com,2005:/community/tutorials/how-to-build-a-rest-api-with-prisma-and-postgresql) authorId Int? } Prisma Migrate just created your migration 20200811140708-init in migrations/ └─ 20200811140708-init/ └─ steps.json └─ schema.prisma └─ README.md

      Feel free to explore the migration files that have been created in the prisma/migrations directory.

      To run the migration against your database and create the tables for your Prisma models, run the following command in your terminal:

      • npx prisma migrate up --experimental

      You’ll receive the following output:

      Output

      . . . Checking the datasource for potential data loss... Database Changes: Migration Database actions Status 20200811140708-init 2 CreateTable statements. Done 🚀 You can get the detailed db changes with prisma migrate up --experimental --verbose Or read about them here: ./migrations/20200811140708-init/README.md 🚀 Done with 1 migration in 206ms.

      Prisma Migrate now generates the SQL statements that are required for the migration and sends them to the database. The following are the SQL statements that created the tables:

      CREATE TABLE "public"."User" (
        "id" SERIAL,
        "email" text  NOT NULL ,
        "name" text   ,
        PRIMARY KEY ("id")
      )
      
      CREATE TABLE "public"."Post" (
        "id" SERIAL,
        "title" text  NOT NULL ,
        "content" text   ,
        "published" boolean  NOT NULL DEFAULT false,
        "authorId" integer   ,
        PRIMARY KEY ("id")
      )
      
      CREATE UNIQUE INDEX "User.email" ON "public"."User"("email")
      
      ALTER TABLE "public"."Post" ADD FOREIGN KEY ("authorId")REFERENCES "public"."User"("id") ON DELETE SET NULL ON UPDATE CASCADE
      

      In this step, you defined your data model in your Prisma schema and created the respective databases tables with Prisma Migrate. In the next step, you’ll install Prisma Client in your project so that you can query the database.

      Step 4 — Exploring Prisma Client Queries in a Plain Script

      Prisma Client is an auto-generated and type-safe query builder that you can use to programmatically read and write data in a database from a Node.js or TypeScript application. You will use it for database access within your REST API routes, replacing traditional ORMs, plain SQL queries, custom data access layers, or any other method of talking to a database.

      In this step, you will install Prisma Client and get familiar with the queries you can send with it. Before implementing the routes for your REST API in the next steps, you will first explore some of the Prisma Client queries in a plain, executable script.

      First, go ahead and install Prisma Client in your project by opening up your terminal and installing the Prisma Client npm package:

      • npm install @prisma/client

      Next, create a new directory called src that will contain your source files:

      Now create a TypeScript file inside of the new directory:

      All of the Prisma Client queries return promises that you can await in your code. This requires you to send the queries inside of an async function.

      Add the following boilerplate with an async function that’s executed in your script:

      my-blog/src/index.ts

      import { PrismaClient } from '@prisma/client'
      
      const prisma = new PrismaClient()
      
      async function main() {
        // ... your Prisma Client queries will go here
      }
      
      main()
        .catch((e) => console.error(e))
        .finally(async () => await prisma.disconnect())
      

      Here’s a quick breakdown of the boilerplate:

      1. You import the PrismaClient constructor from the previously installed @prisma/client npm package.
      2. You instantiate PrismaClient by calling the constructor and obtain an instance called prisma.
      3. You define an async function called main where you’ll add your Prisma Client queries next.
      4. You call the main function, while catching any potential exceptions and ensuring Prisma Client closes any open database connections by calling prisma.disconnect().

      With the main function in place, you can start adding Prisma Client queries to the script. Adjust index.ts to look as follows:

      my-blog/src/index.ts

      import { PrismaClient } from '@prisma/client'
      
      const prisma = new PrismaClient()
      
      async function main() {
        const newUser = await prisma.user.create({
          data: {
            name: 'Alice',
            email: '[email protected]',
            posts: {
              create: {
                title: 'Hello World',
              },
            },
          },
        })
        console.log('Created new user: ', newUser)
      
        const allUsers = await prisma.user.findMany({
          include: { posts: true },
        })
        console.log('All users: ')
        console.dir(allUsers, { depth: null })
      }
      
      main()
        .catch((e) => console.error(e))
        .finally(async () => await prisma.disconnect())
      

      In this code, you’re using two Prisma Client queries:

      • create: Creates a new User record. Notice that you’re actually using a nested write, meaning you’re creating both a User and Post record in the same query.
      • findMany: Reads all existing User records from the database. You’re providing the include option that additionally loads the related Post records for each User record.

      Now run the script with the following command:

      You will receive the following output in your terminal:

      Output

      Created new user: { id: 1, email: '[email protected]', name: 'Alice' } [ { id: 1, email: '[email protected]', name: 'Alice', posts: [ { id: 1, title: 'Hello World', content: null, published: false, authorId: 1 } ] }

      Note: If you are using a database GUI you can validate that the data was created by looking at the User and Post tables. Alternatively, you can explore the data in Prisma Studio by running npx prisma studio --experimental.

      You’ve now used Prisma Client to read and write data in your database. In the remaining steps, you’ll apply that new knowledge to implement the routes for a sample REST API.

      Step 5 — Implementing Your First REST API Route

      In this step, you will install Express in your application. Express is a popular web framework for Node.js that you will use to implement your REST API routes in this project. The first route you will implement will allow you to fetch all users from the API using a GET request. The user data will be retrieved from the database using Prisma Client.

      Go ahead and install Express with the following command:

      Since you’re using TypeScript, you’ll also want to install the respective types as development dependencies. Run the following command to do so:

      • npm install @types/express --save-dev

      With the dependencies in place, you can set up your Express application.

      Start by opening your main source file again:

      Now delete all the code in index.ts and replace it with the following to start your REST API:

      my-blog/src/index.ts

      import { PrismaClient } from '@prisma/client'
      import express from 'express'
      
      const prisma = new PrismaClient()
      const app = express()
      
      app.use(express.json())
      
      // ... your REST API routes will go here
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Here’s a quick breakdown of the code:

      1. You import PrismaClient and express from the respective npm packages.
      2. You instantiate PrismaClient by calling the constructor and obtain an instance called prisma.
      3. You create your Express app by calling express().
      4. You add the express.json() middleware to ensure JSON data can be processed properly by Express.
      5. You start the server on port 3000.

      Now you can implement your first route. Between the calls to app.use and app.listen, add the following code:

      my-blog/src/index.ts

      . . .
      app.use(express.json())
      
      app.get('/users', async (req, res) => {
        const users = await prisma.user.findMany()
        res.json(users)
      })
      
      app.listen(3000, () =>
      console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Once added, save and exit your file. Then start your local web server using the following command:

      You will receive the following output:

      Output

      REST API server ready at: http://localhost:3000

      To access the /users route you can point your browser to http://localhost:3000/users or any other HTTP client.

      In this tutorial, you will test all REST API routes using curl, a terminal-based HTTP client.

      Note: If you prefer to use a GUI-based HTTP client, you can use alternatives like Postwoman or the Advanced REST Client.

      To test your route, open up a new terminal window or tab (so that your local web server can keep running) and execute the following command:

      • curl http://localhost:3000/users

      You will receive the User data that you created in the previous step:

      Output

      [{"id":1,"email":"[email protected]","name":"Alice"}]

      Note that the posts array is not included this time. This is because you’re not passing the include option to the findMany call in the implementation of the /users route.

      You’ve implemented your first REST API route at /users. In the next step you will implement the remaining REST API routes to add more functionality to your API.

      Step 6 — Implementing the Remaining REST API Routes

      In this step, you will implement the remaining REST API routes for your blogging application. At the end, your web server will serve various GET, POST, PUT, and DELETE requests.

      Here is an overview of the different routes you will implement:

      HTTP MethodRouteDescription
      GET/feedFetches all published posts.
      GET/post/:idFetches a specific post by its ID.
      POST/userCreates a new user.
      POST/postCreates a new post (as a draft).
      PUT/post/publish/:idSets the published field of a post to true.
      DELETEpost/:idDeletes a post by its ID.

      Go ahead and implement the remaining GET routes first.

      Open up the index.ts with the following command:

      Next, add the following code following the implementation of the /users route:

      my-blog/src/index.ts

      . . .
      
      app.get('/feed', async (req, res) => {
        const posts = await prisma.post.findMany({
          where: { published: true },
          include: { author: true }
        })
        res.json(posts)
      })
      
      app.get(`/post/:id`, async (req, res) => {
        const { id } = req.params
        const post = await prisma.post.findOne({
          where: { id: Number(id) },
        })
        res.json(post)
      })
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Save and exit your file.

      This code implements the API routes for two GET requests:

      • /feed: Returns a list of published posts.
      • /post/:id: Returns a specific post by its ID.

      Prisma Client is used in both implementations. In the /feed route implementation, the query you send with Prisma Client filters for all Post records where the published column contains the value true. Additionally, the Prisma Client query uses include to also fetch the related author information for each returned post. In the /post/:id route implementation, you are passing the ID that is retrieved from the URL’s path in order to read a specific Post record from the database.

      You can stop the server hitting CTRL+C on your keyboard. Then, restart the server using:

      To test the /feed route, you can use the following curl command:

      • curl http://localhost:3000/feed

      Since no posts have been published yet, the response is an empty array:

      Output

      []

      To test the /post/:id route, you can use the following curl command:

      • curl http://localhost:3000/post/1

      This will return the post you initially created:

      Output

      {"id":1,"title":"Hello World","content":null,"published":false,"authorId":1}

      Next, implement the two POST routes. Add the following code to index.ts following the implementations of the three GET routes:

      my-blog/src/index.ts

      . . .
      
      app.post(`/user`, async (req, res) => {
        const result = await prisma.user.create({
          data: { ...req.body },
        })
        res.json(result)
      })
      
      app.post(`/post`, async (req, res) => {
        const { title, content, authorEmail } = req.body
        const result = await prisma.post.create({
          data: {
            title,
            content,
            published: false,
            author: { connect: { email: authorEmail } },
          },
        })
        res.json(result)
      })
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Once you’re done, save and exit your file.

      This code implements the API routes for two POST requests:

      • /user: Creates a new user in the database.
      • /post: Creates a new post in the database.

      Like before, Prisma Client is used in both implementations. In the /user route implementation, you’re passing in the values from the body of the HTTP request to the Prisma Client create query.

      The /post route is a bit more involved: Here you can’t directly pass in the values from the body of the HTTP request; instead you first need to manually extract them to pass them to the Prisma Client query. The reason for this is that the structure of the JSON in the request body does not match the structure that’s expected by Prisma Client, so you need to manually create the expected structure.

      You can test the new routes by stopping the server with CTRL+C. Then, restart the server using:

      To create a new user via the /user route, you can send the following POST request with curl:

      • curl -X POST -H "Content-Type: application/json" -d '{"name":"Bob", "email":"[email protected]"}' http://localhost:3000/user

      This will create a new user in the database, printing the following output:

      Output

      {"id":2,"email":"[email protected]","name":"Bob"}

      To create a new post via the /post route, you can send the following POST request with curl:

      • curl -X POST -H "Content-Type: application/json" -d '{"title":"I am Bob", "authorEmail":"[email protected]"}' http://localhost:3000/post

      This will create a new post in the database and connect it to the user with the email [email protected]. It prints the following output:

      Output

      {"id":2,"title":"I am Bob","content":null,"published":false,"authorId":2}

      Finally, you can implement the PUT and DELETE routes.

      Open up index.ts with the following command:

      Next, following the implementation of the two POST routes, add the highlighted code:

      my-blog/src/index.ts

      . . .
      
      app.put('/post/publish/:id', async (req, res) => {
        const { id } = req.params
        const post = await prisma.post.update({
          where: { id: Number(id) },
          data: { published: true },
        })
        res.json(post)
      })
      
      app.delete(`/post/:id`, async (req, res) => {
        const { id } = req.params
        const post = await prisma.post.delete({
          where: { id: Number(id) },
        })
        res.json(post)
      })
      
      app.listen(3000, () =>
        console.log('REST API server ready at: http://localhost:3000'),
      )
      

      Save and exit your file.

      This code implements the API routes for one PUT and one DELETE request:

      • /post/publish/:id (PUT): Publishes a post by its ID.
      • /post/:id (DELETE): Deletes a post by its ID.

      Again, Prisma Client is used in both implementations. In the /post/publish/:id route implementation, the ID of the post to be published is retrieved from the URL and passed to the update query of Prisma Client. The implementation of the /post/:id route to delete a post in the database also retrieves the post ID from the URL and passes it to the delete query of Prisma Client.

      Again, stop the server with CTRL+C on your keyboard. Then, restart the server using:

      You can test the PUT route with the following curl command:

      • curl -X PUT http://localhost:3000/post/publish/2

      This is going to publish the post with an ID value of 2. If you resend the /feed request, this post will now be included in the response.

      Finally, you can test the DELETE route with the following curl command:

      • curl -X DELETE http://localhost:3000/post/1

      This is going to delete the post with an ID value of 1. To validate that the post with this ID has been deleted, you can resend a GET request to the /post/1 route.

      In this step, you implemented the remaining REST API routes for your blogging application. The API now responds to various GET, POST, PUT, and DELETE requests and implements functionality to read and write data in the database.

      Conclusion

      In this article, you created a REST API server with a number of different routes to create, read, update, and delete user and post data for a sample blogging application. Inside of the API routes, you are using the Prisma Client to send the respective queries to your database.

      As next steps, you can implement additional API routes or extend your database schema using Prisma Migrate. Be sure to visit the Prisma documentation to learn about different aspects of Prisma and explore some ready-to-run example projects in the prisma-examples repository—using tools such as GraphQL or grPC APIs.



      Source link

      Como Configurar Manualmente um Servidor Prisma no Ubuntu 18.04


      A autora selecionou a Electronic Frontier Foundation para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O Prisma é uma camada de dados que substitui as ferramentas tradicionais de mapeamento relacional de objeto (ORMs) em sua aplicação. Oferecendo suporte tanto para a construção de servidores GraphQL, bem como REST APIs, o Prisma simplifica o acesso ao banco de dados com foco em segurança de tipo e permite migrações de banco de dados declarativas. A segurança de tipo ajuda a reduzir possíveis erros e inconsistências de código, enquanto as migrações de banco de dados declarativas permitem armazenar seu modelo de dados no controle de versão. Esses recursos ajudam os desenvolvedores a reduzir o tempo gasto na configuração de acesso a bancos de dados, migrações e fluxos de trabalho de gerenciamento de dados.

      Você pode fazer o deploy do servidor Prisma, que atua como um proxy para seu banco de dados, de várias maneiras e hospedá-lo remotamente ou localmente. Através do serviço do Prisma, você pode acessar seus dados e se conectar ao seu banco de dados com a API GraphQL, que permite operações em tempo real e a capacidade de criar, atualizar e excluir dados. O GraphQL é uma linguagem de consulta para APIs que permite aos usuários enviar consultas para acessar os dados exatos que eles precisam de seu servidor. O servidor Prisma é um componente independente que fica acima do seu banco de dados.

      Neste tutorial, você irá instalar manualmente um servidor Prisma no Ubuntu 18.04 e executará uma consulta de teste GraphQL no GraphQL Playground. Você hospedará seu código de configuração e desenvolvimento Prisma localmente — onde você constrói de fato a sua aplicação — enquanto executa o Prisma no seu servidor remoto. Ao realizar a instalação manualmente, você terá uma compreensão e uma personalização mais detalhadas da infraestrutura subjacente de sua configuração.

      Embora este tutorial aborde as etapas manuais para implantar o Prisma em um servidor Ubuntu 18.04, você também pode realizar isso de uma forma mais automatizada com a Docker Machine, seguindo este tutorial no site do Prisma.

      Note: A configuração descrita nesta seção não inclui recursos que você normalmente esperaria em servidores prontos para produção, como backups automatizados e failover ativo.

      Pré-requisitos

      Para completar este tutorial, você vai precisar de:

      O Prisma CLI é a principal ferramenta usada para fazer o deploy e gerenciar seus serviços Prisma. Para iniciar os serviços, você precisa configurar a infraestrutura necessária, que inclui o servidor Prisma e um banco de dados para conexão.

      O Docker Compose lhe permite gerenciar e executar aplicações multi-container. Você o utilizará para configurar a infraestrutura necessária para o serviço Prisma.

      Você começará criando o arquivo docker-compose.yml para armazenar a configuração do serviço Prisma em seu servidor. Você usará esse arquivo para ativar automaticamente o Prisma, um banco de dados associado, e configurar os detalhes necessários, tudo em uma única etapa. Uma vez que o arquivo é executado com o Docker Compose, ele irá configurar as senhas para seus bancos de dados, portanto, certifique-se de substituir as senhas para managementAPIsecret e MYSQL_ROOT_PASSWORD por algo seguro. Execute o seguinte comando para criar e editar o arquivo docker-compose.yml:

      • sudo nano docker-compose.yml

      Adicione o seguinte conteúdo ao arquivo para definir os serviços e volumes para a configuração do Prisma:

      docker-compose.yml

      
      version: "3"
      services:
        prisma:
          image: prismagraphql/prisma:1.20
          restart: always
          ports:
            - "4466:4466"
          environment:
            PRISMA_CONFIG: |
              port: 4466
              managementApiSecret: my-secret
              databases:
                default:
                  connector: mysql
                  host: mysql
                  port: 3306
                  user: root
                  password: prisma
                  migrations: true
        mysql:
          image: mysql:5.7
          restart: always
          environment:
            MYSQL_ROOT_PASSWORD: prisma
          volumes:
            - mysql:/var/lib/mysql
      volumes:
        mysql:
      

      Essa configuração faz o seguinte:

      • Lança dois serviços: prisma-db e db.

      • Baixa a última versão do Prisma. No momento da escrita desse artigo, ela é o Prisma 1.20.

      • Define as portas em que o Prisma estará disponível e especifica todas as credenciais para se conectar ao banco de dados MySQL na seção databases.

      O arquivo docker-compose.yml configura o managementApiSecret, que impede que outras pessoas acessem seus dados com conhecimento do seu endpoint. Se você estiver usando este tutorial apenas algo que não seja um deployment de teste, altere o managementAPIsecret para algo mais seguro. Quando fizer isso, guarde isso para que você possa inseri-lo mais tarde durante o processo prisma init.

      Esse arquivo também extrai a imagem Docker do MySQL e define essas credenciais também. Para os propósitos deste tutorial, este arquivo Docker Compose cria uma imagem MySQL, mas você também pode usar o PostgreSQL com o Prisma. Ambas as imagens Docker estão disponíveis no Docker Hub:

      Salve e saia do arquivo.

      Agora que você salvou todos os detalhes, você pode iniciar os containers do Docker. O comando -d diz aos containers para serem executados no modo detached, o que significa que eles serão executados em segundo plano:

      • sudo docker-compose up -d

      Isso irá buscar as imagens do Docker para prisma e mysql. Você pode verificar se os containers do Docker estão sendo executados com o seguinte comando:

      Você verá uma saída semelhante a esta:

      CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                    NAMES
      24f4dd6222b1        prismagraphql/prisma:1.12   "/bin/sh -c /app/sta…"   15 seconds ago      Up 1 second         0.0.0.0:4466->4466/tcp   root_prisma_1
      d8cc3a393a9f        mysql:5.7                   "docker-entrypoint.s…"   15 seconds ago      Up 13 seconds       3306/tcp                 root_mysql_1
      

      Com seu servidor Prisma e o banco de dados configurados, agora você está pronto para trabalhar localmente para fazer o deploy do serviço Prisma.

      Passo 2 — Instalando o Prisma Localmente

      O servidor Prisma fornece os ambientes de runtime para seus serviços Prisma. Agora que você tem seu servidor Prisma iniciado, você pode fazer o deploy do seu serviço Prisma. Você executará estas etapas localmente, não no seu servidor.

      Para começar, crie uma pasta separada que irá conter todos os arquivos do Prisma:

      Mova-se pra essa pasta:

      Você pode instalar o Prisma com o Homebrew se você estiver usando o MacOS. Para fazer isso, execute o seguinte comando para adicionar o repositório do Prisma:

      Você pode então instalar o Prisma com o seguinte comando:

      Ou, alternativamente com o npm:

      Com o Prisma instalado localmente, você está pronto para iniciar o novo serviço Prisma.

      Passo 3 — Criando a Configuração para um Novo Serviço Prisma

      Após a instalação, você pode usar o prisma init para criar a estrutura de arquivos para uma nova API de banco de dados Prisma, que gera os arquivos necessários para construir sua aplicação com o Prisma. Seu endpoint estará automaticamente no arquivo prisma.yml, e o datamodel.prisma já conterá um modelo de dados de amostra que você pode consultar na próxima etapa. O modelo de dados serve como base para sua API Prisma e especifica o modelo para sua aplicação. Neste ponto, você está criando apenas os arquivos e o modelo de dados de amostra. Você não está fazendo nenhuma alteração no banco de dados até executar o prisma deploy posteriormente nesta etapa.

      Agora você pode executar o seguinte comando localmente para criar a nova estrutura de arquivos:

      Depois de executar este comando, você verá um prompt interativo. Quando perguntado, selecione, Use other server e pressione ENTER:

      Output

      Set up a new Prisma server or deploy to an existing server? You can set up Prisma for local development (based on docker-compose) Use existing database Connect to existing database Create new database Set up a local database using Docker Or deploy to an existing Prisma server: Demo server Hosted demo environment incl. database (requires login) ❯ Use other server Manually provide endpoint of a running Prisma server

      Em seguida, você fornecerá o endpoint do seu servidor que está atuando como servidor Prisma. Será algo parecido com: http://IP_DO_SERVIDOR:4466. É importante que o endpoint comece com http (ou https) e tenha o número da porta indicado.

      Output

      Enter the endpoint of your Prisma server http://IP_DO_SERVIDOR:4466

      Para o segredo da API de gerenciamento, insira a frase ou senha que você indicou anteriormente no arquivo de configuração:

      Output

      Enter the management API secret my-secret

      Para as opções subseqüentes, você pode escolher as variáveis padrão pressionando ENTER para o service name e service stage:

      Output

      Choose a name for your service hello-world Choose a name for your stage dev

      Você também terá a opção de escolher uma linguagem de programação para o cliente Prisma. Nesse caso, você pode escolher sua linguagem preferida. Você pode ler mais sobre o cliente aqui.

      Output

      Select the programming language for the generated Prisma client (Use arrow keys) ❯ Prisma TypeScript Client Prisma Flow Client Prisma JavaScript Client Prisma Go Client Don't generate

      Depois de terminar o prompt, você verá a seguinte saída que confirma as seleções que você fez:

      Output

      Created 3 new files: prisma.yml Prisma service definition datamodel.prisma GraphQL SDL-based datamodel (foundation for database) .env Env file including PRISMA_API_MANAGEMENT_SECRET Next steps: 1. Open folder: cd hello-world 2. Deploy your Prisma service: prisma deploy 3. Read more about deploying services: http://bit.ly/prisma-deploy-services

      Vá para o diretório hello-world:

      Sincronize estas mudanças com o seu servidor usando prisma deploy. Isso envia as informações para o servidor Prisma a partir da sua máquina local e cria o serviço Prisma no servidor Prisma:

      Nota: A execução do prisma deploy novamente atualizará seu serviço Prisma.

      Sua saída será algo como:

      Output

      Creating stage dev for service hello-world ✔ Deploying service `hello-world` to stage 'dev' to server 'default' 468ms Changes: User (Type) + Created type `User` + Created field `id` of type `GraphQLID!` + Created field `name` of type `String!` + Created field `updatedAt` of type `DateTime!` + Created field `createdAt` of type `DateTime!` Applying changes 716ms Your Prisma GraphQL database endpoint is live: HTTP: http://IP_DO_SERVIDOR:4466/hello-world/dev WS: ws://IP_DO_SERVIDOR:4466/hello-world/dev

      A saída mostra que o Prisma atualizou seu banco de dados de acordo com o seu modelo de dados (criado na etapa prisma init) com um tipo User. Tipos são uma parte essencial de um modelo de dados; eles representam um item da sua aplicação, e cada tipo contém vários campos. Para o seu modelo de dados, os campos associados que descrevem o usuário são: o ID do usuário, o nome, a hora em que foram criados e o horário em que foram atualizados.

      Se você encontrar problemas nesse estágio e obtiver uma saída diferente, verifique novamente se digitou todos os campos corretamente durante o prompt interativo. Você pode fazer isso revisando o conteúdo do arquivo prisma.yml.

      Com seu serviço Prisma em execução, você pode se conectar a dois endpoints diferentes:

      • A interface de gerenciamento, disponível em http://IP_DO_SERVIDOR:4466/management, onde você pode gerenciar e fazer deployment de serviços Prisma.

      • A API GraphQL para o seu serviço Prisma, disponível em http://IP_DO_SERVIDOR:4466/hello-world/dev.

      Você configurou e fez o deployment com sucesso do seu servidor Prisma. Agora você pode explorar consultas e mutações no GraphQL.

      Passo 4 — Executando uma Consulta de Exemplo

      Para explorar outro caso de uso do Prisma, você pode experimentar em seu servidor a ferramenta GraphQL playground, que é um ambiente de desenvolvimento integrado open-source (IDE). Para acessá-lo, visite seu endpoint em seu navegador, da etapa anterior:

      http://IP_DO_SERVIDOR:4466/hello-world/dev
      

      Uma mutação é um termo do GraphQL que descreve uma maneira de modificar — criar, atualizar ou excluir (CRUD) — dados no backend via GraphQL. Você pode enviar uma mutação para criar um novo usuário e explorar a funcionalidade. Para fazer isso, execute a seguinte mutação no lado esquerdo da página:

      mutation {
        createUser(data: { name: "Alice" }) {
          id
          name
        }
      }
      

      Depois de pressionar o botão play, você verá os resultados no lado direito da página.

      Posteriormente, se você quiser procurar um usuário usando a coluna ID no banco de dados, poderá executar a seguinte consulta:

      query {
        user(where: { id: "cjkar2d62000k0847xuh4g70o" }) {
          id
          name
        }
      }
      

      Agora você tem um servidor Prisma e o serviço em funcionamento no servidor, e você executou consultas de teste no IDE do GraphQL.

      Conclusão

      Você tem uma configuração Prisma em funcionamento no seu servidor. Você pode ver alguns casos de uso adicionais do Prisma e os próximos passos no Guia de primeiros passos ou explorar o conjunto de recursos do Prisma no Prisma Docs. Depois de concluir todas as etapas deste tutorial, você tem várias opções para verificar sua conexão com o banco de dados, sendo que uma possibilidade é a utilização do Prisma Client.

      Por Etel Sverdlov



      Source link