One place for hosting & domains

      PostgreSQL

      Comment développer une API REST avec Prisma et PostgreSQL


      L’auteur a choisi le Diversity in Tech Fund​​​​​ pour recevoir un don dans le cadre du programme Write for DOnations.

      Introduction

      Prisma est une boîte à outils de base de données open source. Il se compose de trois outils principaux :

      • Prisma Client : un constructeur de requêtes automatisé de type sécurisé pour Node.js et TypeScript.
      • Prisma Migrate : un système déclaratif de modélisation et de migration de données.
      • Prisma Studio : une interface graphique permettant de visualiser et de modifier les données de votre base de données.

      Ces outils sont conçus pour optimiser la productivité d’un développeur d’applications dans les flux de travail de ses bases de données. L’un des principaux avantages de Prisma réside dans le niveau d’abstraction qu’il offre : Au lieu de trouver des requêtes SQL complexes ou des migrations de schéma, en utilisant Prisma, les développeurs d’applications peuvent travailler avec leur base de données en réfléchissant de manière plus intuitive sur leurs données.

      Dans ce tutoriel, vous allez créer une API REST pour une petite application de blogs dans TypeScript à l’aide de Prisma et d’une base de données PostgreSQL. Vous allez configurer votre base de données PostgreSQL localement avec Docker et implémenter des itinéraires API REST en utilisant Express. À la fin du tutoriel, vous disposerez d’un serveur web qui fonctionne localement sur votre machine, capable de répondre aux diverses demandes HTTP et de lire et écrire des données dans la base de données.

      Conditions préalables

      Ce tutoriel suppose que :

      Il vous sera utile d’avoir des connaissances de base sur les API TypeScript et REST, mais pas nécessaire pour suivre ce tutoriel.

      Étape 1 — Création de votre projet TypeScript

      Au cours de cette étape, vous allez configurer un projet TypeScript simple en utilisant npm. Ce projet constituera la base de l’API REST que vous allez développer tout au long de ce tutoriel.

      Tout d’abord, créez un nouveau répertoire pour votre projet :

      Ensuite, naviguez dans le répertoire et initialisez un projet npm vide. Notez que l’option -y signifie ici signifie que vous ignorez les invites interactives de la commande. Pour parcourir les invites, supprimez -y de la commande :

      Pour plus d’informations sur ces invites, vous pouvez suivre l’étape 1 dans Comment utiliser les modules Node.js avec npm et package.json.

      Vous obtiendrez un résultat similaire à ce qui suit, avec les réponses par défaut en 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" }

      Cette commande crée un fichier package.json minimal qui vous servira de fichier de configuration pour votre projet npm. Vous êtes maintenant prêt à configurer TypeScript dans votre projet.

      Exécutez la commande suivante pour procéder à une configuration simple de TypeScript :

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

      Vous installerez ainsi trois paquets en tant que dépendances de développement dans votre projet :

      • typescript : la chaîne d’outils TypeScript.
      • ts-node : un paquet qui exécutera les applications TypeScript sans compilation préalable à JavaScript.
      • @types/node : les définitions de type TypeScript pour Node.js.

      La dernière chose à faire consiste à ajouter un fichier tsconfig.json pour vous assurer que TypeScript est correctement configuré pour l’application que vous allez développer.

      Tout d’abord, exécutez la commande suivante pour créer le fichier :

      Ajoutez le code JSON suivant dans le fichier :

      my-blog/tsconfig.json

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

      Enregistrez et quittez le fichier.

      Il s’agit d’une configuration standard et minimale pour un projet TypeScript. Si vous souhaitez en savoir plus sur les propriétés individuelles du fichier de configuration, vous pouvez les consulter dans la documentation de TypeScript.

      Vous avez configuré votre projet TypeScript simple en utilisant npm. Ensuite, vous allez configurer votre base de données PostgreSQL avec Docker et y connecter Prisma.

      Étape 2 — Configuration de Prisma avec PostgreSQL

      Au cours de cette étape, vous allez installer la CLI Prisma, créer votre fichier de schéma Prisma, configurer PostgreSQL avec Docker et y connecter Prisma. Le schéma Prisma est le fichier de configuration principal de votre configuration Prisma et contient votre schéma de base de données.

      Commencez par installer la CLI Prisma avec la commande suivante :

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

      L’une des meilleures pratiques recommande d’installer la CLI Prisma localement dans votre projet (par opposition à une installation globale). Cela permet d’éviter les conflits de versions dans le cas où vous disposeriez de plusieurs projets Prisma sur votre machine.

      Ensuite, vous allez configurer votre base de données PostgreSQL en utilisant Docker. Créez un nouveau fichier Docker Compose avec la commande suivante :

      Maintenant, ajoutez le code suivant au fichier nouvellement créé :

      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:
      

      Ce fichier Docker Compose configure une base de données PostgreSQL qui peut être consultée via le port 5432 du conteneur Docker. Notez également que les informations d’identification de la base de données actuelles sont les suivantes : sammy (utilisateur) et your_password (mot de passe). N’hésitez pas à modifier ces informations d’identification et à utiliser votre nom d’utilisateur et votre mot de passe préférés. Enregistrez et quittez le fichier.

      Une fois cette configuration en place, vous pouvez lancer le serveur de base de données PostgreSQL avec la commande suivante :

      Le résultat de cette commande sera similaire à ce qui suit :

      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

      Vous pouvez vérifier si le serveur de base de données fonctionne avec la commande suivante :

      Vous obtiendrez un résultat similaire à celui-ci :

      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

      Maintenant que le serveur de la base de données est en cours d’exécution, vous pouvez créer votre configuration Prisma. Exécutez la commande suivante depuis la CLI Prisma :

      Vous obtiendrez le résultat suivant :

      Output

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

      Notez que l’une des meilleures pratiques vous recommande de préfixer toutes les invocations de CLI Prisma avec npx. Vous aurez ainsi la certitude que votre installation locale est bien utilisée.

      Une fois la commande exécutée, la CLI Prisma aura créé un nouveau dossier appelé prisma dans votre projet. Il contient les deux fichiers suivants :

      • schema.prisma : le fichier de configuration principal de votre projet Prisma (comprendra votre modèle de données).
      • .env : un fichier dotenv qui définit l’URL de connexion de votre base de données.

      Pour veiller à ce que Prisma connaisse bien l’emplacement de votre base de données, ouvrez le fichier .env et ajustez la variable de l’environnement DATABASE_URL.

      Tout d’abord, ouvrez le fichier .env :

      Maintenant, vous pouvez configurer la variable d’environnement de la manière suivante :

      my-blog/prisma/.env

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

      Veillez à bien remplacer les informations d’identification de la base de données par les données que vous avez spécifiées dans le fichier Docker Compose. Pour en savoir plus sur le format de l’URL de connexion, consultez les docs Prisma.

      Une fois que vous avez terminé, enregistrez et fermez le fichier.

      Au cours de cette étape, vous avez configuré votre base de données PostgreSQL avec Docker, installé la CLI Prisma et connecté Prisma à la base de données via une variable d’environnement. Lors de la section suivante, vous configurerez votre modèle de données et créerez les tableaux de votre base de données.

      Étape 3 — Configuration de votre modèle de données et création des tableaux de base de données

      Au cours de cette étape, vous allez configurer votre data model dans le fichier du schéma Prisma. Ce modèle de données sera ensuite mappé à la base de données avec Prisma Migrate, qui générera et enverra les instructions SQL pour créer les tableaux correspondant à votre modèle de données. Étant donné que vous développez une application de blog, les principales entités de l’application seront les utilisateurs et les publications.

      Prisma utilise son propre langage de modélisation des données pour définir la forme des données de votre application.

      Tout d’abord, ouvrez votre fichier schema.prisma avec la commande suivante :

      • nano prisma/schema.prisma

      Maintenant, ajoutez-y les définitions de modèles suivantes. Vous pouvez placer les modèles au bas du fichier, juste après le bloc generator client :

      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-fr)
        authorId  Int?
      }
      

      Enregistrez et quittez le fichier.

      Vous allez définir deux modèles, que vous nommerez User et Post. Chacun de ces modèles possède un certain nombre de fields qui représentent les propriétés du modèle. Les modèles seront mappés sur les tables de base de données ; les champs représentent les colonnes individuelles.

      Notez également qu’il existe une relation de un à plusieurs entre les deux modèles, spécifiés par les champs de relation posts et author sur User et Post. Cela signifie qu’un utilisateur peut être associé à plusieurs publications.

      Une fois ces modèles en place, vous pouvez maintenant créer les tableaux correspondants dans la base de données en utilisant Prisma Migrate. Sur votre terminal, exécutez la commande suivante :

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

      Cette commande crée une nouvelle migration sur votre système de fichiers. Voici un aperçu rapide des trois options disponibles avec la commande :

      • --experimental : requise car Prisma Migrates indique actuellement un état experimental.
      • --create-db : permet à Prisma Migrate de créer la base de données nommée my-blog qui est spécifiée dans l’URL de connexion.
      • --name "init" : spécifie le nom de la migration (sera utilisé pour nommer le dossier de migration créé sur votre système de fichiers).

      Le résultat de cette commande sera similaire à ce qui suit :

      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-fr) authorId Int? } Prisma Migrate just created your migration 20200811140708-init in migrations/ └─ 20200811140708-init/ └─ steps.json └─ schema.prisma └─ README.md

      N’hésitez pas à explorer les fichiers de migration qui ont été créés dans le répertoire prisma/migrations.

      Pour exécuter la migration par rapport à votre base de données et créer les tableaux pour vos modèles Prisma, exécutez la commande suivante dans votre terminal :

      • npx prisma migrate up --experimental

      Vous obtiendrez le résultat suivant :

      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 génère maintenant les instructions SQL nécessaires à la migration et les envoie à la base de données. Les instructions SQL qui ont créé les tableaux sont les suivantes :

      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
      

      Au cours de cette étape, vous avez défini votre modèle de données dans votre schéma Prisma et créé les tableaux des bases de données correspondants avec Prisma Migrate. À l’étape suivante, vous allez installer Prisma Client dans votre projet afin de pouvoir interroger la base de données.

      Étape 4 — Exploration des requêtes Prisma Client dans un script simple

      Prisma Client est un constructeur de requêtes automatisé de type sécurisé qui vous permet de lire et d’écrire des données dans une base de données depuis une application Node.js ou TypeScript. Vous l’utiliserez pour accéder à la base de données dans vos itinéraires API REST, en remplaçant les ORM traditionnelles, les requêtes SQL simples, les couches d’accès aux données personnalisées ou toute autre méthode d’échange avec une base de données.

      Au cours de cette étape, vous allez installer Prisma Client et vous familiariser avec les requêtes que vous pouvez envoyer. Avant d’implémenter les itinéraires de votre API REST au cours des prochaines étapes, vous allez tout d’abord explorer certaines des requêtes Prisma Client dans un script exécutable simple.

      Premièrement, vous pouvez procéder à l’installation de Prisma Client dans votre projet en ouvrant votre terminal et en installant le paquet npm de Prisma Client :

      • npm install @prisma/client

      Ensuite, créez un nouveau répertoire que vous nommerez src. Il contiendra vos fichiers sources :

      Créez maintenant un fichier TypeScript à l’intérieur du nouveau répertoire :

      Toutes les requêtes de Prisma Client renvoient les promesses auxquelles vous pouvez vous attendre dans votre code. Vous devez donc envoyer les requêtes à l’intérieur d’une fonction async.

      Ajoutez le texte standard suivant avec une fonction async qui s’exécutera dans votre 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())
      

      Voici une rapide décomposition du texte standard :

      1. Importez le constructeur PrismaClient depuis le paquet @prisma/client npm déjà installé.
      2. Instanciez PrismaClient en appelant le constructeur et en obtenant une instance appelée prisma.
      3. Définissez une fonction async que vous appellerez main dans laquelle vous allez ensuite ajouter vos requêtes Prisma Client.
      4. Appelez la fonction main, tout en détectant toute exception potentielle et en vous assurant que Prisma Client ferme toutes les connexions à la base de données ouvertes, en appelant prisma.disconnect().

      Une fois la fonction main en place, vous pouvez commencer à ajouter les requêtes Prisma Client au script. Ajustez index.ts pour que cela ressemble à ce qui suit :

      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())
      

      Dans ce code, vous utilisez deux requêtes Prisma Client :

      • create : crée un nouvel enregistrement User. Notez que, en réalité, vous utilisez une écriture imbriquée, ce qui signifie que vous créez à la fois un enregistrement User et un enregistrement Post dans la même requête.
      • findMany : lit tous les enregistrements User existants depuis la base de données. Vous fournissez l’option include qui charge également les enregistrements de Post correspondants pour chaque enregistrement User.

      Maintenant, exécutez le script avec la commande suivante :

      Vous obtiendrez le résultat suivant dans votre 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 } ] }

      Remarque : si vous utilisez une interface graphique de base de données, vous pouvez valider si les données ont bien été créées en examinant les tableaux User et Post. Vous pouvez également explorer les données dans Prisma Studio en exécutant npx prisma studio --experimental.

      Vous avez maintenant utilisé Prisma Client pour lire et écrire des données dans votre base de données. Au cours des étapes restantes, vous allez appliquer ces nouvelles connaissances pour implémenter les itinéraires dans une API REST échantillon.

      Étape 5 — Implémentation de votre premier itinéraire API REST

      Au cours de cette étape, vous allez installer Express dans votre application. Express est un framework web populaire pour Node.js que vous utiliserez pour implémenter vos itinéraires API REST dans ce projet. Le premier itinéraire que vous allez implémenter vous permettra de récupérer tous les utilisateurs de l’API en utilisant une requête GET. Les données utilisateur seront récupérées depuis la base de données en utilisant Prisma Client.

      Vous pouvez maintenant installer Express avec la commande suivante :

      Étant donné que vous utilisez TypeScript, vous devez également installer les types correspondants en tant que dépendances de développement. Pour cela, exécutez la commande suivante :

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

      Une fois les dépendances installée, vous pouvez configurer votre application Express.

      Commencez par rouvrir votre fichier source principal :

      Maintenant, supprimez l’intégralité du code dans index.ts et remplacez-le par ce qui suit pour lancer votre API REST :

      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'),
      )
      

      Voici une décomposition rapide du code :

      1. Importez PrismaClient et express à partir des paquets npm correspondants.
      2. Instanciez PrismaClient en appelant le constructeur et en obtenant une instance appelée prisma.
      3. Créez votre application Express en appelant express().
      4. Ajoutez le logiciel médiateur express.json() pour avoir la certitude que les données de JSON soient correctement traitées par Express.
      5. Lancez le serveur sur le port 3000.

      Maintenant, vous pouvez implémenter votre premier itinéraire. Entre les appels à app.use et app.listen, ajoutez le code suivant :

      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'),
      )
      

      Une fois ajouté, enregistrez et fermez votre fichier. Ensuite, démarrez votre serveur web local en utilisant la commande suivante :

      Vous recevrez le résultat suivant :

      Output

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

      Pour accéder à l’itinéraire /users, vous pouvez pointer votre navigateur vers http://localhost:3000/users ou tout autre client HTTP.

      Dans ce tutoriel, vous allez tester tous les itinéraire API REST en utilisant curl, un client HTTP basé sur le terminal.

      Note : si vous préférez utiliser un client HTTP basé sur une interface graphique, vous pouvez utiliser des alternatives comme Postwoman ou le Advanced REST Client.

      Pour tester votre itinéraire, ouvrez une nouvelle fenêtre ou un nouveal onglet du terminal (afin que votre serveur web local puisse continuer à fonctionner) et exécutez la commande suivante :

      • curl http://localhost:3000/users

      Vous obtiendrez les données User que vous avez créées au cours de l’étape précédente : 

      Output

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

      Notez que, cette fois, le tableau posts n’est pas inclus, étant donné que vous ne faites pas passer l’option include à l’appel findMany dans l’implémentation de l’itinéraire /users.

      Vous avez implémenté votre premier itinéraire API REST au niveau de /users. Au cours de l’étape suivante, vous allez implémenter les autres itinéraires API REST pour ajouter plus de fonctionnalités à votre API.

      Étape 6 — Implémentation des itinéraires API REST restants

      Au cours de cette étape, vous allez implémenter les autres itinéraires API REST de votre application de blog. À la fin, votre serveur web servira diverses requêtes GET, POST, PUT et DELETE.

      Voici un aperçu des différents itinéraires que vous allez implémenter :

      Méthode HTTPItinéraireDescription
      GET/feedRécupère toutes les publications published.
      GET/post/:idRécupère une publication spécifique en utilisant son ID.
      POST/userCrée un nouvel utilisateur.
      POST/postCrée une nouvelle publication (en tant que draft).
      PUT/post/publish/:idDéfinit le champ published d’une publication comme true.
      DELETEpost/:idSupprime une publication en utilisant son ID.

      Vous pouvez maintenant implémenter le reste des itinéraires Get en premier.

      Ouvrez la commande index.ts avec la commande suivante :

      Ensuite, ajoutez le code suivant une fois l’itinéraire /users  implémenté :

      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'),
      )
      

      Enregistrez et fermez votre fichier

      Ce code implémente les itinéraires API pour deux requêtes GET :

      • /feed : renvoie une liste des posts publiés.
      • /post/:id : renvoie un post spécifique en utilisant son ID.

      Prisma Client est utilisé dans les deux implémentations. Dans l’implémentation de l’itinéraire /feed, la requête que vous envoyez avec Prisma Client filtre pour tous les enregistrements Post pour lesquels la colonne published indique la valeur true. En outre, la requête Prisma Client utilise include pour récupérer les informations liées à l’author pour chaque publication renvoyée. Dans l’implémentation de l’itinéraire /post/:id, faites passer l’ID récupérée depuis le chemin de l’URL afin de lire un enregistrement Post spécifique depuis la base de données.

      Vous pouvez arrêter le serveur en utilisant les touches CTRL+C de votre clavier. Ensuite, redémarrez le serveur en utilisant :

      Pour tester l’itinéraire /feed, vous pouvez utiliser la commande curl suivante :

      • curl http://localhost:3000/feed

      Étant donné qu’aucune publication n’a encore été publiée, la réponse prendra la forme d’un tableau vide :

      Output

      []

      Pour tester l’itinéraire /post/:id, vous pouvez utiliser la commande curl suivante :

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

      Vous obtiendrez la publication que vous avez créée initialement :

      Output

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

      Ensuite, implémentez les deux itinéraires POST. Ajoutez le code suivant à index.ts après les trois itinéraires GET :

      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'),
      )
      

      Une fois que vous avez terminé, enregistrez et fermez le fichier.

      Ce code implémente les itinéraires API pour deux requêtes POST :

      • /user : crée un nouvel utilisateur dans la base de données.
      • /post : crée une nouvelle publication dans la base de données.

      Comme auparavant, Prisma Client est utilisé dans les deux implémentations. Dans le cadre de l’implémentation de l’itinéraire /user, vous faites passer les valeurs depuis le corps de la requête HTTP à la requête create de Prisma Client.

      L’itinéraire /post exige un peu plus d’implication. Ici, vous ne pouvez pas faire passer les valeurs directement depuis le corps de la requête HTTP. Au contraire, vous devez d’abord les extraire manuellement afin de les transmettre à la requête Prisma Client. En effet, étant donné que la structure de JSON dans le corps de requête ne correspond pas à la structure attendue par Prisma Client. Vous devez donc créer la structure attendue manuellement.

      Vous pouvez tester les nouveaux itinéraires en arrêtant le serveur avec CTRL+C. Ensuite, redémarrez le serveur en utilisant :

      Pour créer un nouvel utilisateur via l’itinéraire /user, vous pouvez envoyer la requête POST suivante avec curl :

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

      Cela créera un nouvel utilisateur dans la base de données, en donnant le résultat suivant :

      Output

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

      Pour créer une nouvelle publication via l’itinéraire /post, vous pouvez envoyer la requête POST suivante avec curl :

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

      Cela créera une nouvelle publication dans la base de données et la connectera à l’utilisateur avec le courriel [email protected]. Cela donne le résultat suivant :

      Output

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

      Enfin, vous pouvez implémenter les itinéraires PUT et DELETE.

      Ouvrez la commande index.ts avec la commande suivante :

      Ensuite, une fois les deux itinéraires POST implémentés, ajoutez le code surligné :

      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'),
      )
      

      Enregistrez et fermez votre fichier

      Ce code implémente les itinéraires API pour une requête PUT et une requête DELETE :

      • /post/publish/:id (PUT) : publie une publication en utilisant son ID.
      • /post/:id (DELETE) : supprime une publication en utilisant son ID.

      À nouveau, Prisma Client est utilisé dans les deux implémentations. Dans le cadre de l’implémentation de l’itinéraire /post/publish/:id, l’ID du message à publier est récupéré depuis l’URL et transmis à la requête update de Prisma Client. L’implémentation de l’itinéraire /post/:id qui permet de supprimer une publication dans la base de données renvoie également l’ID de l’URL et le transmet à la requête delete de Prisma Client.

      Encore une fois, arrêtez le serveur à l’aide des touches CTRL+C de votre clavier. Ensuite, redémarrez le serveur en utilisant :

      Vous pouvez tester l’itinéraire PUT avec la commande curl suivante :

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

      Cela vous permettra de publier la publication avec une valeur d’ID de 2. Si vous renvoyez la requête /feed, cette publication sera alors incluse dans la réponse.

      Enfin, vous pouvez tester l’itinéraire DELETE avec la commande curl suivante :

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

      Cela vous permettra de supprimer la publication avec une valeur d’ID de 1. Pour valider le fait que la publication portant cet ID ait été supprimée, vous pouvez renvoyer une requête GET à l’itinéraire /post/1.

      Au cours de cette étape, vous avez implémenté les autres itinéraires API REST de votre application de blog. L’API répond maintenant aux diverses requêtes GET, POST, PUT et DELETE et implémente une fonctionnalité pour lire et écrire des données dans la base de données.

      Conclusion

      Au cours de cet article, vous avez créé un serveur API REST avec plusieurs itinéraires différents pour créer, lire, mettre à jour et supprimer les données utilisateur et de publications pour une application de blog échantillon. À l’intérieur des itinéraires de l’API, vous utilisez le Prisma Client pour envoyer les requêtes correspondantes à votre base de données.

      Ensuite, vous pouvez implémenter des itinéraires API supplémentaires ou étendre le schéma de votre base de données en utilisant Prisma Migrate. Veillez à consulter la documentation de Prisma pour en savoir plus sur les divers aspects de Prisma et à explorer quelques exemples de projets prêts à l’exécution dans le référentiel prisma-examples – en utilisant des outils comme les API GraphQL ou grPC.



      Source link

      Como construir uma API REST com o Prisma e o PostgreSQL


      O autor selecionou a Diversity in Tech Fund​​​​​ para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O Prisma é um conjunto de ferramentas para banco de dados de código aberto. Ele consiste em três ferramentas principais:

      • Prisma Client: um construtor de consultas gerado automaticamente e fortemente tipado para o Node.js e o TypeScript.
      • Prisma Migrate: um sistema declarativo de modelagem e migração de dados.
      • Prisma Studio: uma GUI para visualizar e editar dados em seu banco de dados

      Essas ferramentas visam aumentar a produtividade de um desenvolvedor de aplicativos em seu fluxo de trabalho com banco de dados. Um dos principais benefícios do Prisma é o nível de abstração que ele fornece: em vez de lidar com consultas SQL ou migrações de esquema complexas, os desenvolvedores de aplicativos podem trabalhar com seus dados de uma maneira mais intuitiva usando o Prisma para trabalhar com seus bancos de dados.

      Neste tutorial, você irá construir uma API REST para um pequeno aplicativo de blog no TypeScript usando o Prisma e um banco de dados PostgreSQL. Você irá configurar seu banco de dados PostgreSQL localmente com o Docker e implementar as rotas da API REST usando o Express. No final do tutorial, você terá um servidor Web sendo executado localmente em sua máquina que pode responder a vários pedidos HTTP, além de ler e escrever dados no banco de dados

      Pré-requisitos

      Este tutorial assume o seguinte:

      Possuir uma familiaridade básica com o TypeScript e as APIs REST é útil, mas não é obrigatório para este tutorial.

      Passo 1 — Criando seu projeto do TypeScript

      Neste passo, você irá configurar um projeto simples do TypeScript usando o npm. Esse projeto servirá como fundação para a API REST que você irá construir ao longo deste tutorial.

      Primeiramente, crie um novo diretório para o seu projeto:

      Em seguida, navegue até o diretório e inicialize um projeto vazio do npm. Observe que a opção -y presente aqui significa que os prompts interativos do comando estão sendo ignorados. Para que os prompts sejam executados, remova o -y do comando:

      Para mais detalhes sobre esses prompts, siga o Passo 1 em Como usar os módulos do Node.js com o npm e o package.json.

      Você receberá um resultado semelhante ao seguinte, com as respostas padrão sendo utilizadas:

      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" }

      Esse comando cria um arquivo package.json mínimo que você usa como o arquivo de configuração para o seu projeto do npm. Agora, você está pronto para configurar o TypeScript em seu projeto.

      Execute o comando a seguir para uma configuração simples do TypeScript:

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

      Isso instala três pacotes como dependências de desenvolvimento em seu projeto:

      • typescript: a cadeia de ferramentas do TypeScript.
      • ts-node: um pacote para executar aplicativos do TypeScript sem compilação prévia para JavaScript.
      • @types/node: as definições de tipo do TypeScript para o Node.js.

      A última coisa a ser feita é adicionar um arquivo tsconfig.json para garantir que o TypeScript esteja configurado corretamente para o aplicativo que você irá compilar.

      Primeiramente, execute o comando a seguir para criar o arquivo:

      Adicione o seguinte código JSON ao arquivo:

      my-blog/tsconfig.json

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

      Salve e saia do arquivo.

      Essa é uma configuração padrão e mínima para um projeto do TypeScript. Se quiser aprender sobre as propriedades individuais do arquivo de configuração, procure por elas na documentação do TypeScript.

      Você configurou seu projeto simples do TypeScript usando o npm. Em seguida, irá configurar seu banco de dados do PostgreSQL com o Docker e conectar o Prisma a ele.

      Passo 2 — Configurando o Prisma com o PostgreSQL

      Neste passo, você irá instalar o Prisma CLI, criar seu arquivo de esquema do Prisma inicial, configurar o PostgreSQL com o Docker e conectar o Prisma a ele. O esquema do Prisma é o arquivo de configuração principal para sua configuração do Prisma e contém o esquema do seu banco de dados.

      Comece instalando o Prisma CLI com o seguinte comando:

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

      Como prática recomendada, aconselha-se instalar o Prisma CLI localmente em seu projeto (ao invés de uma instalação global). Isso ajuda a evitar conflitos de versão caso você tenha mais de um projeto Prisma em sua máquina.

      Em seguida, você irá configurar seu banco de dados do PostgreSQL usando o Docker. Crie um novo arquivo do Docker Compose com o seguinte comando:

      Agora, adicione o código a seguir ao arquivo recém-criado:

      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:
      

      Esse arquivo do Docker Compose configura um banco de dados do PostgreSQL que pode ser acessado pela porta 5432 do contêiner do Docker. Observe também que as credenciais do banco de dados estão atualmente definidas como sammy (usuário) e your_password (senha). Sinta-se livre para alterar essas credenciais para o usuário e senha de sua escolha. Salve e saia do arquivo.

      Com essa configuração ajustada, inicie o servidor do banco de dados PostgreSQL com o seguinte comando:

      O resultado deste comando será semelhante a este:

      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

      Verifique se o banco de dados está sendo executado com o seguinte comando:

      Isso irá gerar um resultado semelhante a este:

      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

      Com o servidor do banco de dados em execução, crie agora sua configuração do Prisma. Execute o comando a seguir a partir do Prisma CLI:

      Isso imprimirá o seguinte resultado:

      Output

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

      Observe que como uma prática recomendada, aconselha-se prefixar todas as invocações do Prisma CLI com o npx. Isso garante que sua instalação local esteja sendo usada.

      Depois de executar o comando, o Prisma CLI criou uma nova pasta chamada prisma em seu projeto. Ela contém os dois arquivos a seguir:

      • schema.prisma: o arquivo de configuração principal para o seu projeto Prisma (incluirá o seu modelo de dados).
      • .env: um arquivo dotenv para definir a URL de conexão do seu banco de dados.

      Para garantir que o Prisma saiba a localização do seu banco de dados, abra o arquivo .env e ajuste a variável de ambiente DATABASE_URL.

      Primeiro, abra o arquivo .env:

      Agora, defina a variável de ambiente da seguinte forma:

      my-blog/prisma/.env

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

      Certifique-se de substituir as credenciais do banco de dados por aquelas que você especificou no arquivo do Docker Compose. Para aprender mais sobre o formato da conexão de URL, visite os documentos do Prisma.

      Assim que terminar, salve e feche o arquivo.

      Neste passo, você configurou seu banco de dados do PostgreSQL de dados com o Docker, instalou o Prisma CLI e conectou o Prisma ao banco de dados através de uma variável de ambiente. Na próxima seção, você irá definir seu modelo de dados e criar as tabelas do seu banco de dados.

      Passo 3 — Definindo seu modelo de dados e criando tabelas de banco de dados

      Neste passo, você irá definir seu modelo de dados no arquivo do esquema do Prisma. Esse modelo de dados será então mapeado para o banco de dados com o Prisma Migrate, que irá gerar e enviar as instruções SQL para criar as tabelas que correspondem ao seu modelo de dados. Como você está criando um aplicativo de blog, as principais entidades do aplicativo serão usuários e postagens.

      O Prisma usa sua própria linguagem de modelagem de dados para definir a forma dos dados do seu aplicativo.

      Primeiro, abra seu arquivo schema.prisma com o seguinte comando:

      • nano prisma/schema.prisma

      Agora, adicione as seguintes definições de modelo a ele. Coloque os modelos no final do arquivo, logo após o bloco generator client:

      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-pt)
        authorId  Int?
      }
      

      Salve e saia do arquivo.

      Você está definindo dois modelos, chamados User e Post. Cada um deles tem um número de campos que representam as propriedades do modelo. Os modelos serão mapeados para as tabelas do banco de dados; os campos representam as colunas individuais.

      Observe também que existe uma relação de uma para muitos entre os dois modelos, especificada pelos campos de relação posts e author em User e Post. Isso significa que um usuário pode estar associado a muitas postagens.

      Com esses modelos posicionados, crie agora as tabelas correspondentes no banco de dados usando o Prisma Migrate. No seu terminal, execute o seguinte comando:

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

      Esse comando cria uma nova migração em seu sistema de arquivos Aqui está uma visão geral resumida das três opções que são fornecidas ao comando:

      • --experimental: é necessário porque o Prisma Migrate está atualmente em um estado experimental.
      • --create-db: permite que o Prisma Migrate crie o banco de dados chamado my-blog que é especificado na URL de conexão.
      • --name "init": especifica o nome da migração (será usado para nomear a pasta de migração que será criada em seu sistema de arquivos).

      O resultado deste comando será semelhante a este:

      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-pt) authorId Int? } Prisma Migrate just created your migration 20200811140708-init in migrations/ └─ 20200811140708-init/ └─ steps.json └─ schema.prisma └─ README.md

      Sinta-se à vontade para explorar os arquivos de migração que foram criados no diretório prisma/migrations.

      Para executar a migração em seu banco de dados e criar as tabelas para seus modelos do Prisma, execute o seguinte comando em seu terminal:

      • npx prisma migrate up --experimental

      Você receberá o seguinte resultado:

      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.

      O Prisma Migrate agora gera as declarações SQL que são necessárias para a migração e as envia para o banco de dados. Vê-se a seguir as instruções SQL que criaram as tabelas:

      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
      

      Neste passo, você definiu seu modelo de dados em seu esquema do Prisma e criou as respectivas tabelas de bancos de dados com o Prisma Migrate. No próximo passo, você irá instalar o Prisma Client em seu projeto para que seja possível consultar o banco de dados.

      Passo 4 — Explorando as consultas do Prisma Client em um script simples

      O Prisma Client é um construtor de consultas gerado automaticamente e fortemente tipado que pode ser usado para ler e escrever dados programaticamente em um banco de dados a partir de um aplicativo Node.js ou TypeScript. Você irá usá-lo para ter acesso ao banco de dados em suas rotas da API REST, substituindo as ORMs tradicionais, consultas SQL simples, camadas de acesso de dados personalizadas, ou qualquer outro método de comunicação com um banco de dados.

      Neste passo, você irá instalar o Prisma Client e familiarizar-se com as consultas que podem ser enviadas com ela. Antes de implementar as rotas para sua API REST nos próximos passos, primeiro irá explorar algumas das consultas do Prisma Client em um script simples e executável.

      Primeiro, instale o Prisma Client em seu projeto abrindo seu terminal e instalando o pacote npm do Prisma Client:

      • npm install @prisma/client

      Em seguida, crie um novo diretório chamado src que irá conter seus arquivos de origem:

      Agora, crie um arquivo do TypeScript dentro do novo diretório:

      Todas as consultas do Prisma Client retornam promessas que você pode await (aguardar) em seu código. Isso requer que você envie as consultas dentro de uma função async (assíncrona).

      Adicione o seguinte texto clichê com uma função async a ser executada em seu 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())
      

      Aqui está um rápido detalhamento do código boilerplate.

      1. Você importa o construtor PrismaClient do pacote npm @prisma/client previamente instalado.
      2. Você instancia o PrismaClient chamando o construtor e obtém uma instância chamada prisma.
      3. Você define uma função async chamada main onde irá adicionar suas consultas do Prisma Client a seguir.
      4. Você chama a função main, enquanto captura todas as exceções em potencial e certifica-se de que o Prisma Client feche todas as conexões do banco de dados abertas chamando o prisma.disconnect().

      Com a função main no lugar, comece a adicionar as consultas do Prisma Client ao script. Ajuste o index.ts para que fique parecido com o seguinte:

      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())
      

      Neste código, duas consultas do Prisma Client estão sendo usadas:

      • create: cria um novo registro de User. Observe que você está usando na verdade um texto aninhado, o que significa que um registro de User e Post estão sendo criados na mesma consulta.
      • findMany: lê todos os registros de User existentes no banco de dados Você está fornecendo a opção include que carrega também os registros de Post relacionados para cada registro de User.

      Agora, execute o script com o seguinte comando:

      Você verá o seguinte resultado em seu 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 } ] }

      Nota: se estiver usando a GUI de um banco de dados, é possível confirmar que os dados foram criados olhando nas tabelas User e Post. De maneira alternativa, você pode explorar os dados do Prisma Studio executando npx prisma studio --experimental.

      Até aqui, você usou o Prisma Client para ler e escrever dados em seu banco de dados. Nos passos restantes, você irá aplicar esse novo conhecimento para implementar as rotas para uma API REST amostral.

      Passo 5 — Implementando sua primeira rota da API REST

      Neste passo, você irá instalar o Express em seu aplicativo. O Express é um framework Web popular para o Node.js que será usado para implementar as rotas da sua API REST neste projeto. A primeira rota a ser implementada lhe permitirá buscar todos os usuários da API usando uma solicitação GET. Os dados do usuário serão recuperados do banco de dados usando o Prisma Client.

      Vá em frente e instale o Express com o seguinte comando:

      Como você está usando TypeScript, também será necessário instalar os respectivos tipos como dependências de desenvolvimento. Execute o comando a seguir para fazer isso:

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

      Com as dependências no lugar, configure agora sua aplicação Express.

      Comece abrindo seu arquivo de código de origem principal novamente:

      Agora, exclua todo o código em index.ts e substitua-o pelo seguinte, de forma a iniciar sua API REST:

      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'),
      )
      

      Aqui está um rápido detalhamento do código:

      1. Você importa o PrismaClient e o express dos respectivos pacotes npm.
      2. Você instancia o PrismaClient chamando o construtor e obtém uma instância chamada prisma.
      3. Você cria seu aplicativo Express chamando o express().
      4. Você adiciona o middleware express.json() para garantir que os dados JSON sejam processados corretamente pelo Express.
      5. Você inicia o servidor na porta 3000.

      Agora, implemente sua primeira rota. Adicione o seguinte código entre as chamadas para app.use e app.listen:

      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'),
      )
      

      Depois de adicionado, salve e saia do seu arquivo. Em seguida, inicie seu servidor Web local usando o seguinte comando:

      Você receberá o seguinte resultado:

      Output

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

      Para acessar a rota /users, aponte seu navegador para http://localhost:3000/users ou qualquer outro cliente HTTP.

      Neste tutorial, você irá testar todas as rotas da API REST usando o curl, um cliente HTTP baseado em terminal.

      Nota: se preferir usar um cliente HTTP baseado em GUI, pode usar o Postwoman ou o Advanced REST Client.

      Para testar sua rota, abra uma nova janela ou guia de terminal (para que o seu servidor Web local continue sendo executado) e execute o seguinte comando:

      • curl http://localhost:3000/users

      Você receberá os dados de User que você criou no passo anterior:

      Output

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

      Observe que a matriz posts não foi incluída desta vez. Isso ocorre porque a opção include não está sendo passada para a chamada findMany na implementação da rota /users.

      Você implementou sua primeira rota da API REST em /users. No próximo passo, você irá implementar as rotas restantes da API REST para adicionar mais funcionalidade à sua API.

      Passo 6 — Implementando as rotas restantes da API REST

      Neste passo, você irá implementar as rotas restantes da API REST para seu aplicativo de blog. No final, seu servidor Web irá atender diversas solicitações GET, POST, PUT, e DELETE.

      Aqui está uma visão geral das diferentes rotas que serão implementadas:

      Método HTTPRotaDescrição
      GET/feedBusca todos os posts publicados.
      GET/post/:idBusca um post específico com base em seu ID.
      POST/userCria um novo usuário.
      POST/postCria um novo post (como um rascunho).
      PUT/post/publish/:idDefine o campo published (publicado) de um post como true (verdadeiro).
      DELETEpost/:idExclui um post por seu ID.

      Vá em frente e implemente as rotas GET restantes primeiro.

      Abra o index.ts com o seguinte comando:

      Em seguida, adicione o código a seguir após a implementação da rota /users:

      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'),
      )
      

      Salve e saia do seu arquivo.

      Esse código implementa as rotas API para duas solicitações GET:

      • /feed: retorna uma lista de posts publicados.
      • /post/:id: retorna um post específico por seu ID.

      O Prisma Client é usado em ambas as implementações. Na implementação de rota /feed, a consulta enviada com o Prisma Client filtra por todos os registros de Post onde a coluna published contém o valor true. Além disso, a consulta do Prisma Client usa include (incluir) para também buscar as informações de author relacionadas para cada post retornado. Na implementação de rota /post/:id, o ID que é recuperado do caminho do URL é passado para ler um registro de Post específico do banco de dados.

      Você pode interromper o servidor apertando CTRL+C em seu teclado. Em seguida, reinicie o servidor usando:

      Para testar a rota /feed, use o seguinte comando curl:

      • curl http://localhost:3000/feed

      Como nenhum post ainda foi publicado, a resposta é uma matriz vazia:

      Output

      []

      Para testar a rota /post/:id, use o seguinte comando curl:

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

      Isso irá retornar o post que você criou inicialmente:

      Output

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

      Em seguida, implemente as duas rotas POST. Adicione o código a seguir em index.ts após as implementações das três rotas GET:

      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'),
      )
      

      Assim que terminar, salve e feche o arquivo.

      Esse código implementa as rotas API para duas solicitações POST:

      • /user: cria um novo usuário no banco de dados.
      • /post: cria um novo post no banco de dados.

      Assim como antes, o Prisma Client é usado em ambas as implementações. Na implementação de rota /user, são passados os valores do corpo da solicitação HTTP para a consulta create do Prisma Client.

      A rota /post é um pouco mais confusa: aqui não é possível passar diretamente os valores do corpo da solicitação HTTP; em vez disso, é necessário primeiro extraí-los manualmente para passá-los para a consulta do Prisma Client. A razão por trás disso é que a estrutura do JSON no corpo da solicitação não corresponde à estrutura esperada pelo Prisma Client. Sendo assim, é necessário criar manualmente a estrutura esperada.

      Você pode testar as novas rotas interrompendo o servidor com CTRL+C. Em seguida, reinicie o servidor usando:

      Para criar um novo usuário com a rota /user, envie a seguinte solicitação POST com o o curl:

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

      Isso irá criar um novo usuário no banco de dados, imprimindo o seguinte resultado:

      Output

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

      Para criar um novo post através da rota /post, envie a seguinte solicitação POST com o curl:

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

      Isso irá criar um novo post no banco de dados e conectá-lo ao usuário com e-mail [email protected]. O seguinte resultado será impresso:

      Output

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

      Por fim, é possível implementar as rotas PUT e DELETE.

      Abra o index.ts com o seguinte comando:

      Em seguida, adicione o código destacado após a implementação das duas rotas POST:

      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'),
      )
      

      Salve e saia do seu arquivo.

      Esse código implementa as rotas API para uma solicitação PUT e uma DELETE:

      • /post/publish/:id (PUT): publica um post por seu ID.
      • /post/:id (DELETE): exclui um post por seu ID.

      Novamente, o Prisma Client é usado em ambas as implementações. Na implementação de rota /post/publish/:id, o ID do post a ser publicado é recuperado da URL e passado para a consulta update do Prisma Client. A implementação da rota /post/:id para excluir um post no banco de dados também recupera o ID do post da URL e o passa para a consulta delete do Prisma Client.

      Novamente, interrompa o servidor com CTRL+C em seu teclado. Em seguida, reinicie o servidor usando:

      Teste a rota PUT com o seguinte comando curl:

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

      Isso irá publicar o post com um valor de ID de 2. Se você reenviar a solicitação /feed, esse post será agora incluído na resposta.

      Por fim, teste a rota DELETE com o seguinte comando curl:

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

      Isso irá excluir o post com um valor de ID de 1. Para confirmar se o post com este ID foi excluído, reenvie uma solicitação GET para a rota /post/1.

      Neste passo, você implementou as rotas restantes da API REST para seu aplicativo de blog. A API agora responde a várias solicitações GET, POST, PUT e DELETE e implementa funcionalidades para ler e escrever dados no banco de dados.

      Conclusão

      Neste artigo, você criou um servidor da API REST com uma série de rotas distintas para criar, ler, atualizar e excluir dados de usuários e posts para um aplicativo de blog amostral. Dentro das rotas da API, você usou o Prisma Client para enviar as respectivas consultas para seu banco de dados.

      Como passos adicionais, você pode implementar rotas de API adicionais ou estender seu esquema de banco de dados com o Prisma Migrate. Certifique-se de visitar a documentação do Prisma para aprender sobre os diferentes aspectos do Prisma e explorar alguns exemplos de projetos prontos para serem executados no repositório prisma-examples. Por exemplo, como usar ferramentas como o GraphQL ou o grPC APIs.



      Source link

      Создание REST API с помощью Prisma и PostgreSQL


      Автор выбрал Diversity in Tech Fund для получения пожертвования в рамках программы Write for DOnations.

      Введение

      Prisma — это набор инструментов для работы с базой данных с открытым исходным кодом. Он включает три основных инструмента:

      • Prisma Client: конструктор автоматически генерируемых типобезопасных запросов для Node.js и TypeScript.
      • Prisma Migrate: система моделирования данных и миграции, поддерживающая декларативный подход.
      • Prisma Studio: графический пользовательский интерфейс для просмотра и редактирования данных в вашей базе данных.

      Эти инструменты направлены на повышение производительности разработчика приложения при работе с базой данных. Одним из главных преимуществ Prisma является уровень абстракции, который она предоставляет: вместо формирования сложных SQL запросов или миграций схемы БД, разработчики приложения могут рассуждать о своих данных более интуитивно понятным образом, используя Prisma для работы с базой данных.

      В этом обучающем руководстве мы напишем REST API для небольшого приложения для ведения блога на TypeScript с помощью Prisma и базы данных PostgreSQL. Вы настроите локальную базу данных PostgreSQL с помощью Docker и реализуете маршруты REST API с помощью Express. После выполнения руководства у вас будет работающий на вашем локальном компьютере веб-сервер, который будет отвечать на различные HTTP запросы, а также выполнять чтение и запись в базу данных.

      Предварительные требования

      Для выполнения инструкций данного руководства требуется следующее:

      Базовое знакомство с TypeScript и REST API будет полезно, но не обязательно для выполнения данного руководства.

      Шаг 1 — Создание проекта TypeScript

      В этом шаге мы настроим простой проект TypeScript с помощью npm. Этот проект послужит основой для REST API, который вы будете создавать при выполнении данного руководства.

      Во-первых, создайте новый каталог для вашего проекта:

      Затем перейдите в этот каталог и инициализируйте создание пустого проекта npm. Обратите внимание, что опция -y здесь означает, что вы хотите пропустить интерактивные запросы команды. Чтобы просмотреть запросы, удалите -y из команды:

      Дополнительную информацию об этих запросах вы можете найти в шаге 1 руководства Использование модулей Node.js с npm и package.json.

      Вы получите примерно следующий вывод с ответами по умолчанию:

      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" }

      Эта команда создает файл package.json с минимальным содержанием, который вы будете использовать в качестве файла конфигурации для вашего проекта npm. Теперь вы готовы к настройке TypeScript в вашем проекте.

      Выполните следующую команду для простой настройки TypeScript:

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

      Эта команда устанавливает три пакета в качестве зависимостей разработки в вашем проекте:

      • typescript: набор инструментов TypeScript.
      • ts-node: пакет для запуска приложений TypeScript без предварительной компиляции в JavaScript.
      • @types/node: определения типов TypeScript для Node.js.

      В качестве последнего шага необходимо добавить файл tsconfig.json, чтобы гарантировать корректность настройки TypeScript для приложения, которое вы будете создавать.

      Сначала запустите следующую команду для создания файла:

      Добавьте в файл следующий код JSON:

      my-blog/tsconfig.json

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

      Сохраните и закройте файл.

      Это стандартная и минимальная конфигурация для проекта TypeScript. Если вы хотите узнать об отдельных свойствах файла конфигурации, всю необходимую информацию вы можете найти в документации TypeScript.

      Вы настроили простой проект TypeScript с помощью npm. После этого вы должны будете настроить свою базу данных PostgreSQL с помощью Docker и подключить Prisma к этой базе данных.

      Шаг 2 — Настройка Prisma с PostgreSQL

      В этом шаге мы установим Prisma CLI, создадим первоначальный файл схемы Prisma и настроим PostgreSQL с помощью Docker, после чего нужно будет подключить ее к Prisma. Схема Prisma — это основной файл конфигурации для настройки Prisma, который содержит схему вашей базы данных.

      Начните с установки Prisma CLI, воспользовавшись следующей командой:

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

      Рекомендуется использовать локальную установку Prisma CLI для вашего проекта (а не глобальную установку). Это помогает избежать конфликтов версий при наличии нескольких проектов Prisma на вашем компьютере.

      Далее вам нужно настроить вашу базу данных PostgreSQL с помощью Docker. Создайте новый файл Docker Compose с помощью следующей команды:

      Добавьте следующий код во вновь созданный файл:

      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:
      

      Данный файл Docker Compose настраивает базу данных PostgreSQL, доступ к которой можно получить через порт 5432 контейнера Docker. Обратите внимание, что в настоящее время для базы данных установлены следующие учетные данные: sammy (пользователь) и your_password (пароль). Вы можете изменить эти учетные данные и указать предпочитаемые имя пользователя и пароль. Сохраните и закройте файл.

      После выполнения этих действий вы можете перейти к запуску сервера базы данных PostgreSQL с помощью следующей команды:

      Вывод этой команды будет выглядеть примерно следующим образом:

      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

      Вы можете проверить, работает ли сервер базы данных, воспользовавшись следующей командой:

      Вы получите примерно следующий вывод:

      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

      После запуска сервера базы данных вы сможете создать вашу настройку Prisma. Запустите следующую команду в Prisma CLI:

      Результат будет выглядеть следующим образом:

      Output

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

      Обратите внимание, что рекомендуется использовать префикс npx в каждом вызове Prisma CLI. Это гарантирует, что будет использоваться именно локальная установка клиента.

      После запуска команды Prisma CLI создает новую папку с именем prisma в вашем проекте. Она содержит два следующих файла:

      • schema.prisma: главный файл конфигурации для вашего проекта Prisma (он будет включать вашу модель данных).
      • .env: файл dotenv для определения URL-адреса для подключения к базе данных.

      Чтобы гарантировать, что Prisma будет знать расположение вашей базы данных, откройте файл .env и измените значение переменной среды DATABASE_URL.

      Сначала откройте файл .env:

      Теперь вы можете задать значение переменной среды следующим образом:

      my-blog/prisma/.env

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

      Убедитесь, что вы можете изменить учетные данные для БД на данные, указанные в файле Docker Compose. Дополнительную информацию о формате URL-адреса подключения см. в документации Prisma.

      После выполнения этих действий сохраните и закройте файл.

      В этом шаге вы настроили свою базу данных PostgreSQL с помощью Docker, установили Prisma CLI и подключили Prisma к базе данных с помощью переменной среды. В следующем разделе вы определите модель данных и создадите таблицы вашей базы данных.

      Шаг 3 — Определение модели данных и создание таблиц базы данных

      В этом шаге вы определите вашу модель данных в файле схемы Prisma. Эта модель данных затем будет перенесена на базу данных с помощью Prisma Migrate, которая будет генерировать и отправлять SQL инструкции для создания таблиц, соответствующих вашей модели данных. Поскольку вы создаете приложение для ведения блога, основными сущностями приложения будут пользователи и посты.

      Prisma использует свой собственный язык моделирования данных для определения формы данных вашего приложения.

      Сначала откройте файл schema.prisma с помощью следующей команды:

      • nano prisma/schema.prisma

      Теперь добавьте в файл следующие определения модели. Вы можете поместить модели в нижней части файла сразу после блока generator client:

      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-ru)
        authorId  Int?
      }
      

      Сохраните и закройте файл.

      Вы определяете две модели: User и Post. Каждая из этих моделей имеет ряд полей, которые представляют свойства модели. Модели будут отображаться в таблицах базы данных, а поля представляют отдельные столбцы.

      Обратите внимание на связь один-ко-многим между двумя моделями, определяемую связанными полями posts и author в таблицах User и Post. Это означает, что один пользователь может быть связан с несколькими постами.

      После получения этих моделей вы можете создать соответствующие таблицы в базе данных с помощью Prisma Migrate. В терминале запустите следующую команду:

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

      Эта команда создает новую миграцию в вашей файловой системе. Ниже приводится краткое описание трех опций, предоставляемых командой:

      • --experimental: обязательная опция, поскольку Prisma Migrate находится в настоящее время в экспериментальном состоянии.
      • --create-db: дает Prisma Migrate возможность создать базу данных с именем my-blog, которое указано в URL-адресе подключения.
      • --name "init": указывает имя миграции (будет использоваться при присвоении имени папке миграции, создаваемой в вашей файловой системе).

      Вывод этой команды будет выглядеть примерно следующим образом:

      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-ru) authorId Int? } Prisma Migrate just created your migration 20200811140708-init in migrations/ └─ 20200811140708-init/ └─ steps.json └─ schema.prisma └─ README.md

      Вы можете ознакомиться с созданными миграционными файлами в каталоге prisma/migrations.

      Чтобы запустить миграцию для вашей базы данных и создать таблицы для ваших моделей Prisma, запустите следующую команду в терминале:

      • npx prisma migrate up --experimental

      Вывод должен выглядеть следующим образом:

      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 генерирует инструкции SQL, необходимые для выполнения миграции, и отправляет их базе данных. Ниже приводятся SQL инструкции, которые создают таблицы:

      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
      

      В этом шаге вы определили вашу модель данных в схеме Prisma и создали соответствующие таблицы базы данных с помощью Prisma Migrate. В следующем шаге вы установите Prisma Client для вашего проекта, чтобы вы могли отправлять запросы базе данных.

      Шаг 4 — Знакомство с запросами Prisma Client в форме простого скрипта

      Prisma Client — это инструмент для автоматической генерации типобезопасных запросов, который вы можете использовать для программного чтения и записи данных в базу данных в приложении на базе Node.js или TypeScript. Вы будете использовать его для доступа к базе данных в рамках ваших маршрутов REST API в качестве замены для традиционных ORM, простых запросов SQL, собственных слоев доступа к данным или любого другого метода работы с базой данных.

      В этом шаге вы установите Prisma Client и познакомитесь с запросами, которые он позволяет отправлять. Прежде чем реализовать маршруты для вашего REST API в следующих шагах, вы должны будете познакомиться с запросами Prisma Client в форме простого исполняемого скрипта.

      Перейдите к установке Prisma Client для вашего проекта, открыв терминал и установив пакет npm Prisma Client:

      • npm install @prisma/client

      Затем создайте новый каталог с именем src, который будет содержать исходные файлы:

      Теперь создайте файл TypeScript внутри нового каталога:

      Все запросы Prisma Client возвращают промисы, которые вы можете ожидать в своем коде. Поэтому вы должны отправлять запросы внутри асинхронной функции.

      Добавьте следующий шаблонный код с асинхронной функцией, выполняемой в вашем скрипте:

      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())
      

      Ниже приводится короткое пояснения шаблонного кода:

      1. Импорт конструктора PrismaClient из ранее установленного пакета npm @prisma/client.
      2. Создание объекта PrismaClient с помощью вызова конструктора и получения экземпляра с именем prisma.
      3. Определение асинхронной функции с именем main, куда вы позже будете добавлять запросы Prisma Client.
      4. Вызов функции main вместе с перехватом любых возможных исключений, а также гарантия того, что Prisma Client будет закрывать все открытые подключения к базе данных с помощью вызова prisma.disconnect().

      Получив в распоряжение функцию main, вы можете начинать добавлять запросы Prisma Client в скрипт. Измените содержание файла index.ts, которое должно выглядеть следующим образом:

      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())
      

      В этом коде вы используете два запроса Prisma Client:

      • create: создает новую запись User. Обратите внимание, что вы используете вложенную запись, что означает, что вы создаете записи User и Post в одном запросе.
      • findMany: считывает все существующие записи User из базы данных. Вы указываете опцию include, которая дополнительно загружает связанные записи Post для каждой записи User.

      Теперь запустите скрипт с помощью следующей команды:

      В терминале вы получили следующий вывод:

      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 } ] }

      Примечание: если вы используете графический пользовательский интерфейс для базы данных, то сможете проверить, были ли созданы записи, посмотрев таблицы User и Post. Также вы можете просмотреть данные с помощью Prisma Studio, запустив команду npx prisma studio --experimental.

      Вы успешно воспользовались Prisma Client для чтения и записи данных в вашей базе данных. В оставшихся шагах вы будете применять эти новые знания для реализации маршрутов на образце REST API.

      Шаг 5 — Реализация вашего первого маршрута REST API

      В этом шаге вы установите Express для вашего приложения. Express — это популярный веб-фреймворк для Node.js, который вы будете использовать для имплементации ваших маршрутов REST API в рамках данного проекта. Первый маршрут, который вы будете реализовать, позволит вам получить всех пользователей из API с помощью запроса GET. Данные пользователя будут получены из базы данных с помощью Prisma Client.

      Начните с установки Express с помощью следующей команды:

      Поскольку вы используете TypeScript, вам также нужно будет установить соответствующие типы в качестве зависимостей разработки. Для этого запустите следующую команду:

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

      После получения зависимостей вы можете перейти к настройке вашего приложения Express.

      Начните с открытия вашего главного исходного файла еще раз:

      Теперь удалите весь код в файле index.ts и замените его на следующий код для запуска вашего 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'),
      )
      

      Ниже приводится краткое описание элементов кода:

      1. Импорт PrismaClient и express из соответствующих пакетов npm.
      2. Создание объекта PrismaClient с помощью вызова конструктора и получения экземпляра с именем prisma.
      3. Создание вашего приложения Express с помощью вызова express().
      4. Добавление промежуточного слоя ПО с помощью вызова express.json() для обеспечения возможности корректной обработки данных в формате JSON с помощью Express.
      5. Запуск сервера на порту 3000.

      Теперь вы можете реализовать свой первый маршрут. Между вызовами app.use и app.listen добавьте следующий код:

      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'),
      )
      

      После добавления кода сохраните и закройте файл. Затем запустите локальный веб-сервер с помощью следующей команды:

      Результат будет выглядеть следующим образом:

      Output

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

      Чтобы получить доступ к маршруту /users, вы можете указать в адресной строке браузера http://localhost:3000/users или воспользоваться любым другим клиентом HTTP.

      В этом руководстве мы будем тестировать все маршруты REST API с помощью curl, HTTP клиента для командной строки.

      Примечание: если вы предпочитаете использовать клиент HTTP с графическим пользовательским интерфейсом, вы можете использовать такие альтернативные варианты, как Postwoman или Advanced REST Client.

      Чтобы протестировать маршрут, откройте новое окно терминала или вкладку (чтобы ваш локальный веб-сервер мог продолжать работу) и выполните следующую команду:

      • curl http://localhost:3000/users

      Вы получите данные сущности User, которую вы создали в предыдущем шаге:

      Output

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

      Обратите внимание, что в этот раз массив posts не включен в результат. Это происходит потому, что вы не передаете опцию include в вызов findMany при реализации маршрута /users.

      Вы успешно реализовали свой первый маршрут REST API в /users. В следующем шаге вы будете реализовывать оставшиеся маршруты REST API, чтобы добавить дополнительный функционал для вашего API.

      Шаг 6 — Реализация остальных маршрутов REST API

      В этом шаге вы будете реализовывать оставшиеся маршруты REST API для вашего приложения для ведения блога. В результате ваш веб-сервер будет обслуживать различные запросы типа GET, POST, PUT и DELETE.

      Ниже приводится описание различных маршрутов, которые вы будете реализовывать:

      Метод HTTPМаршрутОписание
      GET/feedПолучает все опубликованные посты.
      GET/post/:idПолучает определенный пост по его идентификатору.
      POST/userСоздает нового пользователя.
      POST/postСоздает новый пост (в виде черновика).
      PUT/post/publish/:idЗадает для поля published поста значение true.
      DELETEpost/:idУдаляет пост по его идентификатору.

      Теперь вы можете перейти к реализации остальных маршрутов GET.

      Откройте файл index.ts с помощью следующей команды:

      Затем добавьте следующий код под реализацией маршрута /users:

      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'),
      )
      

      Сохраните и закройте файл.

      Этот код реализует маршруты API для двух запросов GET:

      • /feed: возвращает список опубликованных постов.
      • /post/:id: возвращает конкретный пост по его идентификатору.

      Prisma Client используется в обеих реализациях. В реализации маршрута /feed запрос, который вы отправляете с помощью Prisma Client, отфильтровывает все записи Post, где в колонке published указано значение true. Кроме того, запрос Prisma Client использует опцию include для получения связанной информации об авторе для каждого возвращаемого поста. В реализации маршрута /post/:id вы передаете идентификатор, который будет получен из URL-адреса, для чтения конкретной записи Post из базы данных.

      Вы можете остановить работу сервера, нажав CTRL+C на клавиатуре. Затем перезапустите его с помощью следующей команды:

      Чтобы протестировать маршрут /feed, вы можете воспользоваться следующей командой curl:

      • curl http://localhost:3000/feed

      Поскольку ни один пост еще не был опубликован, ответ будет содержать пустой массив:

      Output

      []

      Чтобы протестировать маршрут /post/:id, вы можете воспользоваться следующей командой curl:

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

      Она вернет пост, созданный вами ранее:

      Output

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

      Далее реализуйте два маршрута POST. Добавьте следующий код в файл index.ts под реализацией трех маршрутов GET:

      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'),
      )
      

      После этого сохраните и закройте файл.

      Этот код реализует маршруты API для двух запросов POST:

      • /user: создает нового пользователя в базе данных.
      • /post: создает новый пост в базе данных.

      Как и ранее, Prisma Client используется в обеих реализациях. В реализации маршрута /user вы передаете значения из тела запроса HTTP в запрос create Prisma Client.

      Маршрут /post имеет немного более сложную структуру: здесь вы не можете прямо передавать значения из тела HTTP запроса, вместо этого вам сначала нужно вручную извлечь их, а уже после этого передать эти полученные значения в запрос Prisma Client. Это вызвано тем, что структура JSON в теле запроса не соответствует структуре, которую ожидает Prisma Client, поэтому вам нужно вручную создать ожидаемую структуру.

      Вы можете протестировать новые маршруты, остановив сервер с помощью CTRL+C. Затем перезапустите его с помощью следующей команды:

      Чтобы создать нового пользователя с помощью маршрута /user, вы можете отправить следующий POST запрос с помощью curl:

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

      В результате в базе данных будет создан новый пользователь, а в консоли будет отображен следующий вывод:

      Output

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

      Чтобы создать новый пост с помощью маршрута /post, вы можете отправить следующий POST запрос с помощью curl:

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

      В результате в базе данных будет создан новый пост, который будет привязан к пользователю с электронной почтой [email protected]. В консоль будет выведен следующий текст:

      Output

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

      В заключение вы можете реализовать маршруты PUT и DELETE.

      Откройте файл index.ts с помощью следующей команды:

      Затем под реализацией двух маршрутов POST добавьте выделенный код:

      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'),
      )
      

      Сохраните и закройте файл.

      Этот код реализует маршруты API для одного запроса PUT и одного запроса DELETE:

      • /post/publish/:id (PUT): публикует пост по его идентификатору.
      • /post/:id(DELETE): удаляет пост по его идентификатору.

      Prisma Client снова используется в обеих реализациях. В реализации маршрута /post/publish/:id идентификатор поста, который будет опубликован, извлекается из URL-адреса и передается в запрос update Prisma Client. Реализация маршрута /post/:id, который будет удалять пост в базе данных, также извлекает идентификатор поста из URL-адреса и передает его в запрос delete Prisma Client.

      Еще раз остановите сервер, нажав CTRL+C на клавиатуре. Затем перезапустите его с помощью следующей команды:

      Вы можете протестировать маршрут PUT с помощью следующей команды curl:

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

      В этом случае пост будет опубликован с идентификатором, равным 2. Если вы повторно отправите запрос для маршрута /feed, этот пост будет добавлен в ответ.

      Далее вы можете протестировать маршрут DELETE с помощью следующей команды curl:

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

      В результате выполнения этой команды будет удален пост с идентификатором 1. Чтобы убедиться, что пост с этим идентификатором был удален, повторно отправьте запрос GET для маршрута /post/1.

      В этом шаге вы реализовали оставшиеся маршруты REST API для вашего приложения для ведения блога. API теперь отвечает на различные запросы GET, POST, PUT и DELETE и реализует функционал для чтения и записи данных в базе данных.

      Заключение

      С помощью этой статьи вы создали сервер REST API с рядом различных маршрутов для создания, чтения, обновления и удаления данных пользователя и поста для примера приложения для ведения блога. Внутри маршрутов API вы используете Prisma Client для отправки соответствующих запросов для вашей базы данных.

      В качестве следующих шагов вы можете реализовать дополнительные маршруты API или расширить схему вашей базы данных с помощью Prisma Migrate. Обязательно ознакомьтесь с документацией Prisma для получения информации о различных аспектах Prisma и изучите ряд готовых проектов в репозитории prisma-examples, воспользовавшись такими инструментами, как GraphQL или grPC API.



      Source link