Prisma - 차세대 ORM

요구 사항:
  • API REST 기본 구성
  • SQL 기본 정보 확인
  • Node.js

  • npm client de su preferencia.

  • En este tutorial veremos como hacer un API REST TODO App con TypeScript , Prisma y esbuild .

    ⚠️ No necesitas previo conocimiento de ninguna de estas tecnologías.



    Que es Prisma?



    Es un ORM de próxima generación con soporte para TypeScript con unas herramientas para facilitarnos la vida:

  • Prisma Client : Generador de Consultas de tipo seguro y autogenerado que se adapta a sus datos.

  • Migraciones : Herramienta para creary gestionar las migraciones de tu base de datos.

  • Prisma Studio : 기본 데이터에 대한 GUI 클라이언트.

  • 👀 Para que no haya pierde en donde va cada cosa o si solo vienes a echar un vistazo rápido; te dejo el código en este repo.



    엠페제모스 🧑‍💻



    Si estas usando VSCode puedes usar el plugin oficial de Prisma.



    Instalemos nuestras 의존성




    # yarn
    $ yarn add -D prisma esbuild @types/node
    $ yarn add @prisma/client
    
    # npm
    $ npm i -D prisma esbuild @types/node
    $ npm i @prisma/client 
    


    레반테모스 누에스트로 엔토르노 드 트라바조




    # yarn
    $ yarn prisma init
    
    # npm
    $ npx prisma init
    


    Actualicemos nuestras 변수 de entorno. Para este tutorial practico usaremos SQLite pero puede revisar las que soporta Prisma .

    # .env
    DATABASE_URL="file:./database.sqlite"
    


    Actualicemos nuestro schema.prisma

    // prisma/schema.prisma
    generator client {
      provider = "prisma-client-js"
    }
    
    datasource db {
      provider = "sqlite" // <- usemos SQLite
      url      = env("DATABASE_URL")
    }
    


    Creamos 새로운 빌더는 TypeScript와 함께 Trabajar를 빌드합니다.

    Si no sabes como funciona esto igual luego deberías darte tiempo para leer mi blog



    // esbuild.dev.js
    import { spawn } from 'child_process'
    import esbuild from 'esbuild'
    
    let server;
    
    const startServer = (message) => {
        if (server) server.kill('SIGINT')
        server = spawn('node', ['./dist/index.mjs'], { stdio: 'inherit' })
        console.log(`\n${message}\n`)
    }
    
    esbuild.build({
        entryPoints: ['./src/index.ts'],
        watch: { onRebuild: (err) => !err && startServer('Rebuilded') },
        bundle: true,
        minify: true,
        platform: 'node',
        format: 'esm',
        target: ['esnext'],
        external: ['/node_modules/*'],
        outfile: './dist/index.mjs',
    })
        .then(() => startServer('Done 🚀'))
        .catch(() => process.exit(1))
    


    Actualicemos nuestro package.json.

    // package.json
    {
      "name": "prisma",
      "version": "1.0.0",
      "main": "index.js",
      "author": "Ushieru Kokoran (https://ushieru.com/)",
      "license": "MIT",
      "type": "module", // <- soporte a mjs
      "scripts": {
        "dev": "node esbuild.dev.js" // <- script para desarrollo
      },
      "dependencies": {
        "@prisma/client": "^4.1.0",
        "@types/koa": "^2.13.5",
        "@types/node": "^18.0.6",
        "koa": "^2.13.4"
      },
      "devDependencies": {
        "esbuild": "^0.14.49",
        "prisma": "^4.1.0"
      }
    }
    


    Creemos el modelo de nuestras tareas. Si estas usando otra DB que no sea SQLite puede usar enums en el status. ( defining-enums )

    generator client {
      provider = "prisma-client-js"
    }
    
    datasource db {
      provider = "sqlite"
      url      = env("DATABASE_URL")
    }
    
    model Task {
      id          String   @id @default(cuid())
      name        String
      description String
      status      String   @default("OPEN") // OPEN, IN_PROGRESS, DONE
      createdAt   DateTime @default(now())
      updatedAt   DateTime @updatedAt
    }
    


    Ahora debemos cargar nuestros modelos a la base de datos.

    # yarn
    $ yarn prisma db push
    
    # npm
    $ npx prisma db push
    




    Prisma 클라이언트 생성...? Asi es, prisma genera los types de los objetos a partir de las tablas de la base de datos al vuelo. VSCode는 TypeScript 서버를 다시 시작할 수 있는 este cambio가 아닙니다.
    Para eso abrimos la paleta de comandos y ejecutamos: TypeScript: Reset TS server.



    Creemos un cliente de prisma para tener acceso a nuestro ORM y su each CRUD(Create, Read, Update, Delete).

    // src/crudTask.ts
    import { PrismaClient } from '@prisma/client';
    
    const prisma = new PrismaClient();
    
    // Tenemos acceso a nuestro modelo task que es un mapeo exacto
    // a nuestra tabla en la base de datos. Y con TypeScript tenemos
    // el autocompletado para no cometer errores.
    
    export const createTask = async (name: string, description: string) => {
        return await prisma.task.create({
            data: { name, description }
        })
    }
    
    export const readTasks = async () => {
        return await prisma.task.findMany()
    }
    
    export const readOneTask = async (id: string) => {
        return await prisma.task.findUnique({ where: { id } })
    }
    
    export const updateTask = async (id: string, name: string, description: string, status: 'OPEN' | 'IN_PROGRESS' | 'DONE') => {
        return await prisma.task.update({
            data: { name, description, status },
            where: { id }
        })
    }
    
    export const deleteTask = async (id: string) => {
        return await prisma.task.delete({ where: { id } })
    }
    


    Y ya lo tenemos 🎉🎉 Puedes envolverlo en cualquier backend que quieras en src/index.ts.

    Si usas Next.js debes hacer unos cambios en la declaracion del cliente. Te dejo la Doc



    Te muestro este pequeño ejemplo con Koa :

    // src/index.ts
    import Koa from 'koa';
    import Router from 'koa-router';
    import koaBody from 'koa-body';
    import { createTask, readTasks, readOneTask, updateTask, deleteTask } from './crudTask'
    
    const app = new Koa();
    
    app.use(koaBody({ jsonLimit: '5kb' }));
    
    const router = new Router();
    
    router.get('/', (ctx) => ctx.body = 'Hello World');
    
    router.post('/tasks', async (ctx) =>
        ctx.body = await createTask(ctx.request.body.name, ctx.request.body.description));
    
    router.get('/tasks', async (ctx) =>
        ctx.body = await readTasks());
    
    router.get('/tasks/:id', async (ctx) =>
        ctx.body = await readOneTask(ctx.params.id));
    
    router.put('/tasks/:id', async (ctx) =>
        ctx.body = await updateTask(
            ctx.params.id,
            ctx.request.body.name,
            ctx.request.body.description,
            ctx.request.body.status
        ));
    
    router.delete('/tasks/:id', async (ctx) =>
        ctx.body = await deleteTask(ctx.params.id));
    
    app.use(router.routes());
    
    app.listen(3000);
    


    Y ya lo tenemos, vemos un ejemplo con Relaciones? cuéntame en los commentarios.

    Y 해피해킹 🎉👨‍💻

    좋은 웹페이지 즐겨찾기