# Intro to Prisma [Prisma](https://www.prisma.io/) is a modern typesafe ORM that is usable with any node.js or TypeScript backend. It consists of three main parts: 1. Prisma Client - Autogenerated typesafe query builder for Node and TypeScript 2. Prisma Migrate - Database Migration System 3. Prisma Studio - GUI to view and edit data in your database ## Getting Started with Prisma ### Prerequisites * [Node 16](https://nodejs.org/en/) (current LTS) * NPM 8 (comes with node) * [Docker](https://docs.docker.com/get-docker/) * [Docker Compose](https://docs.docker.com/compose/install/) ### Initialization The following commands will create a new directory, initialize an npm project inside it, add the dependencies necessary for getting started with Prisma, and initialize Prisma itself. ``` # Initialize an npm project and add dev dependencies mkdir prisma-demo && cd prisma-demo npm init -y npm install prisma typescript ts-node @types/node --save-dev npm install @prisma/client npx prisma init ``` This results in a standard npm project with the additional files `.env` and `prisma/schema.prisma` * `.env` - contains a connection string for database * `prisma/schema.prisma` - contains initial boilerplate for prisma, written in Prisma Schema Language (PSL) From here we will add a few things to get up and running with a database with a couple tables and some data. ### Stand up Database in Docker This demo uses postgres running inside docker by adding a very basic docker compose file and updating our .env file ``` # docker-compose.yaml version: "3.8" services: postgres: image: postgres restart: always ports: - "9902:5432" environment: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} pgadmin: image: dpage/pgadmin4:4.25 restart: always depends_on: - postgres ports: - "9903:80" environment: PGADMIN_DEFAULT_EMAIL: ${PGADMIN_USER} PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD} links: - postgres # .env POSTGRES_PASSWORD=prisma PGADMIN_USER=pgadmin PGADMIN_PASSWORD=pgadmin PRISMA_DATASOURCE_URL=postgresql://postgres:prisma@localhost:9902/api ``` ### Running Migrations Updating your database schema is done by adding models to your prisma schema file and running migrations. ``` PSL model Student { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt firstName String lastName String } model Assignment { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String completed Boolean @default(false) } ``` Whenever you add or update models you can migrate your local database with `npx prisma migrate dev`. This generates a migration file written in the sql flavor of your database provider. ``` -- CreateTable CREATE TABLE "Student" ( "id" SERIAL NOT NULL, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" TIMESTAMP(3) NOT NULL, "firstName" TEXT NOT NULL, "lastName" TEXT NOT NULL, CONSTRAINT "Student_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "Assignment" ( "id" SERIAL NOT NULL, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" TIMESTAMP(3) NOT NULL, "title" TEXT NOT NULL, "completed" BOOLEAN NOT NULL DEFAULT false CONSTRAINT "Assignment_pkey" PRIMARY KEY ("id") ); ``` ### Seeding your Database You can optionally add a seed command that prisma will run for you. ``` // package.json // add a prisma key with the seed command "prisma": { "seed": "ts-node prisma/seed.ts" } //prisma/seed.ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { await prisma.student.create({ data: { firstName: "John", lastName: "Cena" } }) await prisma.assignment.create({ data: { title: "Master the Five Moves of Doom" } }) } main() .catch(e => { throw e }) .finally(async () => { await prisma.$disconnect() }) ``` ### Logging Prisma takes in a config object when initialized that allows for customizing the log level. ``` const prisma = new PrismaClient({ log: [ 'info', 'query' ] }) ``` ### Adding Relationships You define relations between tables in PSL by referencing the model and adding relationship metadata attributes. ``` model Student { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt firstName String lastName String Assignments Assignment[] } model Assignment { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String completed Boolean @default(false) student Student @relation(fields: [studentId], references: [id]) studentId Int } ``` The prisma cli has a format command that will help with the syntax of adding relationships between models. This feature is also available in editor plugins, such as the [VSCode Prisma extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) or [coc-prisma in vim](https://github.com/pantharshit00/coc-prisma) ### Data Migrations Sometimes you ned to do data migrations when updating your schema to avoid loss of data. With prisma, you can do this by manually editing the migrations sql file that gets generated when you update the schema. You can do this in your local environment by running `npx prisma migrate dev --create-only`. This creates the migration script without running it so you can modify or add any commands. ### Inspecting the Client By default, the prisma client is generated inside of node_modules under `.prisma/client`. If you would like to inspect the types that are generated for your client you can look at the `index.d.ts` file in this directory. ### Nested Operations Once you have relationships, the prisma client allows you to perform nested operations. For example, you can now add a new student with an initial assignment in one operation ``` const newStudent = await prisma.student.create({ data: { firstName: "Margot", lastName: "Robbie", Assignment: { create: { title: "Introduction" } } } }) ``` ## Next Steps You now have enough information to start building an app with Prisma! From here, you could go in many directions. Prisma can be used in REST APIs, GraphQL APIs, gRPC APIs, serverless functions, etc... [demo code](https://github.com/Pat-Ayres/prisma-demo)