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