├── .github └── renovate.json ├── .gitignore ├── README.md ├── functions ├── createUser.js ├── posts.js ├── seed.js ├── status.js └── users.js ├── netlify.toml ├── package.json ├── prisma ├── migrations │ ├── 20210317105423_init │ │ └── migration.sql │ └── migration_lock.toml └── schema.prisma └── public └── index.html /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base", "docker:disable"], 3 | "automerge": false, 4 | "masterIssue": true, 5 | "reviewers": ["@2color"], 6 | "baseBranches": ["master"], 7 | "packageRules": [ 8 | { 9 | "baseBranchList": ["master"], 10 | "packageNames": ["prisma", "@prisma/client"], 11 | "enabled": true, 12 | "updateTypes": ["minor"] 13 | }, 14 | { 15 | "packageNames": ["netlify-cli"], 16 | "updateTypes": ["minor"], 17 | "schedule": ["at any time"], 18 | "automerge": true 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn-error.log 3 | dist 4 | build 5 | .DS_Store 6 | examples 7 | tmp 8 | pnpm-debug.log 9 | sandbox 10 | *.tsbuildinfo 11 | # Local Netlify folder 12 | .netlify 13 | 14 | # Ignore files containing environment variables 15 | .env* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Prisma deployment to Netlify example 2 | 3 | [Deployment Guide](https://www.prisma.io/docs/guides/deployment/deploying-to-netlify) -------------------------------------------------------------------------------- /functions/createUser.js: -------------------------------------------------------------------------------- 1 | const { PrismaClient, PrismaClientRequestError } = require('@prisma/client') 2 | const prisma = new PrismaClient() 3 | 4 | exports.handler = async (event, context, callback) => { 5 | try { 6 | const data = JSON.parse(event.body) 7 | const createdUser = await prisma.user.create({ data }) 8 | 9 | return { 10 | statusCode: 200, 11 | headers: { 'Content-Type': 'application/json' }, 12 | body: JSON.stringify(createdUser) 13 | } 14 | } catch (e) { 15 | if (e instanceof PrismaClientRequestError) { 16 | if (e.code === 'P2002') { 17 | return { 18 | statusCode: 409, 19 | headers: { 'Content-Type': 'application/json' }, 20 | body: JSON.stringify({ 21 | error: 'A user with this email already exists' 22 | }) 23 | } 24 | } 25 | } 26 | 27 | console.error(e) 28 | return { statusCode: 500 } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /functions/posts.js: -------------------------------------------------------------------------------- 1 | const { PrismaClient } = require('@prisma/client') 2 | 3 | const prisma = new PrismaClient() 4 | 5 | exports.handler = async (event, context, callback) => { 6 | try { 7 | const posts = await prisma.post.findMany({ 8 | include: { author: true } 9 | }) 10 | return { 11 | statusCode: 200, 12 | headers: { 'Content-Type': 'application/json' }, 13 | body: JSON.stringify(posts) 14 | } 15 | } catch (error) { 16 | console.error(error) 17 | return { 18 | statusCode: 500, 19 | headers: { 'Content-Type': 'application/json' }, 20 | body: JSON.stringify(error) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /functions/seed.js: -------------------------------------------------------------------------------- 1 | const { PrismaClient } = require('@prisma/client') 2 | const prisma = new PrismaClient() 3 | 4 | exports.handler = async (event, context, callback) => { 5 | try { 6 | await Promise.all([prisma.profile.deleteMany(), prisma.post.deleteMany()]) 7 | await prisma.user.deleteMany() 8 | 9 | const createdUser = await prisma.user.create({ 10 | data: seedUser 11 | }) 12 | 13 | const createdUser2 = await prisma.user.create({ 14 | data: seedUser2 15 | }) 16 | 17 | return { 18 | statusCode: 201, 19 | headers: { 'Content-Type': 'application/json' }, 20 | body: JSON.stringify([createdUser, createdUser2]) 21 | } 22 | } catch (error) { 23 | console.error(error) 24 | return { statusCode: 500 } 25 | } 26 | } 27 | 28 | const seedUser = { 29 | email: 'jane@prisma.io', 30 | name: 'Jane', 31 | profile: { 32 | create: { 33 | bio: 'Health Enthusiast', 34 | }, 35 | }, 36 | posts: { 37 | create: [ 38 | { 39 | title: 'Comparing Database Types: How Database Types Evolved to Meet Different Needs', 40 | content: 'https://www.prisma.io/blog/comparison-of-database-models-1iz9u29nwn37/', 41 | }, 42 | { 43 | title: 'Analysing Sleep Patterns: The Quantified Self', 44 | content: 'https://quantifiedself.com/get-started/', 45 | }, 46 | { 47 | title: 'Prisma 2 Docs', 48 | content: 'https://www.prisma.io/docs/', 49 | }, 50 | ], 51 | }, 52 | } 53 | 54 | const seedUser2 = { 55 | email: 'toru@prisma.io', 56 | name: 'Toru Takemitsu', 57 | profile: { 58 | create: { 59 | bio: 'Musician', 60 | }, 61 | }, 62 | posts: { 63 | create: [ 64 | { 65 | title: 'Requiem for String Orchestra', 66 | content: '', 67 | }, 68 | { 69 | title: 'Music of Tree', 70 | content: '', 71 | }, 72 | { 73 | title: 'Waves for clarinet, horn, two trombones and bass drum ', 74 | content: '', 75 | }, 76 | ], 77 | }, 78 | } 79 | -------------------------------------------------------------------------------- /functions/status.js: -------------------------------------------------------------------------------- 1 | exports.handler = async (event, context, callback) => { 2 | return { 3 | statusCode: 200, 4 | headers: { 'Content-Type': 'application/json' }, 5 | body: JSON.stringify({ up: true }) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /functions/users.js: -------------------------------------------------------------------------------- 1 | const { PrismaClient } = require('@prisma/client') 2 | const prisma = new PrismaClient() 3 | 4 | exports.handler = async (event, context, callback) => { 5 | try { 6 | const users = await prisma.user.findMany({ 7 | include: { profile: true } 8 | }) 9 | return { 10 | statusCode: 200, 11 | headers: { 'Content-Type': 'application/json' }, 12 | body: JSON.stringify(users) 13 | } 14 | } catch (error) { 15 | console.error(error) 16 | return { 17 | statusCode: 500, 18 | headers: { 'Content-Type': 'application/json' }, 19 | body: JSON.stringify(error) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "npm run build" 3 | 4 | functions = "functions/" 5 | 6 | publish = "public/" 7 | 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deployment-example-netlify", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "devDependencies": { 7 | "netlify-cli": "12.2.9", 8 | "prisma": "^4.7.1" 9 | }, 10 | "scripts": { 11 | "build": "prisma generate", 12 | "dev": "netlify dev" 13 | }, 14 | "dependencies": { 15 | "@prisma/client": "^4.7.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /prisma/migrations/20210317105423_init/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "Post" ( 3 | "id" SERIAL NOT NULL, 4 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 5 | "title" TEXT NOT NULL, 6 | "content" TEXT, 7 | "published" BOOLEAN NOT NULL DEFAULT false, 8 | "authorId" INTEGER NOT NULL, 9 | 10 | PRIMARY KEY ("id") 11 | ); 12 | 13 | -- CreateTable 14 | CREATE TABLE "Profile" ( 15 | "id" SERIAL NOT NULL, 16 | "bio" TEXT, 17 | "userId" INTEGER NOT NULL, 18 | 19 | PRIMARY KEY ("id") 20 | ); 21 | 22 | -- CreateTable 23 | CREATE TABLE "User" ( 24 | "id" SERIAL NOT NULL, 25 | "email" TEXT NOT NULL, 26 | "name" TEXT, 27 | 28 | PRIMARY KEY ("id") 29 | ); 30 | 31 | -- CreateIndex 32 | CREATE UNIQUE INDEX "Profile.userId_unique" ON "Profile"("userId"); 33 | 34 | -- CreateIndex 35 | CREATE UNIQUE INDEX "User.email_unique" ON "User"("email"); 36 | 37 | -- AddForeignKey 38 | ALTER TABLE "Post" ADD FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; 39 | 40 | -- AddForeignKey 41 | ALTER TABLE "Profile" ADD FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; 42 | -------------------------------------------------------------------------------- /prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "postgresql" -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | binaryTargets = ["native", "rhel-openssl-1.0.x"] 4 | } 5 | 6 | datasource db { 7 | provider = "postgresql" 8 | url = env("DATABASE_URL") 9 | } 10 | 11 | model Post { 12 | id Int @id @default(autoincrement()) 13 | createdAt DateTime @default(now()) 14 | title String 15 | content String? 16 | published Boolean @default(false) 17 | author User @relation(fields: [authorId], references: [id]) // renamed from `User` -> `author` 18 | authorId Int // relation scalar field 19 | } 20 | 21 | model Profile { 22 | id Int @id @default(autoincrement()) 23 | bio String? 24 | userId Int @unique // relation scalar field 25 | user User @relation(fields: [userId], references: [id]) // renamed from `User` -> `user` 26 | } 27 | 28 | model User { 29 | id Int @id @default(autoincrement()) 30 | email String @unique 31 | name String? 32 | posts Post[] // renamed from `Post` -> `posts` 33 | profile Profile? // renamed from `User` -> `profile` 34 | } 35 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |