One place for hosting & domains

      Cómo crear una API de REST con Prisma y PostgreSQL


      El autor seleccionó la organización Diversity in Tech Fund para que reciba una donación como parte del programa Write for DOnations.

      Introducción

      Prisma es un conjunto de herramientas para bases de datos de código abierto. Consta de tres herramientas principales:

      • Prisma Client: un generador de consultas con seguridad de tipos que se genera de forma automática para Node.js y TypeScript.
      • Prisma Migrate: un sistema de migración y modelado de datos declarativo.
      • Prisma Studio: una GUI para ver y editar datos en su base de datos.

      Estas herramientas pretenden aumentar la productividad de los desarrolladores de aplicaciones en los flujos de trabajo de sus bases de datos. Uno de los principales beneficios de Prisma es el nivel de abstracción que proporciona: en lugar de tener que resolver consultas SQL o migraciones de esquemas complejas, los desarrolladores de aplicaciones pueden razonar acerca de sus datos de forma más intuitiva al utilizar Prisma para trabajar con su base de datos.

      En este tutorial, creará una API de REST para una aplicación de blog pequeña en TypeScript usando Prisma y una base de datos PostgreSQL. Configurará su base de datos PostgreSQL de forma local con Docker e implementará las rutas de la API de REST utilizando Express. Al final del tutorial, tendrá un servidor web que puede responder a varias solicitudes HTTP y leer y escribir datos en la base de datos ejecutándose en su equipo de forma local.

      Requisitos previos

      Para seguir este tutorial, necesitará lo siguiente:

      Es útil, pero no un requisito de este tutorial, tener conocimientos básicos sobre TypeScript y las API de REST.

      Paso 1: Crear su proyecto de TypeScript

      En este paso, configurará un proyecto de TypeScript simple utilizando npm. Este proyecto será la base para la API de REST que creará en el transcurso de este tutorial.

      Primero, cree un directorio nuevo para su proyecto:

      Luego, diríjase al directorio e inicie un proyecto npm vacío. Tenga en cuenta que la opción -y se utiliza para omitir las solicitudes interactivas del comando. Para verlas, elimine -y del comando:

      Para obtener más información sobre estas solicitudes, siga el Paso 1 de Cómo usar módulos Node.js con npm y package.json.

      Obtendrá un resultado similar al siguiente con las respuestas predeterminadas:

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

      Este comando crea un archivo package.json mínimo que utiliza como archivo de configuración de su proyecto npm. Con esto, está listo para configurar TypeScript en su proyecto.

      Ejecute el siguiente comando para realizar la instalación básica de TypeScript:

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

      Este comando instala tres paquetes como dependencias de desarrollo en su proyecto:

      • typescript: la cadena de herramientas de TypeScript.
      • ts-node: un paquete para ejecutar aplicaciones TypeScript sin compilar previamente a JavaScript.
      • @types/node: las definiciones de tipo de TypeScript para Node.js.

      Solo resta añadir un archivo tsconfig.json para garantizar que TypeScript esté configurado de forma adecuada para la aplicación que va a crear.

      Primero, ejecute el siguiente comando para crear el archivo:

      Agregue el siguiente código de JSON al archivo:

      my-blog/tsconfig.json

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

      Guarde el archivo y ciérrelo.

      Esta es una configuración estándar y mínima para un proyecto de TypeScript. Puede encontrar información sobre las propiedades individuales del archivo de configuración en la documentación de TypeScript.

      Ha configurado su proyecto de TypeScript simple usando npm. A continuación, configurará su base de datos PostgreSQL con Docker y la conectará a Prisma.

      Paso 2: Configurar Prisma con PostgreSQL

      En este paso, instalará la CLI de Prisma, creará su archivo de esquema de Prisma inicial, configurará PostgreSQL con Docker y conectará Prisma a la base de datos. El archivo de esquema de Prisma es el archivo de configuración principal de su instalación de Prisma y contiene el esquema de su base de datos.

      Comience por instalar la CLI de Prisma con el siguiente comando:

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

      Se recomienda instalar la CLI de Prisma en el proyecto de forma local (en lugar de realizar una instalación global). Esto ayuda a evitar conflictos de versiones en caso de que tenga más de un proyecto de Prisma en su equipo.

      A continuación, configurará su base de datos PostgreSQL utilizando Docker. Cree un nuevo archivo de Docker Compose con el siguiente comando:

      Luego, añada el siguiente código al archivo nuevo:

      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:
      

      Este archivo de Docker Compose configura una base de datos PostgreSQL a la que se puede acceder a través del puerto 5432 del contenedor de Docker. Tenga en cuenta que estamos utilizando las credenciales de la base de datos sammy (usuario) y your_password (contraseña). Puede modificar estas credenciales y utilizar el nombre de usuario y la contraseña que desee. Guarde el archivo y ciérrelo.

      Ahora que estableció esta configuración, proceda a iniciar el servidor de la base de datos PostgreSQL con el siguiente comando:

      El resultado de este comando será similar al siguiente:

      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

      Puede verificar que el servidor de la base de datos se esté ejecutando con el siguiente comando:

      Obtendrá un resultado similar al siguiente:

      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

      Ahora que el servidor de la base de datos está en ejecución, puede crear su instalación de Prisma. Ejecute el siguiente comando desde la CLI de Prisma:

      Esto imprimirá el siguiente resultado:

      Output

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

      Tenga en cuenta que es recomendable prefijar todas las invocaciones de la CLI de Prisma con npx. Esto garantiza que se utilice su instalación local.

      Cuando ejecutó el comando, la CLI de Prisma creó una nueva carpeta denominada prisma en su proyecto. Contiene estos dos archivos:

      • schema.prisma: el archivo de configuración principal de su proyecto de Prisma (incluirá su modelo de datos).
      • .env: un archivo dotenv para definir la URL de conexión de su base de datos.

      Para asegurarse de que Prisma conozca la ubicación de su base de datos, abra el archivo .env y ajuste la variable de entorno DATABASE_URL.

      Primero, abra el archivo .env:

      Ahora, puede establecer la variable de entorno de la siguiente manera:

      my-blog/prisma/.env

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

      Asegúrese de reemplazar las credenciales de la base de datos por las que especificó en el archivo de Docker Compose. Para obtener más información sobre el formato de la URL de conexión, consulte la documentación de Prisma.

      Cuando termine, guarde y cierre el archivo.

      En este paso, configuró su base de datos PostgreSQL con Docker, instaló la CLI de Prisma y conectó a la base de datos a través de una variable de entorno. En la siguiente sección, definirá el modelo de datos y creará las tablas de su base de datos.

      Paso 3: Definir el modelo de datos y crear tablas de datos

      En este paso, definirá el modelo de datos en el archivo de esquema de Prisma. Luego, asignará ese modelo de datos a la base de datos con Prisma Migrate, que generará y enviará las instrucciones SQL para crear las tablas correspondientes a su modelo de datos. Como está creando una aplicación de blog, las principales entidades de la aplicación serán usuarios y publicaciones.

      Prisma utiliza su propio lenguaje de modelado de datos para definir la forma de los datos de su aplicación.

      Primero, abra el archivo schema.prisma con el siguiente comando:

      • nano prisma/schema.prisma

      Luego, añada las siguientes definiciones del modelo allí. Puede colocar los modelos en la parte inferior del archivo, justo después del bloque 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-es)
        authorId  Int?
      }
      

      Guarde el archivo y ciérrelo.

      Está definiendo dos modelos, denominados User y Post. Cada uno de ellos contiene varios campos que representan las propiedades del modelo. Los modelos se asignarán a las tablas de la base de datos; los campos representan las columnas individuales.

      Tenga en cuenta que hay una relación de uno a varios entre los dos modelos, especificada por los campos de relaciones posts y author en User y Post. Esto significa que se puede asociar un usuario a varias publicaciones.

      Ahora que estableció estos modelos, puede crear las tablas correspondientes en la base de datos utilizando Prisma Migrate. Ejecute el siguiente comando en su terminal:

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

      Este comando crea una migración nueva en su sistema de archivos. A continuación, se presenta una descripción general de las tres opciones que se proporcionan al comando:

      • --experimental: se requiere porque, actualmente, Prisma Migrate está en estado experimental.
      • --create-db: permite a Prisma Migrate crear la base de datos denominada my-blog especificada en la URL de conexión.
      • --name "init": especifica el nombre de la migración (se utilizará para dar nombre a la carpeta de migración que se crea en su sistema de archivos).

      El resultado de este comando será similar al siguiente:

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

      Puede ver los archivos de migración que se crearon en el directorio prisma/migrations.

      Para ejecutar la migración de su base de datos y crear las tablas para sus modelos de Prisma, ejecute el siguiente comando en su terminal:

      • npx prisma migrate up --experimental

      Obtendrá el siguiente 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.

      Ahora, Prisma Migrate generará las instrucciones SQL necesarias para la migración y las enviará a la base de datos. Estas son las instrucciones SQL que crearon las tablas:

      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
      

      En este paso, definió su modelo de datos en el esquema de Prisma y creó las respectivas tablas de bases de datos con Prisma Migrate. En el siguiente paso, instalará Prisma Client en su proyecto para poder consultar la base de datos.

      Paso 4: Explorar consultas de Prisma Client en una secuencia de comandos simple

      Prisma Client es un generador de consultas con seguridad de tipos de generación automática que puede utilizar para leer y escribir datos mediante programación en una base de datos desde una aplicación Node.js o TypeScript. Lo utilizará para acceder a la base de datos con las rutas de su API de REST, en lugar de usar ORM tradicionales, consultas SQL simples, capas de acceso a datos personalizadas o cualquier otro método de comunicación con una base de datos.

      En este paso, instalará Prisma Client y se familiarizará con las consultas que puede enviar. Antes de implementar las rutas de su API de REST en los siguientes pasos, analizaremos algunas consultas de Prisma Client en una secuencia de comandos ejecutable simple.

      Primero, para instalar Prisma Client en su proyecto, abra su terminal e instale el paquete npm de Prisma Client:

      • npm install @prisma/client

      A continuación, cree un directorio nuevo denominado src para alojar sus archivos de origen:

      Ahora, cree un archivo de TypeScript en el directorio nuevo:

      Todas las consultas de Prisma Client devuelven promesas con las que puede usar await en su código. Para hacerlo, deberá enviar las consultas dentro de una función async.

      Añada el siguiente código reutilizable con una función async que se ejecute en su secuencia de comandos:

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

      A continuación, se presenta una descripción general del código reutilizable:

      1. Se importa el constructor PrismaClient del paquete npm @prisma/client previamente instalado.
      2. Se inicia PrismaClient al invocar al constructor y se obtiene una instancia denominada prisma.
      3. Se define una función async denominada main en la que, a continuación, añadirá las consultas de Prisma Client.
      4. Se invoca la función main y, a la vez, se detectan posibles excepciones y se garantiza que Prisma Client cierre cualquier conexión con bases de datos abierta al invocar prisma.disconnect().

      Ahora que estableció la función main, puede comenzar a añadir consultas de Prisma Client a la secuencia de comandos. Ajuste index.ts para que tenga el siguiente aspecto:

      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: 'alice@prisma.io',
            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())
      

      En este código, está utilizando dos consultas de Prisma Client:

      • create: crea un nuevo registro de User. Tenga en cuenta que, en realidad, está utilizando una escritura anidada, lo que significa que está creando un registro de User y uno de Post en la misma consulta.
      • findMany: lee todos los registros de User existentes de la base de datos. Está proporcionando una opción include, que, adicionalmente, carga los registros de Post relacionados de cada registro de User.

      A continuación, ejecute la secuencia de comandos con el siguiente comando:

      Obtendrá el siguiente resultado en su terminal:

      Output

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

      Nota: Si está utilizando una GUI de base de datos, puede verificar que los datos se hayan creado al revisar las tablas User y Post. De forma alternativa, puede consultar los datos de Prisma Studio al ejecutar npx prisma studio --experimental.

      Ha aprendido a utilizar Prisma Client para leer y escribir datos en su base de datos. En los siguientes pasos, aplicará sus conocimientos nuevos para implementar las rutas de una API de REST de muestra.

      Paso 5: Implementar su primera ruta de la API de REST

      En este paso, instalará Express en su aplicación. Express es un marco web popular para Node.js que utilizará para implementar sus rutas de la API de REST en este proyecto. La primera ruta que implementará le permitirá obtener todos los usuarios de la API utilizando una solicitud GET. Obtendrá los datos de los usuarios de la base de datos utilizando Prisma Client.

      Instale Express con el siguiente comando:

      Como está utilizando TypeScript, también le convendrá instalar los respectivos tipos como dependencias de desarrollo. Para hacerlo, ejecute el siguiente comando:

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

      Ahora que estableció las dependencias, puede configurar su aplicación Express.

      Comience por volver a abrir su archivo de origen principal:

      A continuación, elimine todo el código de index.ts y sustitúyalo por el siguiente para iniciar su API de 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'),
      )
      

      A continuación, se presenta una descripción breve del código:

      1. Se importan PrismaClient y express de sus respectivos paquetes npm.
      2. Se inicia PrismaClient al invocar al constructor y se obtiene una instancia denominada prisma.
      3. Su aplicación Express se crea al invocar express().
      4. Se añade el software intermedio express.json() para garantizar que Express pueda procesar correctamente los datos de JSON.
      5. Se inicia el servidor en el puerto 3000.

      Con esto, puede implementar su primera ruta. Agregue el siguiente código entre las invocaciones a app.use y 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'),
      )
      

      Una vez que lo haya añadido, guarde y cierre su archivo. A continuación, inicie su servidor web local utilizando el siguiente comando:

      Recibirá el siguiente resultado:

      Output

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

      Para acceder a la ruta /users, puede apuntar su navegador a http://localhost:3000/users o a cualquier otro cliente HTTP.

      En este tutorial, probará todas las rutas de la API de REST utilizando curl, un cliente HTTP basado en terminal.

      Nota: Si prefiere usar un cliente HTTP basado en GUI, puede usar alternativas como Postwoman o el cliente REST avanzado.

      Para probar su ruta, abra una ventana o una pestaña de terminal nueva (para que su servidor web local pueda seguir en ejecución) y ejecute el siguiente comando:

      • curl http://localhost:3000/users

      Obtendrá los datos de User que creó en el paso anterior:

      Output

      [{"id":1,"email":"alice@prisma.io","name":"Alice"}]

      Tenga en cuenta que la matriz posts no se incluye en este momento. Esto se debe a que no está pasando la opción include a la invocación de findMany en la implementación de la ruta /users.

      Ha implementado su primera ruta de la API de REST en /users. En el siguiente paso, implementará las rutas restantes de la API de REST para añadir más funcionalidad a su API.

      Paso 6: Implementar las rutas restantes de la API de REST

      En este paso, implementará las rutas restantes de la API de REST para su aplicación de blog. Al final, su servidor web proporcionará diversas solicitudes GET, POST, PUT y DELETE.

      A continuación, se presenta una descripción general de las diferentes rutas que implementará:

      Método HTTP Ruta Descripción
      GET /feed Obtiene todas las publicaciones publicadas.
      GET /post/:id Obtiene un publicación específica por su ID.
      POST /user Crea un usuario nuevo.
      POST /post Crea una publicación nueva (como borrador).
      PUT /post/publish/:id Establece el campo published de una publicación en true.
      DELETE post/:id Elimina una publicación por su ID.

      Primero, proceda a ejecutar e implementar las rutas GET restantes.

      Abra index.ts con el siguiente comando:

      A continuación, añada el siguiente código después de la implementación de la ruta /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'),
      )
      

      Guarde y cierre su archivo.

      Este código implementa las rutas de la API para dos solicitudes GET:

      • /feed: devuelve una lista de las publicaciones publicadas.
      • /post/:id: devuelve una publicación específica por su ID.

      Se utiliza Prisma Client en ambas implementaciones. En la implementación de la ruta /feed, la consulta que envía con Prisma Client filtra todos los registros de Post en los que la columna published contiene el valor true. Además, la consulta de Prisma Client utiliza include para obtener la información relacionada de author de cada publicación que se devuelve. En la implementación de la ruta /post/:id, pasa la ID que se obtiene de la ruta de la URL para poder leer un registro de Post específico de la base de datos.

      Puede detener el servidor al pulsar CTRL+C en el teclado. A continuación, reinicie el servidor utilizando lo siguiente:

      Para probar la ruta /feed, puede usar el siguiente comando curl:

      • curl http://localhost:3000/feed

      Como aún no se ha publicado ninguna publicación, la respuesta es una matriz vacía:

      Output

      []

      Para probar la ruta /post/:id, puede usar el siguiente comando curl:

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

      Este comando devolverá la publicación que creó inicialmente:

      Output

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

      A continuación, ejecute las dos rutas de POST. Añada el siguiente código a index.ts después de las implementaciones de las tres rutas de 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'),
      )
      

      Cuando termine, guarde y cierre el archivo.

      Este código implementa las rutas de la API para dos solicitudes POST:

      • /user: crea un usuario nuevo en la base de datos.
      • /post: crea una publicación nueva en la base de datos.

      Al igual que anteriormente, se utiliza Prisma Client en ambas implementaciones. En la implementación de la ruta /user, pasa los valores del cuerpo de la solicitud HTTP a la consulta create de Prisma Client.

      La ruta /post es un poco más compleja: como no puede pasar los valores del cuerpo de la solicitud HTTP directamente, primero, deberá extraerlos de forma manual para pasarlos a la consulta de Prisma Client. Esto se debe a que la estructura de JSON en el cuerpo de la solicitud no coincide con la que espera Prisma Client, por lo tanto, debe crear la estructura esperada de forma manual.

      Puede probar las rutas nuevas al detener el servidor con CTRL+C. A continuación, reinicie el servidor utilizando lo siguiente:

      Para crear un usuario nuevo a través de la ruta /user, puede enviar la siguiente solicitud POST con curl:

      • curl -X POST -H "Content-Type: application/json" -d '{"name":"Bob", "email":"bob@prisma.io"}' http://localhost:3000/user

      Con esto, se creará un usuario nuevo en la base de datos y se imprimirá el siguiente resultado:

      Output

      {"id":2,"email":"bob@prisma.io","name":"Bob"}

      Para crear una publicación nueva a través de la ruta /post, puede enviar la siguiente solicitud POST con curl:

      • curl -X POST -H "Content-Type: application/json" -d '{"title":"I am Bob", "authorEmail":"bob@prisma.io"}' http://localhost:3000/post

      Con esto, se creará una publicación nueva en la base de datos que se conectará al usuario con el correo electrónico bob@prisma.io. Se imprime el siguiente resultado:

      Output

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

      Por último, puede implementar las rutas PUT y DELETE.

      Abra index.ts con el siguiente comando:

      A continuación, después de la implementación de las dos rutas de POST, añada el código resaltado:

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

      Guarde y cierre su archivo.

      Este código implementa las rutas de la API para una solicitud PUT y una DELETE:

      • /post/public/:id (PUT): publica una publicación por su ID.
      • /post/:id (DELETE): elimina una publicación por su ID.

      Nuevamente, se utiliza Prisma Client en ambas implementaciones. En la implementación de la ruta /post/public/:id, se obtiene la ID de la publicación que se va a publicar de la URL y se pasa a la consulta update de Prisma Client. La implementación de la ruta /post/:id para eliminar una publicación de la base de datos también obtiene la ID de la publicación de la URL y la pasa a la consulta delete de Prisma Client.

      Vuelva a detener el servidor pulsando CTRL+C en el teclado. A continuación, reinicie el servidor utilizando lo siguiente:

      Puede probar la ruta PUT con el siguiente comando curl:

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

      Con esto, se publicará la publicación con un valor de ID de 2. Si reenvía la solicitud /feed, ahora, esta publicación se incluirá en la respuesta.

      Por último, puede probar la ruta DELETE con el siguiente comando curl:

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

      Con esto, se eliminará la publicación con un valor de ID de 1. Para confirmar que la publicación con esta ID se haya eliminado, puede reenviar una solicitud GET a la ruta /post/1.

      En este paso, implementó las rutas restantes de la API de REST para su aplicación de blog. Ahora, la API responde a diversas solicitudes GET, POST, PUT y DELETE e implementa la funcionalidad para leer y escribir datos en la base de datos.

      Conclusión

      En este artículo, creó un servidor para la API de REST con diversas rutas para crear, leer, actualizar y eliminar datos de usuarios y publicaciones para una aplicación de blog. Está utilizando Prisma Client dentro de las rutas de la API para enviar las consultas respectivas a su base de datos.

      Como próximo paso, puede implementar rutas de la API adicionales o ampliar el esquema de su base de datos utilizando Prisma Migrate. Asegúrese de consultar la documentación de Prisma para obtener más información sobre los distintos aspectos de Prisma y explorar algunos proyectos de ejemplo listos para ejecutar en el repositorio prisma-examples utilizando herramientas como GraphQL o API de 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: 'alice@prisma.io',
            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: 'alice@prisma.io', name: 'Alice' } [ { id: 1, email: 'alice@prisma.io', 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":"alice@prisma.io","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 HTTP Rota Descrição
      GET /feed Busca todos os posts publicados.
      GET /post/:id Busca um post específico com base em seu ID.
      POST /user Cria um novo usuário.
      POST /post Cria um novo post (como um rascunho).
      PUT /post/publish/:id Define o campo published (publicado) de um post como true (verdadeiro).
      DELETE post/:id Exclui 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":"bob@prisma.io"}' http://localhost:3000/user

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

      Output

      {"id":2,"email":"bob@prisma.io","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":"bob@prisma.io"}' http://localhost:3000/post

      Isso irá criar um novo post no banco de dados e conectá-lo ao usuário com e-mail bob@prisma.io. 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

      Cómo configurar el acceso remoto para MongoDB en Ubuntu 20.04


      Melissa Anderson escribió una versión anterior de este tutorial.

      Introducción

      MongoDB, también conocido como Mongo, es una base de datos de documentos de código abierto usada comúnmente en las aplicaciones web modernas. Por defecto, solo permite conexiones que se originan en el mismo servidor donde está instalado. Si desea administrar MongoDB de forma remota o conectarlo a un servidor de aplicaciones independiente, existen algunos cambios que deberá realizar a la configuración predeterminada.

      En este tutorial, configurará una instalación de MongoDB para permitir el acceso de forma segura desde un equipo remoto de confianza. Para hacer esto, actualizará las reglas de su firewall para proporcionar acceso del equipo remoto al puerto sobre el cual MongoDB está escuchando las conexiones, y a continuación actualizará su archivo de configuración para cambiar su ajuste de vinculación de IP. Luego, como paso final, probará que su equipo remoto puede realizar la conexión a su base de datos correctamente.

      Requisitos previos

      Para completar este tutorial, necesitará lo siguiente:

      • Un servidor con Ubuntu 20.04. Este servidor debería tener un usuario administrativo y un firewall configurado con ufw. Puede establecerlo siguiendo nuestra Guía inicial de configuración del servidor para Ubuntu 20.04.
      • MongoDB instalado en su servidor. Este tutorial asume que tiene instalado MongoDB 4.4 o una versión más reciente. Puede instalar esta versión siguiendo nuestro tutorial en Cómo instalar MongoDB en Ubuntu 20.04.
      • Un segundo equipo desde el cual accederá a su instancia de MongDB. Para mayor simplicidad, este tutorial asume que este equipo es otro servidor Ubuntu 20.04 con un usuario administrativo no root y un firewall UFW configurado siguiendo nuestra guía de configuración inicial para servidores de Ubuntu 20.04. Sin embargo, los Pasos 1 y 2, que describen el procedimiento real para permitir la conectividad remota sobre el servidor de la base de datos, funcionarán independientemente de qué sistemas operativos esté ejecutando el equipo remoto.

      Finalmente, aunque no es necesario para completar este tutorial, recomendamos encarecidamente que proteja su instalación de MongoDB creando una cuenta de usuario administrativo para la base de datos y permitiendo la autenticación. Para hacer esto, siga nuestro tutorial sobre Cómo proteger MongoDB en Ubuntu 20.04.

      Paso 1: Ajuste del firewall

      Asumiendo que siguió el tutorial de requisitos previos de configuración inicial del servidor y habilitó un firewall UFW en su servidor, su instalación de MongoDB será inaccesible desde Internet. Si tiene intención de usar el servidor de MongoDB solo a nivel local con aplicaciones que se ejecuten en el mismo servidor, este es el ajuste recomendado y seguro. Sin embargo, si desea poder conectar con su servidor MongoDB desde una ubicación remota, tendrá que permitir las conexiones entrantes al puerto donde está escuchando la base de datos añadiendo una nueva regla UFW.

      Comience verificando en qué puerto está escuchando la instalación de MongoDB con el comando lsof. Este comando normalmente devuelve una lista con cada archivo abierto en un sistema, pero cuando se combina con la opción -i, lista solo los archivos o corrientes de datos relacionados con la red:

      El siguiente comando redirigirá el resultado producido por lsof -i a un comando grep que busca una cadena llamada mongo:

      • sudo lsof -i | grep mongo

      Este resultado de ejemplo muestra que MongoDB está escuchando las conexiones en su puerto predeterminado, 27017:

      Output

      mongod 82221 mongodb 11u IPv4 913411 0t0 TCP localhost:27017 (LISTEN)

      En la mayoría de los casos, solo se debe acceder a MongoDB desde determinadas ubicaciones de confianza, como otro servidor que aloje una aplicación. Una forma de configurar esto es ejecutar el siguiente comando en su servidor MongoDB, que abre el acceso en el puerto predeterminado de Mongo mientras que explícitamente solo permite la dirección IP del otro servidor de confianza.

      Ejecute el siguiente comando, asegurándose de cambiar trusted_server_ip a la dirección IP del equipo remoto de confianza que usará para acceder a su instancia de MongoDB:

      Nota: Si el resultado del comando anterior mostró que su instalación de MongoDB está escuchando sobre un puerto no predeterminado, utilice ese número de puerto en lugar de 27017 en este comando.

      • sudo ufw allow from trusted_server_ip to any port 27017

      En el futuro, si alguna vez quiere acceder a MongoDB desde otro equipo, ejecute este comando de nuevo con la dirección IP del nuevo equipo en lugar de trusted_server_ip.

      Puede verificar el cambio en los ajustes del firewall con ufw:

      El resultado mostrará que el tráfico al puerto 27017 desde el servidor remoto ahora está permitido:

      Output

      Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere 27017 ALLOW trusted_server_ip OpenSSH (v6) ALLOW Anywhere (v6)

      Puede encontrar ajustes de firewall más avanzados para restringir el acceso a servicios en Aspectos básicos de UFW: Reglas y comandos comunes de firewall.

      A continuación, vinculará MongoDB a la dirección IP pública del servidor para que pueda acceder a él desde su equipo remoto.

      Paso 2: Configurar una bindIP pública

      En este momento, aunque el puerto está abierto, MongoDB está actualmente vinculado a 127.0.0.1, la interfaz de red loopback. Esto significa que MongoDB solo puede aceptar conexiones que se originen en el servidor donde está instalado.

      Para permitir conexiones remotas, debe editar el archivo de configuración de MongoDB (/etc/mongod.conf) para vincular adicionalmente MongoDB a la dirección IP públicamente dirigible de su servidor. De esta forma, su instalación de MongoDB podrá escuchar las conexiones realizadas a su servidor MongoDB desde equipos remotos.

      Abra el archivo de configuración de MongoDB en su editor de texto preferido: El siguiente ejemplo utiliza nano:

      • sudo nano /etc/mongod.conf

      Busque la sección network interfaces y, a continuación, el valor bindIp:

      /etc/mongod.conf

      . . .
      # network interfaces
      net:
        port: 27017
        bindIp: 127.0.0.1
      
      . . .
      

      Añada una coma a esta línea seguida de la dirección IP pública de su servidor MongoDB:

      /etc/mongod.conf

      . . .
      # network interfaces
      net:
        port: 27017
        bindIp: 127.0.0.1,mongodb_server_ip
      
      . . .
      

      Guarde y cierre el archivo. Si utiliza nano, podrá hacerlo presionando CTRL+X, Y y luego ENTER.

      A continuación, reinicie MongoDB para que este cambio surta efecto:

      • sudo systemctl restart mongod

      Tras eso, su instalación de MongoDB podrá aceptar conexiones remotas desde cualquier equipo al que haya permitido acceder al puerto 27017. Como paso final, puede probar si el servidor remoto de confianza que permitió a través del firewall en el Paso 1 puede llegar a la instancia de MongoDB que se ejecuta en su servidor.

      Paso 3: Probar la conectividad remota

      Ahora que ha configurado su instalación de MongoDB para que escuche las conexiones que se originan en su dirección IP dirigible públicamente y ha concedido a su equipo remoto acceso a través del firewall de su servidor al puerto predeterminado de Mongo, puede probar que el equipo remoto puede conectarse.

      Nota: Como se mencionó en la sección Requisitos previos, este tutorial asume que su equipo remoto es otro servidor con Ubuntu 20.04. El procedimiento para permitir las conexiones remotas descrito en los Pasos 1 y 2 debería funcionar independientemente de qué sistema operativo ejecute su equipo remoto, pero los métodos de prueba descritos en este Paso no funcionan universalmente entre sistemas operativos.

      Una forma de probar que su servidor remoto de confianza puede conectarse a la instancia de MongoDB es usar el comando nc. nc, abreviatura de netcat, es una utilidad usada para establecer conexiones de red con TCP o UDP. Es útil para probar en casos como este porque le permite especificar una dirección IP y un número de puerto.

      Primero, inicie sesión en su servidor de confianza usando SSH:

      • ssh sammy@trusted_server_ip

      A continuación, ejecute el siguiente comando nc, que incluye la opción -z. Esto limita a nc para que solo analice un daemon de escucha en el servidor de destino sin enviar datos. Recuerde del tutorial de instalación de requisitos previos que MongoDB está ejecutándose como un daemon de servicio, lo que hace que esta opción sea útil para probar la conectividad. También incluye la opción v que aumenta la verbosidad del comando, lo que hace que netcat devuelva un resultado que de otra forma no devolvería.

      Ejecute el siguiente comando nc desde su servidor remoto de confianza, asegurándose de sustituir mongodb_server_ip con la dirección IP del servidor sobre el cual instaló MongoDB:

      • nc -zv mongodb_server_ip 27017

      Si el servidor de confianza puede acceder al daemon de MongoDB, su resultado indicará que la conexión se realizó correctamente:

      Output

      Connection to mongodb_server_ip 27017 port [tcp/*] succeeded!

      Asumiendo que tenga una versión compatible del shell de mongo instalado en su servidor remoto, puede en este momento conectar directamente con la instancia de MongoDB instalada en el servidor host.

      Una forma de conectar es con una URI de cadena de conexión, como esta:

      • mongo "mongodb://mongo_server_ip:27017"

      Nota: Si siguió el tutorial recomendado Cómo proteger MongoDB en Ubuntu 20.04, habrá cerrado el acceso a su base de datos para los usuarios sin autenticar. En este caso, necesitará usar una URI que especifique un nombre de usuario válido, como esta:

      • mongo "mongodb://username@mongo_server_ip:27017"

      El shell le pedirá automáticamente que introduzca la contraseña del usuario.

      Con eso, ha confirmado que su servidor MongoDB puede aceptar conexiones desde el servidor de confianza.

      Conclusión

      Ahora puede acceder a su instalación de MongoDB desde un servidor remoto. En este momento, puede administrar su base de datos Mongo remotamente desde el servidor de confianza. Alternativamente, podría configurar una aplicación para que se ejecute en el servidor remoto y utilice la base de datos remotamente.

      Si no ha configurado un usuario administrativo y habilitado la autenticación, cualquiera que tenga acceso a su servidor remoto podrá acceder también a su instalación de MongoDB. Si aún no lo ha hecho, le recomendamos encarecidamente que siga nuestra guía sobre Cómo proteger MongoDB en Ubuntu 20.04 para añadir usuario administrativo y habilitar un bloqueo adicional.



      Source link