diff --git a/.circleci/config.yml b/.circleci/config.yml
deleted file mode 100644
index c9fc0c2cdcb2..000000000000
--- a/.circleci/config.yml
+++ /dev/null
@@ -1,79 +0,0 @@
-version: 2
-jobs:
- meta:
- docker:
- - image: circleci/node
- steps:
- - checkout
- - run: cd .github/tests && yarn && yarn test
-
- node:
- docker:
- - image: circleci/node
- steps:
- - checkout
- - run: sudo yarn global add prisma
- - run: cd node/cli-app && yarn && prisma generate
- - run: cd node/graphql && yarn && prisma generate
- - run: cd node/graphql-auth && yarn && prisma generate
- - run: cd node/graphql-subscriptions && yarn && prisma generate
- - run: cd node/rest-express && yarn && prisma generate
- - run: cd node/script && yarn && prisma generate
- - run: cd node/docker-mongodb && yarn && prisma generate
- - run: cd node/docker-mysql && yarn && prisma generate
- - run: cd node/docker-postgres && yarn && prisma generate
- - run: cd node/grpc && yarn && prisma generate
-
- typescript:
- docker:
- - image: circleci/node
- steps:
- - checkout
- - run: sudo yarn global add prisma
- # - run: cd typescript/circleci && yarn && yarn tsc
- - run: cd typescript/cli-app && yarn && prisma generate && yarn tsc
- - run: cd typescript/graphql && yarn && prisma generate && npx nexus-prisma-generate --client "./src/generated/prisma-client" --output "./src/generated/nexus-prisma" && yarn tsc
- - run: cd typescript/graphql-auth && yarn && prisma generate && npx nexus-prisma-generate --client "./src/generated/prisma-client" --output "./src/generated/nexus-prisma" && yarn tsc
- - run: cd typescript/graphql-subscriptions && yarn && prisma generate && yarn generate && yarn tsc
- - run: cd typescript/rest-express && yarn && prisma generate && yarn tsc
- - run: cd typescript/script && yarn && prisma generate && yarn tsc
- - run: cd typescript/docker-mongodb && yarn && prisma generate
- - run: cd typescript/docker-mysql && yarn && prisma generate
- - run: cd typescript/docker-postgres && yarn && prisma generate
- - run: cd typescript/grpc && yarn && prisma generate && yarn tsc
-
- flow:
- docker:
- - image: circleci/node
- steps:
- - checkout
- - run: sudo yarn global add prisma
- - run: cd flow/graphql && yarn && prisma generate && yarn generate && yarn flow check
- # - run: cd flow/script && yarn && prisma generate && yarn flow check # typechecking is broken: https://github.com/prisma/prisma-examples/issues/373
- - run: cd flow/script && yarn && prisma generate
-
- go:
- docker:
- - image: circleci/golang
- working_directory: /go/src/github.com/prisma/prisma-examples
- steps:
- - checkout
- - run: curl https://s3-eu-west-1.amazonaws.com/curl-linux/prisma-1.27.0.tar.gz | tar xvz && sudo mv prisma /usr/local/bin # TODO (see https://github.com/prisma/prisma/issues/3620)
- - run: cd go/cli-app && prisma generate && dep ensure && go build
- - run: cd go/graphql && prisma generate && dep ensure && go run ./scripts/gqlgen.go && cd server && go build
- - run: cd go/http-mux && prisma generate && dep ensure && go build
- - run: cd go/rest-gin && prisma generate && dep ensure && go build
- - run: cd go/script && prisma generate && dep ensure && go build
- - run: cd go/docker-mongodb && prisma generate && dep ensure && go build
- - run: cd go/docker-mysql && prisma generate && dep ensure && go build
- - run: cd go/docker-postgres && prisma generate && dep ensure && go build
-
-workflows:
- version: 2
- build:
- jobs:
- - meta
- - node
- - typescript
- - flow
- - go
diff --git a/.coderabbit.yaml b/.coderabbit.yaml
new file mode 100644
index 000000000000..e39330b6b209
--- /dev/null
+++ b/.coderabbit.yaml
@@ -0,0 +1,23 @@
+# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
+# yaml template to refer to https://docs.coderabbit.ai/reference/yaml-template#enterprise
+language: 'en-US'
+reviews:
+ collapse_walkthrough: false
+ profile: 'chill'
+ high_level_summary: true
+ request_changes_workflow: true
+ poem: false
+ in_progress_fortune: false
+ sequence_diagrams: true
+ suggested_labels: false
+ suggested_reviewers: false
+ auto_review:
+ enabled: true
+ drafts: false
+ finishing_touches:
+ docstrings:
+ enabled: false
+ unit_tests:
+ enabled: false
+chat:
+ art: false
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000000..9d08a1a828a3
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/.github/prisma-configs/flow/seed.js b/.github/get-ppg-dev/.gitignore
similarity index 100%
rename from .github/prisma-configs/flow/seed.js
rename to .github/get-ppg-dev/.gitignore
diff --git a/.github/get-ppg-dev/index.js b/.github/get-ppg-dev/index.js
new file mode 100644
index 000000000000..855592cdc5c7
--- /dev/null
+++ b/.github/get-ppg-dev/index.js
@@ -0,0 +1,26 @@
+import { unstable_startServer } from '@prisma/dev'
+
+async function main() {
+ const server = await unstable_startServer({
+ persistenceMode: 'stateless',
+ })
+
+ // Emit only the Prisma-compatible URL for CI shell script to capture
+ console.log(server.ppg.url)
+
+ // Wait for shutdown signal
+ process.once('SIGTERM', async () => {
+ await server.close()
+ process.exit(0)
+ })
+
+ process.once('SIGINT', async () => {
+ await server.close()
+ process.exit(0)
+ })
+}
+
+main().catch((err) => {
+ console.error('❌ Failed to start dev server:', err)
+ process.exit(1)
+})
diff --git a/.github/get-ppg-dev/package.json b/.github/get-ppg-dev/package.json
new file mode 100644
index 000000000000..0ab72036898e
--- /dev/null
+++ b/.github/get-ppg-dev/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "get-ppg-dev",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "type": "module",
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "@prisma/dev": "latest"
+ }
+}
diff --git a/.github/prisma-configs/configure.sh b/.github/prisma-configs/configure.sh
deleted file mode 100644
index c441b7b38a12..000000000000
--- a/.github/prisma-configs/configure.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-
-# Node
-cp ./node/prisma.yml ../../node/cli-app/prisma
-cp ./node/prisma.yml ../../node/graphql/prisma
-cp ./node/prisma.yml ../../node/graphql-auth/prisma
-cp ./node/prisma.yml ../../node/graphql-subscriptions/prisma
-cp ./node/prisma.yml ../../node/rest-express/prisma
-cp ./node/prisma.yml ../../node/script/prisma
-cp ./node/mongo/prisma.yml ../../node/docker-mongodb/prisma
-cp ./node/mysql-and-postgres/prisma.yml ../../node/docker-mysql/prisma
-cp ./node/mysql-and-postgres/prisma.yml ../../node/docker-postgres/prisma
-cp ./node/grpc/prisma.yml ../../node/grpc/prisma
-
-# Node (seeding)
-cp ./node/seed.js ../../node/graphql/prisma
-cp ./node/graphql-auth/seed.js ../../node/graphql-auth/prisma
-cp ./node/graphql-subscriptions/seed.js ../../node/graphql-subscriptions/prisma
-cp ./node/seed.js ../../node/rest-express/prisma
-cp ./node/seed.js ../../node/script/prisma
-cp ./node/grpc/seed.js ../../node/grpc/prisma
-cp ./node/cli-app/seed.js ../../node/cli-app/prisma
-cp ./node/mongo/seed.js ../../node/docker-mongodb/prisma
-cp ./node/mysql-and-postgres/seed.js ../../node/docker-mysql/prisma
-cp ./node/mysql-and-postgres/seed.js ../../node/docker-postgres/prisma
-
-# TypeScript (prisma.yml)
-cp ./typescript/prisma.yml ../../typescript/cli-app/prisma
-cp ./typescript/graphql/prisma.yml ../../typescript/graphql/prisma
-cp ./typescript/graphql/prisma.yml ../../typescript/graphql-crud/prisma
-cp ./typescript/graphql-auth/prisma.yml ../../typescript/graphql-auth/prisma
-cp ./typescript/prisma.yml ../../typescript/graphql-subscriptions/prisma
-cp ./typescript/prisma.yml ../../typescript/script/prisma
-cp ./typescript/mongo/prisma.yml ../../typescript/docker-mongodb/prisma
-cp ./typescript/mysql-and-postgres/prisma.yml ../../typescript/docker-mysql/prisma
-cp ./typescript/mysql-and-postgres/prisma.yml ../../typescript/docker-postgres/prisma
-cp ./typescript/grpc/prisma.yml ../../typescript/grpc/prisma
-
-# TypeScript (seeding)
-cp ./typescript/seed.ts ../../typescript/graphql/prisma
-cp ./typescript/seed.ts ../../typescript/graphql-crud/prisma
-cp ./typescript/graphql-auth/seed.ts ../../typescript/graphql-auth/prisma
-cp ./typescript/graphql-subscriptions/seed.ts ../../typescript/graphql-subscriptions/prisma
-cp ./typescript/seed.ts ../../typescript/rest-express/prisma
-cp ./typescript/seed.ts ../../typescript/script/prisma
-cp ./typescript/grpc/seed.ts ../../typescript/grpc/prisma
-cp ./typescript/cli-app/seed.ts ../../typescript/cli-app/prisma
-cp ./typescript/mongo/seed.ts ../../typescript/docker-mongodb/prisma
-cp ./typescript/mysql-and-postgres/seed.ts ../../typescript/docker-mysql/prisma
-cp ./typescript/mysql-and-postgres/seed.ts ../../typescript/docker-postgres/prisma
-
-# TypeScript (tsconfig.json)
-cp ./typescript/tsconfig.json ../../typescript/cli-app
-cp ./typescript/tsconfig-graphql.json ../../typescript/graphql
-mv ../../typescript/graphql/tsconfig-graphql.json ../../typescript/graphql/tsconfig.json
-cp ./typescript/tsconfig-graphql.json ../../typescript/graphql-crud
-mv ../../typescript/graphql-crud/tsconfig-graphql.json ../../typescript/graphql-crud/tsconfig.json
-cp ./typescript/tsconfig-graphql.json ../../typescript/graphql-auth
-mv ../../typescript/graphql-auth/tsconfig-graphql.json ../../typescript/graphql-auth/tsconfig.json
-cp ./typescript/tsconfig-graphql.json ../../typescript/graphql-subscriptions
-mv ../../typescript/graphql-subscriptions/tsconfig-graphql.json ../../typescript/graphql-subscriptions/tsconfig.json
-cp ./typescript/tsconfig.json ../../typescript/script
-cp ./typescript/tsconfig.json ../../typescript/docker-mongodb
-cp ./typescript/tsconfig.json ../../typescript/docker-mysql
-cp ./typescript/tsconfig.json ../../typescript/docker-postgres
-cp ./typescript/tsconfig.json ../../typescript/grpc
-
-# TypeScript (graphqlgen)
-cp ./typescript/graphqlgen.yml ../../typescript/graphql-subscriptions
-
-# Flow (prisma.yml)
-cp ./flow/prisma.yml ../../flow/graphql/prisma
-cp ./flow/prisma.yml ../../flow/script/prisma
-
-# Flow (.flowconfig)
-cp ./flow/.flowconfig ../../flow/graphql
-cp ./flow/.flowconfig ../../flow/script
-
-# Go
-cp ./go/prisma.yml ../../go/cli-app/prisma
-cp ./go/prisma.yml ../../go/graphql/prisma
-cp ./go/prisma.yml ../../go/http-mux/prisma
-cp ./go/prisma.yml ../../go/rest-gin/prisma
-cp ./go/prisma.yml ../../go/script/prisma
-cp ./go/mongo/prisma.yml ../../go/docker-mongodb/prisma
-cp ./go/mysql-and-postgres/prisma.yml ../../go/docker-mysql/prisma
-cp ./go/mysql-and-postgres/prisma.yml ../../go/docker-postgres/prisma
-
-# Go (seeding)
-cp ./go/graphql/seed.go ../../go/graphql/prisma
-cp ./go/http-mux/seed.go ../../go/http-mux/prisma
-cp ./go/rest-gin/seed.go ../../go/rest-gin/prisma
-cp ./go/script/seed.go ../../go/script/prisma
-cp ./go/cli-app/seed.go ../../go/cli-app/prisma
diff --git a/.github/prisma-configs/flow/.flowconfig b/.github/prisma-configs/flow/.flowconfig
deleted file mode 100644
index 1454726c4c08..000000000000
--- a/.github/prisma-configs/flow/.flowconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-[ignore]
-# this is required until this issue gets fixed: https://github.com/prisma/prisma/issues/3617
-.*/node_modules/graphql/jsutils/keyValMap.js.flow
-
-[include]
-
-[libs]
-
-[lints]
-
-[options]
-
-[strict]
diff --git a/.github/prisma-configs/flow/prisma.yml b/.github/prisma-configs/flow/prisma.yml
deleted file mode 100644
index f58d63fc5490..000000000000
--- a/.github/prisma-configs/flow/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: flow-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- import: seed.graphql
\ No newline at end of file
diff --git a/.github/prisma-configs/go/cli-app/seed.go b/.github/prisma-configs/go/cli-app/seed.go
deleted file mode 100644
index dcff7537e003..000000000000
--- a/.github/prisma-configs/go/cli-app/seed.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package main
-
-import (
- "context"
-
- prisma "github.com/prisma/prisma-examples/go/cli-app/prisma-client"
-)
-
-func main() {
-
- client := prisma.New(nil)
- ctx := context.Background()
-
- text1 := "Join us for GraphQL Conf 2019 in Berlin"
- text2 := "Subscribe to GraphQL Weekly for community news"
-
- client.CreateTodo(prisma.TodoCreateInput{
- Text: text1,
- }).Exec(ctx)
-
- client.CreateTodo(prisma.TodoCreateInput{
- Text: text2,
- }).Exec(ctx)
-}
diff --git a/.github/prisma-configs/go/graphql/seed.go b/.github/prisma-configs/go/graphql/seed.go
deleted file mode 100644
index eaefcb729d48..000000000000
--- a/.github/prisma-configs/go/graphql/seed.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package main
-
-import (
- "context"
-
- prisma "github.com/prisma/prisma-examples/go/graphql/prisma-client"
-)
-
-func main() {
-
- client := prisma.New(nil)
- ctx := context.Background()
-
- published := true
-
- email1 := "alice@prisma.io"
- name1 := "Alice"
- title1 := "Join us for GraphQL Conf 2019 in Berlin"
- content1 := "https://www.graphqlconf.org/"
- client.CreateUser(prisma.UserCreateInput{
- Name: &name1,
- Email: email1,
- Posts: &prisma.PostCreateManyWithoutAuthorInput{
- Create: []prisma.PostCreateWithoutAuthorInput{
- prisma.PostCreateWithoutAuthorInput{
- Title: title1,
- Content: &content1,
- Published: &published,
- },
- },
- },
- }).Exec(ctx)
-
- email2 := "bob@prisma.io"
- name2 := "Bob"
- title2 := "Subscribe to GraphQL Weekly for community news"
- content2 := "https://graphqlweekly.com/"
- title3 := "Follow Prisma on Twitter"
- content3 := "https://twitter.com/prisma/"
- client.CreateUser(prisma.UserCreateInput{
- Name: &name2,
- Email: email2,
- Posts: &prisma.PostCreateManyWithoutAuthorInput{
- Create: []prisma.PostCreateWithoutAuthorInput{
- prisma.PostCreateWithoutAuthorInput{
- Title: title2,
- Content: &content2,
- Published: &published,
- },
- prisma.PostCreateWithoutAuthorInput{
- Title: title3,
- Content: &content3,
- },
- },
- },
- }).Exec(ctx)
-}
diff --git a/.github/prisma-configs/go/http-mux/seed.go b/.github/prisma-configs/go/http-mux/seed.go
deleted file mode 100644
index ab3e918a9410..000000000000
--- a/.github/prisma-configs/go/http-mux/seed.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package main
-
-import (
- "context"
-
- prisma "github.com/prisma/prisma-examples/go/http-mux/prisma-client"
-)
-
-func main() {
-
- client := prisma.New(nil)
- ctx := context.Background()
-
- published := true
-
- email1 := "alice@prisma.io"
- name1 := "Alice"
- title1 := "Join us for GraphQL Conf 2019 in Berlin"
- content1 := "https://www.graphqlconf.org/"
- client.CreateUser(prisma.UserCreateInput{
- Name: &name1,
- Email: email1,
- Posts: &prisma.PostCreateManyWithoutAuthorInput{
- Create: []prisma.PostCreateWithoutAuthorInput{
- prisma.PostCreateWithoutAuthorInput{
- Title: title1,
- Content: &content1,
- Published: &published,
- },
- },
- },
- }).Exec(ctx)
-
- email2 := "bob@prisma.io"
- name2 := "Bob"
- title2 := "Subscribe to GraphQL Weekly for community news"
- content2 := "https://graphqlweekly.com/"
- title3 := "Follow Prisma on Twitter"
- content3 := "https://twitter.com/prisma/"
- client.CreateUser(prisma.UserCreateInput{
- Name: &name2,
- Email: email2,
- Posts: &prisma.PostCreateManyWithoutAuthorInput{
- Create: []prisma.PostCreateWithoutAuthorInput{
- prisma.PostCreateWithoutAuthorInput{
- Title: title2,
- Content: &content2,
- Published: &published,
- },
- prisma.PostCreateWithoutAuthorInput{
- Title: title3,
- Content: &content3,
- },
- },
- },
- }).Exec(ctx)
-}
diff --git a/.github/prisma-configs/go/mongo/prisma.yml b/.github/prisma-configs/go/mongo/prisma.yml
deleted file mode 100644
index bd95197b12a2..000000000000
--- a/.github/prisma-configs/go/mongo/prisma.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: http://localhost:4466
-
-# Defines your models, each model is mapped to the database as a collection.
-datamodel: datamodel.prisma
-
-# Indicates that this Prisma server is based on MongoDB.
-databaseType: document
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: go-client
- output: ../prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- import: seed.graphql
\ No newline at end of file
diff --git a/.github/prisma-configs/go/mysql-and-postgres/prisma.yml b/.github/prisma-configs/go/mysql-and-postgres/prisma.yml
deleted file mode 100644
index 3fae5e4875f0..000000000000
--- a/.github/prisma-configs/go/mysql-and-postgres/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: http://localhost:4466
-
-# Defines your models, each model is mapped to the database as a collection.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: go-client
- output: ../prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- import: seed.graphql
\ No newline at end of file
diff --git a/.github/prisma-configs/go/prisma.yml b/.github/prisma-configs/go/prisma.yml
deleted file mode 100644
index d06f4e6330f9..000000000000
--- a/.github/prisma-configs/go/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: go-client
- output: ../prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- run: go run ./prisma/seed.go
\ No newline at end of file
diff --git a/.github/prisma-configs/go/rest-gin/seed.go b/.github/prisma-configs/go/rest-gin/seed.go
deleted file mode 100644
index e24c6a65a0b9..000000000000
--- a/.github/prisma-configs/go/rest-gin/seed.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package main
-
-import (
- "context"
-
- prisma "github.com/prisma/prisma-examples/go/rest-gin/prisma-client"
-)
-
-func main() {
-
- client := prisma.New(nil)
- ctx := context.Background()
-
- published := true
-
- email1 := "alice@prisma.io"
- name1 := "Alice"
- title1 := "Join us for GraphQL Conf 2019 in Berlin"
- content1 := "https://www.graphqlconf.org/"
- client.CreateUser(prisma.UserCreateInput{
- Name: &name1,
- Email: email1,
- Posts: &prisma.PostCreateManyWithoutAuthorInput{
- Create: []prisma.PostCreateWithoutAuthorInput{
- prisma.PostCreateWithoutAuthorInput{
- Title: title1,
- Content: &content1,
- Published: &published,
- },
- },
- },
- }).Exec(ctx)
-
- email2 := "bob@prisma.io"
- name2 := "Bob"
- title2 := "Subscribe to GraphQL Weekly for community news"
- content2 := "https://graphqlweekly.com/"
- title3 := "Follow Prisma on Twitter"
- content3 := "https://twitter.com/prisma/"
- client.CreateUser(prisma.UserCreateInput{
- Name: &name2,
- Email: email2,
- Posts: &prisma.PostCreateManyWithoutAuthorInput{
- Create: []prisma.PostCreateWithoutAuthorInput{
- prisma.PostCreateWithoutAuthorInput{
- Title: title2,
- Content: &content2,
- Published: &published,
- },
- prisma.PostCreateWithoutAuthorInput{
- Title: title3,
- Content: &content3,
- },
- },
- },
- }).Exec(ctx)
-}
diff --git a/.github/prisma-configs/go/script/seed.go b/.github/prisma-configs/go/script/seed.go
deleted file mode 100644
index a9d1da6fa255..000000000000
--- a/.github/prisma-configs/go/script/seed.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package main
-
-import (
- "context"
-
- prisma "github.com/prisma/prisma-examples/go/script/prisma-client"
-)
-
-func main() {
-
- client := prisma.New(nil)
- ctx := context.Background()
-
- published := true
-
- email1 := "alice@prisma.io"
- name1 := "Alice"
- title1 := "Join us for GraphQL Conf 2019 in Berlin"
- content1 := "https://www.graphqlconf.org/"
- client.CreateUser(prisma.UserCreateInput{
- Name: &name1,
- Email: email1,
- Posts: &prisma.PostCreateManyWithoutAuthorInput{
- Create: []prisma.PostCreateWithoutAuthorInput{
- prisma.PostCreateWithoutAuthorInput{
- Title: title1,
- Content: &content1,
- Published: &published,
- },
- },
- },
- }).Exec(ctx)
-
- email2 := "bob@prisma.io"
- name2 := "Bob"
- title2 := "Subscribe to GraphQL Weekly for community news"
- content2 := "https://graphqlweekly.com/"
- title3 := "Follow Prisma on Twitter"
- content3 := "https://twitter.com/prisma/"
- client.CreateUser(prisma.UserCreateInput{
- Name: &name2,
- Email: email2,
- Posts: &prisma.PostCreateManyWithoutAuthorInput{
- Create: []prisma.PostCreateWithoutAuthorInput{
- prisma.PostCreateWithoutAuthorInput{
- Title: title2,
- Content: &content2,
- Published: &published,
- },
- prisma.PostCreateWithoutAuthorInput{
- Title: title3,
- Content: &content3,
- },
- },
- },
- }).Exec(ctx)
-}
diff --git a/.github/prisma-configs/node/cli-app/seed.js b/.github/prisma-configs/node/cli-app/seed.js
deleted file mode 100644
index 603c7fec5cbd..000000000000
--- a/.github/prisma-configs/node/cli-app/seed.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const { prisma } = require('../src/generated/prisma-client')
-
-async function main() {
- await prisma.createTodo({ title: 'Subscribe to GraphQL Weekly' })
- await prisma.createTodo({ title: 'Join GraphQL Conf 2019' })
-}
-
-main()
\ No newline at end of file
diff --git a/.github/prisma-configs/node/graphql-auth/seed.js b/.github/prisma-configs/node/graphql-auth/seed.js
deleted file mode 100644
index 121b8665fc75..000000000000
--- a/.github/prisma-configs/node/graphql-auth/seed.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const { prisma } = require('../src/generated/prisma-client')
-
-async function main() {
- await prisma.createUser({
- email: "alice@prisma.io",
- name: "Alice",
- password: "$2b$10$dqyYw5XovLjpmkYNiRDEWuwKaRAvLaG45fnXE5b3KTccKZcRPka2m", // "secret42"
- posts: {
- create: {
- title: "Join us for GraphQL Conf 2019 in Berlin",
- content: "https://www.graphqlconf.org/",
- published: true
- }
- }
- })
- await prisma.createUser({
- email: "bob@prisma.io",
- name: "Bob",
- password: "$2b$10$o6KioO.taArzboM44Ig85O3ZFZYZpR3XD7mI8T29eP4znU/.xyJbW", // "secret43"
- posts: {
- create: [{
- title: "Subscribe to GraphQL Weekly for community news",
- content: "https://graphqlweekly.com/",
- published: true
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma",
- }]
- }
- })
-}
-
-main()
diff --git a/.github/prisma-configs/node/graphql-subscriptions/seed.js b/.github/prisma-configs/node/graphql-subscriptions/seed.js
deleted file mode 100644
index 3bf48612690b..000000000000
--- a/.github/prisma-configs/node/graphql-subscriptions/seed.js
+++ /dev/null
@@ -1,20 +0,0 @@
-const { prisma } = require('../src/generated/prisma-client')
-
-async function main() {
- await prisma.createPost({
- title: 'Join us for GraphQL Conf 2019 in Berlin',
- content: 'https://www.graphqlconf.org/',
- published: true,
- })
- await prisma.createPost({
- title: 'Subscribe to GraphQL Weekly for community news',
- content: 'https://graphqlweekly.com/',
- published: true,
- })
- await prisma.createPost({
- title: 'Follow Prisma on Twitter',
- content: 'https://twitter.com/prisma',
- })
-}
-
-main().catch(e => console.error(e))
diff --git a/.github/prisma-configs/node/grpc/prisma.yml b/.github/prisma-configs/node/grpc/prisma.yml
deleted file mode 100644
index d5110c94c819..000000000000
--- a/.github/prisma-configs/node/grpc/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: javascript-client
- output: ../server/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- run: node ./prisma/seed.js
\ No newline at end of file
diff --git a/.github/prisma-configs/node/grpc/seed.js b/.github/prisma-configs/node/grpc/seed.js
deleted file mode 100644
index 2ee2fcc87ff5..000000000000
--- a/.github/prisma-configs/node/grpc/seed.js
+++ /dev/null
@@ -1,31 +0,0 @@
-const { prisma } = require('../server/generated/prisma-client')
-
-async function main() {
- await prisma.createUser({
- email: "alice@prisma.io",
- name: "Alice",
- posts: {
- create: {
- title: "Join us for GraphQL Conf 2019 in Berlin",
- content: "https://www.graphqlconf.org/",
- published: true
- }
- }
- })
- await prisma.createUser({
- email: "bob@prisma.io",
- name: "Bob",
- posts: {
- create: [{
- title: "Subscribe to GraphQL Weekly for community news",
- content: "https://graphqlweekly.com/",
- published: true
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma",
- }]
- }
- })
-}
-
-main().catch(e => console.error(e))
diff --git a/.github/prisma-configs/node/mongo/prisma.yml b/.github/prisma-configs/node/mongo/prisma.yml
deleted file mode 100644
index 25929a7cb713..000000000000
--- a/.github/prisma-configs/node/mongo/prisma.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: http://localhost:4466
-
-# Defines your models, each model is mapped to the database as a collection.
-datamodel: datamodel.prisma
-
-# Indicates that this Prisma server is based on MongoDB.
-databaseType: document
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: javascript-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- run: node ./prisma/seed.js
\ No newline at end of file
diff --git a/.github/prisma-configs/node/mongo/seed.js b/.github/prisma-configs/node/mongo/seed.js
deleted file mode 100644
index 9508af2c5987..000000000000
--- a/.github/prisma-configs/node/mongo/seed.js
+++ /dev/null
@@ -1,44 +0,0 @@
-const { prisma } = require('../src/generated/prisma-client')
-
-async function main() {
- await prisma.createUser({
- name: 'Alice',
- email: 'alice@prisma.io',
- posts: {
- create: [
- {
- title: 'Join us for GraphQL Conf 2019 in Berlin',
- content: 'https://www.graphqlconf.org/',
- published: true
- },
- ],
- },
- })
-
- await prisma.createUser({
- name: 'Bob',
- email: 'bob@prisma.io',
- posts: {
- create: [
- {
- title: 'Subscribe to GraphQL Weekly for community news',
- content: 'https://graphqlweekly.com/',
- published: true,
- comments: {
- create: [{
- text: "Can recommend 💯",
- writtenBy: {
- connect: { email: "alice@prisma.io" }
- }
- }]
- }
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma"
- }
- ],
- },
- })
-}
-
-main()
\ No newline at end of file
diff --git a/.github/prisma-configs/node/mysql-and-postgres/prisma.yml b/.github/prisma-configs/node/mysql-and-postgres/prisma.yml
deleted file mode 100644
index 1acc1ee774a0..000000000000
--- a/.github/prisma-configs/node/mysql-and-postgres/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: http://localhost:4466
-
-# Defines your models, each model is mapped to the database as a collection.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: javascript-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- run: node ./prisma/seed.js
\ No newline at end of file
diff --git a/.github/prisma-configs/node/mysql-and-postgres/seed.js b/.github/prisma-configs/node/mysql-and-postgres/seed.js
deleted file mode 100644
index 9508af2c5987..000000000000
--- a/.github/prisma-configs/node/mysql-and-postgres/seed.js
+++ /dev/null
@@ -1,44 +0,0 @@
-const { prisma } = require('../src/generated/prisma-client')
-
-async function main() {
- await prisma.createUser({
- name: 'Alice',
- email: 'alice@prisma.io',
- posts: {
- create: [
- {
- title: 'Join us for GraphQL Conf 2019 in Berlin',
- content: 'https://www.graphqlconf.org/',
- published: true
- },
- ],
- },
- })
-
- await prisma.createUser({
- name: 'Bob',
- email: 'bob@prisma.io',
- posts: {
- create: [
- {
- title: 'Subscribe to GraphQL Weekly for community news',
- content: 'https://graphqlweekly.com/',
- published: true,
- comments: {
- create: [{
- text: "Can recommend 💯",
- writtenBy: {
- connect: { email: "alice@prisma.io" }
- }
- }]
- }
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma"
- }
- ],
- },
- })
-}
-
-main()
\ No newline at end of file
diff --git a/.github/prisma-configs/node/prisma.yml b/.github/prisma-configs/node/prisma.yml
deleted file mode 100644
index b32ebf8f6008..000000000000
--- a/.github/prisma-configs/node/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: javascript-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- run: node ./prisma/seed.js
\ No newline at end of file
diff --git a/.github/prisma-configs/node/seed.js b/.github/prisma-configs/node/seed.js
deleted file mode 100644
index fb509606798b..000000000000
--- a/.github/prisma-configs/node/seed.js
+++ /dev/null
@@ -1,31 +0,0 @@
-const { prisma } = require('../src/generated/prisma-client')
-
-async function main() {
- await prisma.createUser({
- email: "alice@prisma.io",
- name: "Alice",
- posts: {
- create: {
- title: "Join us for GraphQL Conf 2019 in Berlin",
- content: "https://www.graphqlconf.org/",
- published: true
- }
- }
- })
- await prisma.createUser({
- email: "bob@prisma.io",
- name: "Bob",
- posts: {
- create: [{
- title: "Subscribe to GraphQL Weekly for community news",
- content: "https://graphqlweekly.com/",
- published: true
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma",
- }]
- }
- })
-}
-
-main().catch(e => console.error(e))
diff --git a/.github/prisma-configs/typescript/cli-app/seed.ts b/.github/prisma-configs/typescript/cli-app/seed.ts
deleted file mode 100644
index 3485da19430d..000000000000
--- a/.github/prisma-configs/typescript/cli-app/seed.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { prisma } from '../src/generated/prisma-client'
-
-async function main() {
- await prisma.createTodo({ title: 'Subscribe to GraphQL Weekly' })
- await prisma.createTodo({ title: 'Join GraphQL Conf 2019' })
-}
-
-main()
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/graphql-auth/prisma.yml b/.github/prisma-configs/typescript/graphql-auth/prisma.yml
deleted file mode 100644
index d5b2a6aae33e..000000000000
--- a/.github/prisma-configs/typescript/graphql-auth/prisma.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: typescript-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
- - npx nexus-prisma-generate --client ./src/generated/prisma-client --output ./src/generated/nexus-prisma # Runs the codegen tool from nexus-prisma.
-
-# Seeds initial data into the database by running a script.
-seed:
- run: yarn ts-node ./prisma/seed.ts
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/graphql-auth/seed.ts b/.github/prisma-configs/typescript/graphql-auth/seed.ts
deleted file mode 100644
index 5d2e520e419d..000000000000
--- a/.github/prisma-configs/typescript/graphql-auth/seed.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { prisma } from '../src/generated/prisma-client'
-
-async function main() {
- await prisma.createUser({
- email: "alice@prisma.io",
- name: "Alice",
- password: "$2b$10$dqyYw5XovLjpmkYNiRDEWuwKaRAvLaG45fnXE5b3KTccKZcRPka2m", // "secret42"
- posts: {
- create: {
- title: "Join us for GraphQL Conf 2019 in Berlin",
- content: "https://www.graphqlconf.org/",
- published: true
- }
- }
- })
- await prisma.createUser({
- email: "bob@prisma.io",
- name: "Bob",
- password: "$2b$10$o6KioO.taArzboM44Ig85O3ZFZYZpR3XD7mI8T29eP4znU/.xyJbW", // "secret43"
- posts: {
- create: [{
- title: "Subscribe to GraphQL Weekly for community news",
- content: "https://graphqlweekly.com/",
- published: true
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma",
- }]
- }
- })
-}
-
-main()
diff --git a/.github/prisma-configs/typescript/graphql-subscriptions/seed.ts b/.github/prisma-configs/typescript/graphql-subscriptions/seed.ts
deleted file mode 100644
index 72e2e29495ef..000000000000
--- a/.github/prisma-configs/typescript/graphql-subscriptions/seed.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { prisma } from '../src/generated/prisma-client'
-
-async function main() {
- await prisma.createPost({
- title: 'Join us for GraphQL Conf 2019 in Berlin',
- content: 'https://www.graphqlconf.org/',
- published: true,
- })
- await prisma.createPost({
- title: 'Subscribe to GraphQL Weekly for community news',
- content: 'https://graphqlweekly.com/',
- published: true,
- })
- await prisma.createPost({
- title: 'Follow Prisma on Twitter',
- content: 'https://twitter.com/prisma',
- })
-}
-
-main().catch(e => console.error(e))
diff --git a/.github/prisma-configs/typescript/graphql/prisma.yml b/.github/prisma-configs/typescript/graphql/prisma.yml
deleted file mode 100644
index d5b2a6aae33e..000000000000
--- a/.github/prisma-configs/typescript/graphql/prisma.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: typescript-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
- - npx nexus-prisma-generate --client ./src/generated/prisma-client --output ./src/generated/nexus-prisma # Runs the codegen tool from nexus-prisma.
-
-# Seeds initial data into the database by running a script.
-seed:
- run: yarn ts-node ./prisma/seed.ts
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/graphqlgen.yml b/.github/prisma-configs/typescript/graphqlgen.yml
deleted file mode 100644
index 9f462336625c..000000000000
--- a/.github/prisma-configs/typescript/graphqlgen.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-# The target programming language for the generated code.
-language: typescript
-
-# The file path pointing to your GraphQL schema.
-schema: ./src/schema.graphql
-
-# Type definition for the resolver context object.
-context: ./src/types.ts:Context
-
-# Map SDL types from the GraphQL schema to TS models.
-models:
- files:
- - ./src/generated/prisma-client
- - ./src/types.ts
-
-# Generated typings for resolvers and default resolver implementations
-# DO NOT EDIT THIS FILE but just _import_ from it into your own source files.
-output: ./src/generated/graphqlgen.ts
-
-# Temporary scaffolded resolvers to copy and paste into your own source files.
-resolver-scaffolding:
- output: ./src/generated/tmp-resolvers/
- layout: file-per-type
diff --git a/.github/prisma-configs/typescript/grpc/prisma.yml b/.github/prisma-configs/typescript/grpc/prisma.yml
deleted file mode 100644
index 8a65f858990e..000000000000
--- a/.github/prisma-configs/typescript/grpc/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: typescript-client
- output: ../server/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- run: yarn ts-node ./prisma/seed.ts
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/grpc/seed.ts b/.github/prisma-configs/typescript/grpc/seed.ts
deleted file mode 100644
index fb9d77c6a2b9..000000000000
--- a/.github/prisma-configs/typescript/grpc/seed.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { prisma } from '../server/generated/prisma-client'
-
-async function main() {
- await prisma.createUser({
- email: "alice@prisma.io",
- name: "Alice",
- posts: {
- create: {
- title: "Join us for GraphQL Conf 2019 in Berlin",
- content: "https://www.graphqlconf.org/",
- published: true
- }
- }
- })
- await prisma.createUser({
- email: "bob@prisma.io",
- name: "Bob",
- posts: {
- create: [{
- title: "Subscribe to GraphQL Weekly for community news",
- content: "https://graphqlweekly.com/",
- published: true
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma",
- }]
- }
- })
-}
-
-main().catch(e => console.error(e))
diff --git a/.github/prisma-configs/typescript/mongo/prisma.yml b/.github/prisma-configs/typescript/mongo/prisma.yml
deleted file mode 100644
index e5bbd8d69b35..000000000000
--- a/.github/prisma-configs/typescript/mongo/prisma.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: http://localhost:4466
-
-# Defines your models, each model is mapped to the database as a collection.
-datamodel: datamodel.prisma
-
-# Indicates that this Prisma server is based on MongoDB.
-databaseType: document
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: typescript-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- run: yarn ts-node ./prisma/seed.ts
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/mongo/seed.ts b/.github/prisma-configs/typescript/mongo/seed.ts
deleted file mode 100644
index c6aa9e6fb98e..000000000000
--- a/.github/prisma-configs/typescript/mongo/seed.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { prisma } from '../src/generated/prisma-client'
-
-async function main() {
- await prisma.createUser({
- name: 'Alice',
- email: 'alice@prisma.io',
- posts: {
- create: [
- {
- title: 'Join us for GraphQL Conf 2019 in Berlin',
- content: 'https://www.graphqlconf.org/',
- published: true
- },
- ],
- },
- })
-
- await prisma.createUser({
- name: 'Bob',
- email: 'bob@prisma.io',
- posts: {
- create: [
- {
- title: 'Subscribe to GraphQL Weekly for community news',
- content: 'https://graphqlweekly.com/',
- published: true,
- comments: {
- create: [{
- text: "Can recommend 💯",
- writtenBy: {
- connect: { email: "alice@prisma.io" }
- }
- }]
- }
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma"
- }
- ],
- },
- })
-}
-
-main()
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/mysql-and-postgres/prisma.yml b/.github/prisma-configs/typescript/mysql-and-postgres/prisma.yml
deleted file mode 100644
index 00aaafdb7bee..000000000000
--- a/.github/prisma-configs/typescript/mysql-and-postgres/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: http://localhost:4466
-
-# Defines your models, each model is mapped to the database as a collection.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: typescript-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- run: yarn ts-node ./prisma/seed.ts
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/mysql-and-postgres/seed.ts b/.github/prisma-configs/typescript/mysql-and-postgres/seed.ts
deleted file mode 100644
index c6aa9e6fb98e..000000000000
--- a/.github/prisma-configs/typescript/mysql-and-postgres/seed.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { prisma } from '../src/generated/prisma-client'
-
-async function main() {
- await prisma.createUser({
- name: 'Alice',
- email: 'alice@prisma.io',
- posts: {
- create: [
- {
- title: 'Join us for GraphQL Conf 2019 in Berlin',
- content: 'https://www.graphqlconf.org/',
- published: true
- },
- ],
- },
- })
-
- await prisma.createUser({
- name: 'Bob',
- email: 'bob@prisma.io',
- posts: {
- create: [
- {
- title: 'Subscribe to GraphQL Weekly for community news',
- content: 'https://graphqlweekly.com/',
- published: true,
- comments: {
- create: [{
- text: "Can recommend 💯",
- writtenBy: {
- connect: { email: "alice@prisma.io" }
- }
- }]
- }
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma"
- }
- ],
- },
- })
-}
-
-main()
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/prisma.yml b/.github/prisma-configs/typescript/prisma.yml
deleted file mode 100644
index 0627df6eb77d..000000000000
--- a/.github/prisma-configs/typescript/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: typescript-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- run: yarn ts-node ./prisma/seed.ts
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/seed.ts b/.github/prisma-configs/typescript/seed.ts
deleted file mode 100644
index 00c2b7dc5833..000000000000
--- a/.github/prisma-configs/typescript/seed.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { prisma } from '../src/generated/prisma-client'
-
-
-async function main() {
- await prisma.createUser({
- email: "alice@prisma.io",
- name: "Alice",
- posts: {
- create: {
- title: "Join us for GraphQL Conf 2019 in Berlin",
- content: "https://www.graphqlconf.org/",
- published: true
- }
- }
- })
- await prisma.createUser({
- email: "bob@prisma.io",
- name: "Bob",
- posts: {
- create: [{
- title: "Subscribe to GraphQL Weekly for community news",
- content: "https://graphqlweekly.com/",
- published: true
- }, {
- title: "Follow Prisma on Twitter",
- content: "https://twitter.com/prisma",
- }]
- }
- })
-}
-
-main().catch(e => console.error(e))
diff --git a/.github/prisma-configs/typescript/tsconfig-graphql.json b/.github/prisma-configs/typescript/tsconfig-graphql.json
deleted file mode 100644
index 0064ec16f4e6..000000000000
--- a/.github/prisma-configs/typescript/tsconfig-graphql.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "compilerOptions": {
- "sourceMap": true,
- "outDir": "dist",
- "lib": ["esnext", "dom"],
- // "strict": true, // `strict` is commented because of this issue: https://github.com/prisma/prisma/issues/3774; all its options except `strictNullChecks` & `strictPropertyInitialization` are explicitly set below.
- "noImplicitAny": true,
- "noImplicitThis": true,
- "alwaysStrict": true,
- "strictBindCallApply": true,
- "strictFunctionTypes": true,
- "skipLibCheck": true // `skipLibCheck` is enabled until this is issue is fixed: https://github.com/prisma/nexus-prisma/issues/82
- }
-}
\ No newline at end of file
diff --git a/.github/prisma-configs/typescript/tsconfig.json b/.github/prisma-configs/typescript/tsconfig.json
deleted file mode 100644
index 669f46efc390..000000000000
--- a/.github/prisma-configs/typescript/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "compilerOptions": {
- "sourceMap": true,
- "outDir": "dist",
- "strict": true,
- "lib": ["esnext", "dom"]
- }
-}
\ No newline at end of file
diff --git a/.github/readmes/_using-the-graphql-api-auth.md b/.github/readmes/_using-the-graphql-api-auth.md
deleted file mode 100644
index f213b6f26c18..000000000000
--- a/.github/readmes/_using-the-graphql-api-auth.md
+++ /dev/null
@@ -1,173 +0,0 @@
-### 5. Using the GraphQL API
-
-The schema that specifies the API operations of your GraphQL server is defined in [`./src/schema.graphql`](./src/schema.graphql). Below are a number of operations that you can send to the API using the GraphQL Playground.
-
-Feel free to adjust any operation by adding or removing fields. The GraphQL Playground helps you with its auto-completion and query validation features.
-
-#### Retrieve all published posts and their authors
-
-```graphql
-query {
- feed {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-See more API operations
-
-#### Register a new user
-
-You can send the following mutation in the Playground to sign up a new user and retrieve an authentication token for them:
-
-```graphql
-mutation {
- signup(name: "Alice", email: "alice@prisma.io", password: "graphql") {
- token
- }
-}
-```
-
-#### Log in an existing user
-
-This mutation will log in an existing user by requesting a new authentication token for them:
-
-```graphql
-mutation {
- login(email: "alice@prisma.io", password: "graphql") {
- token
- }
-}
-```
-
-#### Check whether a user is currently logged in with the `me` query
-
-For this query, you need to make sure a valid authentication token is sent along with the `Bearer`-prefix in the `Authorization` header of the request:
-
-```json
-{
- "Authorization": "Bearer __YOUR_TOKEN__"
-}
-```
-
-With a real token, this looks similar to this:
-
-```json
-{
- "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJjanAydHJyczFmczE1MGEwM3kxaWl6c285IiwiaWF0IjoxNTQzNTA5NjY1fQ.Vx6ad6DuXA0FSQVyaIngOHYVzjKwbwq45flQslnqX04"
-}
-```
-
-Inside the Playground, you can set HTTP headers in the bottom-left corner:
-
-
-
-Once you've set the header, you can send the following query to check whether the token is valid:
-
-```graphql
-{
- me {
- id
- name
- email
- }
-}
-```
-
-#### Create a new draft
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground.
-
-```graphql
-mutation {
- createDraft(
- title: "Join the Prisma Slack"
- content: "https://slack.prisma.io/"
- authorEmail: "alice@prisma.io"
- ) {
- id
- published
- }
-}
-```
-
-#### Publish an existing draft
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground. The authentication token must belong to the user who created the post.
-
-```graphql
-mutation {
- publish(id: "__POST_ID__") {
- id
- published
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-#### Search for posts with a specific title or content
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground.
-
-```graphql
-{
- filterPosts(searchString: "graphql") {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-#### Retrieve a single post
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground.
-
-```graphql
-{
- posts(id: "__POST_ID__") {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-#### Delete a post
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground. The authentication token must belong to the user who created the post.
-
-```graphql
-mutation {
- deletePost(id: "__POST_ID__") {
- id
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-
\ No newline at end of file
diff --git a/.github/readmes/_using-the-graphql-api-crud.md b/.github/readmes/_using-the-graphql-api-crud.md
deleted file mode 100644
index f4ddcb5158d0..000000000000
--- a/.github/readmes/_using-the-graphql-api-crud.md
+++ /dev/null
@@ -1,133 +0,0 @@
-### 5. Using the CRUD GraphQL API
-
-The schema that specifies the API operations of your GraphQL server is defined in [`./src/schema.graphql`](./src/schema.graphql). Below are a number of operations that you can send to the API using the GraphQL Playground.
-
-Feel free to adjust any operation by adding or removing fields. The GraphQL Playground helps you with its auto-completion and query validation features.
-
-#### Retrieve all posts and their authors
-
-```graphql
-query {
- posts {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-See more API operations
-
-#### Create a new user
-
-```graphql
-mutation {
- createUser(data: {
- name: "Sarah"
- email: "sarah@prisma.io"
- }) {
- id
- }
-}
-```
-
-#### Create a new post
-
-```graphql
-mutation {
- createPost(data: {
- title: "Join the Prisma Slack"
- content: "https://slack.prisma.io/"
- author: {
- connect: { email: "alice@prisma.io" }
- }
- }) {
- id
- published
- author {
- id
- name
- }
- }
-}
-```
-
-#### Update an existing draft
-
-```graphql
-mutation {
- updatePost(
- where: { id: "__POST_ID__" }
- data: { published: true }
- ) {
- id
- published
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `posts`-query.
-
-#### Search for posts with a specific title or content
-
-```graphql
-{
- posts(where: {
- OR: [{
- title_contains: "graphql"
- }, {
- content_contains: "graphql"
- }]
- }) {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-#### Retrieve a single post
-
-```graphql
-{
- post(where: { id: "__POST_ID__"}) {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `posts`-query.
-
-#### Delete a post
-
-```graphql
-mutation {
- deletePost(where: { id: "__POST_ID__"}) {
- id
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `posts`-query.
-
-
\ No newline at end of file
diff --git a/.github/readmes/_using-the-graphql-api-subs.md b/.github/readmes/_using-the-graphql-api-subs.md
deleted file mode 100644
index 755f67b3ba36..000000000000
--- a/.github/readmes/_using-the-graphql-api-subs.md
+++ /dev/null
@@ -1,194 +0,0 @@
-### 5. Using the GraphQL API
-
-The schema that specifies the API operations of your GraphQL server is defined in [`./src/schema.graphql`](./src/schema.graphql). Below are a number of operations that you can send to the API using the GraphQL Playground.
-
-Feel free to adjust any operation by adding or removing fields. The GraphQL Playground helps you with its auto-completion and query validation features.
-
-#### Retrieve all published posts and their authors
-
-```graphql
-query {
- feed {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-See more API operations
-
-#### Register a new user
-
-You can send the following mutation in the Playground to sign up a new user and retrieve an authentication token for them:
-
-```graphql
-mutation {
- signup(name: "Alice", email: "alice@prisma.io", password: "graphql") {
- token
- }
-}
-```
-
-#### Log in an existing user
-
-This mutation will log in an existing user by requesting a new authentication token for them:
-
-```graphql
-mutation {
- login(email: "alice@prisma.io", password: "graphql") {
- token
- }
-}
-```
-
-#### Check whether a user is currently logged in with the `me` query
-
-For this query, you need to make sure a valid authentication token is sent along with the `Bearer`-prefix in the `Authorization` header of the request. Inside the Playground, you can set HTTP headers in the bottom-left corner:
-
-
-
-Once you've set the header, you can send the following query to check whether the token is valid:
-
-```graphql
-{
- me {
- id
- name
- email
- }
-}
-```
-
-#### Create a new draft
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground.
-
-```graphql
-mutation {
- createDraft(
- title: "Join the Prisma Slack"
- content: "https://slack.prisma.io/"
- authorEmail: "alice@prisma.io"
- ) {
- id
- published
- }
-}
-```
-
-#### Publish an existing draft
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground. The authentication token must belong to the user who created the post.
-
-```graphql
-mutation {
- publish(id: "__POST_ID__") {
- id
- published
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-#### Search for posts with a specific title or content
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground.
-
-```graphql
-{
- filterPosts(searchString: "graphql") {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-#### Retrieve a single post
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground.
-
-```graphql
-{
- posts(id: "__POST_ID__") {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-#### Delete a post
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground. The authentication token must belong to the user who created the post.
-
-```graphql
-mutation {
- deletePost(id: "__POST_ID__") {
- id
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-
-
-### 6. Testing GraphQL subscriptions in the Playground
-
-To test the `post` subscription, you need to send a subscription query in the Playground, e.g.:
-
-```graphql
-subscription {
- posts {
- id
- createdAt
- title
- content
- published
- }
-}
-```
-
-When hitting the _Play_-button, you won't see an immediate response. Instead there's a loading indicator in the response pane of the Playground:
-
-
-
-Now, whenever a post is created (or updated), e.g. with this mutation (you can run it in another tab):
-
-```graphql
-mutation {
- createDraft(
- title: "Join the Prisma community on Slack"
- content: "https://slack.prisma.io/"
- ) {
- id
- }
-}
-```
-
-You will see the results appear in the tab where the subscription is running:
-
-
\ No newline at end of file
diff --git a/.github/readmes/_using-the-graphql-api.md b/.github/readmes/_using-the-graphql-api.md
deleted file mode 100644
index 90fd72242b21..000000000000
--- a/.github/readmes/_using-the-graphql-api.md
+++ /dev/null
@@ -1,118 +0,0 @@
-### 5. Using the GraphQL API
-
-The schema that specifies the API operations of your GraphQL server is defined in [`./src/schema.graphql`](./src/schema.graphql). Below are a number of operations that you can send to the API using the GraphQL Playground.
-
-Feel free to adjust any operation by adding or removing fields. The GraphQL Playground helps you with its auto-completion and query validation features.
-
-#### Retrieve all published posts and their authors
-
-```graphql
-query {
- feed {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-See more API operations
-
-#### Create a new user
-
-```graphql
-mutation {
- signupUser(
- name: "Sarah"
- email: "sarah@prisma.io"
- ) {
- id
- }
-}
-```
-
-#### Create a new draft
-
-```graphql
-mutation {
- createDraft(
- title: "Join the Prisma Slack"
- content: "https://slack.prisma.io/"
- authorEmail: "alice@prisma.io"
- ) {
- id
- published
- }
-}
-```
-
-#### Publish an existing draft
-
-```graphql
-mutation {
- publish(id: "__POST_ID__") {
- id
- published
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-#### Search for posts with a specific title or content
-
-```graphql
-{
- filterPosts(searchString: "graphql") {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-#### Retrieve a single post
-
-```graphql
-{
- post(id: "__POST_ID__") {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-#### Delete a post
-
-```graphql
-mutation {
- deletePost(id: "__POST_ID__") {
- id
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-
\ No newline at end of file
diff --git a/.github/readmes/_using-the-rest-api.md b/.github/readmes/_using-the-rest-api.md
deleted file mode 100644
index 42b7923380b4..000000000000
--- a/.github/readmes/_using-the-rest-api.md
+++ /dev/null
@@ -1,27 +0,0 @@
-### 5. Using the REST API
-
-#### `GET`
-
-- `/post/:id`: Fetch a single post by its `id`
-- `/feed`: Fetch all _published_ posts
-- `/filterPosts?searchString={searchString}`: Filter posts by `title` or `content`
-
-#### `POST`
-
-- `/post`: Create a new post
- - Body:
- - `title: String` (required): The title of the post
- - `content: String` (optional): The content of the post
- - `authorEmail: String` (required): The email of the user that creates the post
-- `/user`: Create a new user
- - Body:
- - `email: String` (required): The email address of the user
- - `name: String` (optional): The name of the user
-
-#### `PUT`
-
-- `/publish/:id`: Publish a post by its `id`
-
-#### `DELETE`
-
-- `/post/:id`: Delete a post by its `id`
\ No newline at end of file
diff --git a/.github/readmes/flow/_next-steps.md b/.github/readmes/flow/_next-steps.md
deleted file mode 100644
index 75839deb0901..000000000000
--- a/.github/readmes/flow/_next-steps.md
+++ /dev/null
@@ -1,5 +0,0 @@
-## Next steps
-
-- [Use Prisma with an existing database](https://www.prisma.io/docs/-f003/)
-- [Explore the Prisma client API](https://www.prisma.io/client/client-flow)
-- [Learn more about the GraphQL schema](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e/)
\ No newline at end of file
diff --git a/.github/readmes/flow/_setup-1.md b/.github/readmes/flow/_setup-1.md
deleted file mode 100644
index f5fcb69916cb..000000000000
--- a/.github/readmes/flow/_setup-1.md
+++ /dev/null
@@ -1,13 +0,0 @@
-## How to use
-
-### 1. Download example & install dependencies
-
-Clone the repository:
-
-```
-git clone git@github.com:prisma/prisma-examples.git
-```
-
-Install Node dependencies:
-
-```
\ No newline at end of file
diff --git a/.github/readmes/flow/_setup-2.md b/.github/readmes/flow/_setup-2.md
deleted file mode 100644
index d05c2a47bc45..000000000000
--- a/.github/readmes/flow/_setup-2.md
+++ /dev/null
@@ -1,64 +0,0 @@
-npm install
-```
-
-### 2. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 3. Set up database & deploy Prisma datamodel
-
-For this example, you'll use a free _demo database_ (AWS Aurora) hosted in Prisma Cloud. To set up your database, run:
-
-```
-prisma deploy
-```
-
-Then, follow these steps in the interactive CLI wizard:
-
-1. Select **Demo server**
-1. **Authenticate** with Prisma Cloud in your browser (if necessary)
-1. Back in your terminal, **confirm all suggested values**
-
-
- Alternative: Run Prisma locally via Docker
-
-1. Ensure you have Docker installed on your machine. If not, you can get it from [here](https://store.docker.com/search?offering=community&type=edition).
-1. Create `docker-compose.yml` for MySQL (see [here](https://www.prisma.io/docs/prisma-server/database-connector-POSTGRES-jgfr/) for Postgres):
- ```yml
- version: '3'
- services:
- prisma:
- image: prismagraphql/prisma:1.27
- restart: always
- ports:
- - "4466:4466"
- environment:
- PRISMA_CONFIG: |
- port: 4466
- databases:
- default:
- connector: mysql
- host: mysql
- port: 3306
- user: root
- password: prisma
- migrations: true
- mysql:
- image: mysql:5.7
- restart: always
- environment:
- MYSQL_ROOT_PASSWORD: prisma
- volumes:
- - mysql:/var/lib/mysql
- volumes:
- mysql:
- ```
-1. Run `docker-compose up -d`
-1. Set the `endpoint` in `prisma.yml` to `http://localhost:4466`
-1. Run `prisma deploy`
-
-
\ No newline at end of file
diff --git a/.github/readmes/flow/_start-graphql-server.md b/.github/readmes/flow/_start-graphql-server.md
deleted file mode 100644
index de3531c94450..000000000000
--- a/.github/readmes/flow/_start-graphql-server.md
+++ /dev/null
@@ -1,9 +0,0 @@
-### 4. Start the GraphQL server
-
-Launch your GraphQL server with this command:
-
-```
-npm run start
-```
-
-Navigate to [http://localhost:4000](http://localhost:4000) in your browser to explore the API of your GraphQL server in a [GraphQL Playground](https://github.com/prisma/graphql-playground).
\ No newline at end of file
diff --git a/.github/readmes/flow/graphql/README.md b/.github/readmes/flow/graphql/README.md
deleted file mode 100644
index 420fafaa0e23..000000000000
--- a/.github/readmes/flow/graphql/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# GraphQL Server Example
-
-This example shows how to implement a **GraphQL server with Flow** based on Prisma & [graphql-yoga](https://github.com/prisma/graphql-yoga).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/flow/graphql
-__INLINE(../_setup-2.md)__
-
-__INLINE(../_start-graphql-server.md)__
-
-__INLINE(../../_using-the-graphql-api-subs.md)__
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/flow/script/README.md b/.github/readmes/flow/script/README.md
deleted file mode 100644
index 5cf34a42e2d3..000000000000
--- a/.github/readmes/flow/script/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Simple Flow Script Example
-
-This example shows how to use the Prisma client in a **simple Flow script** to read and write data in a database.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/flow/script
-__INLINE(../_setup-2.md)__
-
-### 4. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/go/_next-steps.md b/.github/readmes/go/_next-steps.md
deleted file mode 100644
index 9426bab67422..000000000000
--- a/.github/readmes/go/_next-steps.md
+++ /dev/null
@@ -1,5 +0,0 @@
-## Next steps
-
-- [Use Prisma with an existing database](https://www.prisma.io/docs/-g003/)
-- [Explore the Prisma client API](https://www.prisma.io/client/client-go)
-- [Learn more about the GraphQL schema](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e/)
\ No newline at end of file
diff --git a/.github/readmes/go/_setup-1.md b/.github/readmes/go/_setup-1.md
deleted file mode 100644
index 8ba8009853de..000000000000
--- a/.github/readmes/go/_setup-1.md
+++ /dev/null
@@ -1,13 +0,0 @@
-## How to use
-
-### 1. Download example & install dependencies
-
-Clone the repository:
-
-```
-git clone git@github.com:prisma/prisma-examples.git
-```
-
-Ensure dependencies are available and up-to-date:
-
-```
\ No newline at end of file
diff --git a/.github/readmes/go/_setup-2.md b/.github/readmes/go/_setup-2.md
deleted file mode 100644
index 4f72d492bba9..000000000000
--- a/.github/readmes/go/_setup-2.md
+++ /dev/null
@@ -1,65 +0,0 @@
-dep ensure -update
-```
-
-### 2. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via Homebrew or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-brew install prisma
-brew tap
-```
-
-### 3. Set up database & deploy Prisma datamodel
-
-For this example, you'll use a free _demo database_ (AWS Aurora) hosted in Prisma Cloud. To set up your database, run:
-
-```
-prisma deploy
-```
-
-Then, follow these steps in the interactive CLI wizard:
-
-1. Select **Demo server**
-1. **Authenticate** with Prisma Cloud in your browser (if necessary)
-1. Back in your terminal, **confirm all suggested values**
-
-
- Alternative: Run Prisma locally via Docker
-
-1. Ensure you have Docker installed on your machine. If not, you can get it from [here](https://store.docker.com/search?offering=community&type=edition).
-1. Create `docker-compose.yml` for MySQL (see [here](https://www.prisma.io/docs/prisma-server/database-connector-POSTGRES-jgfr/) for Postgres):
- ```yml
- version: '3'
- services:
- prisma:
- image: prismagraphql/prisma:1.27
- restart: always
- ports:
- - "4466:4466"
- environment:
- PRISMA_CONFIG: |
- port: 4466
- databases:
- default:
- connector: mysql
- host: mysql
- port: 3306
- user: root
- password: prisma
- migrations: true
- mysql:
- image: mysql:5.7
- restart: always
- environment:
- MYSQL_ROOT_PASSWORD: prisma
- volumes:
- - mysql:/var/lib/mysql
- volumes:
- mysql:
- ```
-1. Run `docker-compose up -d`
-1. Set the `endpoint` in `prisma.yml` to `http://localhost:4466`
-1. Run `prisma deploy`
-
-
\ No newline at end of file
diff --git a/.github/readmes/go/cli-app/README.md b/.github/readmes/go/cli-app/README.md
deleted file mode 100644
index db3685a4c3b7..000000000000
--- a/.github/readmes/go/cli-app/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Simple TODO-App Example (CLI)
-
-This example shows how to implement a **TODO-app as a CLI tool** with Golang and Prisma.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/go/cli-app
-__INLINE(../_setup-2.md)__
-
-### 4. Use the CLI app
-
-```
-go run main.go
-```
-
-#### Add a `Todo` item
-
-```
-go run main.go create Groceries
-```
-
-#### List all `Todo` items
-
-```
-go run main.go list
-```
-
-#### Delete a `Todo` item
-
-```
-go run main.go delete Groceries
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/go/docker-mongodb/README.md b/.github/readmes/go/docker-mongodb/README.md
deleted file mode 100644
index 806365613a1c..000000000000
--- a/.github/readmes/go/docker-mongodb/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# MongoDB with Docker Example
-
-This example shows how to **set up Prisma using Docker and MongoDB** locally on your machine. It then uses the Prisma client in a simple Go script to read and write data in the database.
-
-> When using MongoDB with Prisma, you use a [new datamodel format](https://www.prisma.io/docs/-b6a7/). Learn more in the [docs](https://www.prisma.io/docs/-b6o5/).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/go/docker-mongodb
-dep ensure -update
-```
-
-### 2. Launch Prisma with Docker
-
-This example is based on Docker. If you don't have Docker installed, you can get it from [here](https://store.docker.com/search?type=edition&offering=community). Use the Docker Compose CLI to launch the Docker containers specified in [docker-compose.yml](./docker-compose.yml):
-
-```
-docker-compose up -d
-```
-
-### 3. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via Homebrew or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-brew install prisma
-brew tap
-```
-
-### 4. Set up database & deploy Prisma datamodel
-
-To deploy the datamodel for this example, run the following command:
-
-```
-prisma deploy
-```
-
-### 5. Run the script
-
-Execute the script with this command:
-
-```
-go run main.go
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/go/docker-mysql/README.md b/.github/readmes/go/docker-mysql/README.md
deleted file mode 100644
index 30b9bccb678b..000000000000
--- a/.github/readmes/go/docker-mysql/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# MySQL with Docker Example
-
-This example shows how to **set up Prisma using Docker and MySQL** locally on your machine. It then uses the Prisma client in a simple Go script to read and write data in the database.
-
-> This example uses a new and empty database. **Learn how to connect Prisma to your existing database [here](https://www.prisma.io/docs/-g003/)**.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/go/docker-mysql
-dep ensure -update
-```
-
-### 2. Launch Prisma with Docker
-
-This example is based on Docker. If you don't have Docker installed, you can get it from [here](https://store.docker.com/search?type=edition&offering=community). Use the Docker Compose CLI to launch the Docker containers specified in [docker-compose.yml](./docker-compose.yml):
-
-```
-docker-compose up -d
-```
-
-### 3. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via Homebrew or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-brew install prisma
-brew tap
-```
-
-### 4. Set up database & deploy Prisma datamodel
-
-To deploy the datamodel for this example, run the following command:
-
-```
-prisma deploy
-```
-
-### 5. Run the script
-
-Execute the script with this command:
-
-```
-go run main.go
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/go/docker-postgres/README.md b/.github/readmes/go/docker-postgres/README.md
deleted file mode 100644
index 960d3600d586..000000000000
--- a/.github/readmes/go/docker-postgres/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# PostgreSQL with Docker Example
-
-This example shows how to **set up Prisma using Docker and PostgreSQL** locally on your machine. It then uses the Prisma client in a simple Go script to read and write data in the database.
-
-> This example uses a new and empty database. **Learn how to connect Prisma to your existing database [here](https://www.prisma.io/docs/-g003/)**.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/go/docker-postgres
-dep ensure -update
-```
-
-### 2. Launch Prisma with Docker
-
-This example is based on Docker. If you don't have Docker installed, you can get it from [here](https://store.docker.com/search?type=edition&offering=community). Use the Docker Compose CLI to launch the Docker containers specified in [docker-compose.yml](./docker-compose.yml):
-
-```
-docker-compose up -d
-```
-
-### 3. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via Homebrew or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-brew install prisma
-brew tap
-```
-
-### 4. Set up database & deploy Prisma datamodel
-
-To deploy the datamodel for this example, run the following command:
-
-```
-prisma deploy
-```
-
-### 5. Run the script
-
-Execute the script with this command:
-
-```
-go run main.go
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/go/graphql/README.md b/.github/readmes/go/graphql/README.md
deleted file mode 100644
index 1e3c4693bca5..000000000000
--- a/.github/readmes/go/graphql/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# GraphQL Server Example
-
-This example shows how to implement a **GraphQL server with Golang** based on Prisma & [gqlgen](https://github.com/99designs/gqlgen).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/go/graphql
-__INLINE(../_setup-2.md)__
-
-### 4. Start the GraphQL server
-
-```
-go run ./server
-```
-
-Navigate to [http://localhost:4000](http://localhost:4000) in your browser to explore the API of your GraphQL server in a [GraphQL Playground](https://github.com/prisma/graphql-playground).
-
-__INLINE(../../_using-the-graphql-api.md)__
-
-### 6. Changing the GraphQL schema
-
-After you made changes to `schema.graphql`, you need to update the generated types in `./server/generated.go` and potentially also adjust the resolver implementations in `./server/resolver.go`:
-
-```
-go run sripts/gqlgen.go
-```
-
-This updates `./server/generated.go` to incorporate the schema changes in your Go type definitions. It also generates scaffolded resolvers in `tmp/resolver.go` that you might need to copy and paste into `./server/resolver.go`.
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/go/http-mux/README.md b/.github/readmes/go/http-mux/README.md
deleted file mode 100644
index 034d5e7d21bf..000000000000
--- a/.github/readmes/go/http-mux/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# REST API Example
-
-This example shows how to implement a **REST (HTTP) API** using [gorilla/mux](http://www.gorillatoolkit.org/pkg/mux) and Prisma.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/go/http-mux
-__INLINE(../_setup-2.md)__
-
-### 4. Start the REST API server
-
-```
-go run main.go
-```
-
-The server is now running on `http://localhost:8080`. You can send the API requests implemented in `main.go`, e.g. [`http://localhost:8080/feed`](http://localhost:8080/feed).
-
-__INLINE(../../_using-the-rest-api.md)__
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/go/rest-gin/README.md b/.github/readmes/go/rest-gin/README.md
deleted file mode 100644
index 873aa212c0d1..000000000000
--- a/.github/readmes/go/rest-gin/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# REST API Example
-
-This example shows how to implement a **REST (HTTP) API** using the [Gin Web Framework](https://github.com/gin-gonic/gin) and Prisma.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/go/rest-gin
-__INLINE(../_setup-2.md)__
-
-### 4. Start the REST API server
-
-```
-go run main.go
-```
-
-The server is now running on `http://localhost:8080`. You can send the API requests implemented in `main.go`, e.g. [`http://localhost:8080/feed`](http://localhost:8080/feed).
-
-__INLINE(../../_using-the-rest-api.md)__
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/go/script/README.md b/.github/readmes/go/script/README.md
deleted file mode 100644
index 98b8d1c28fb6..000000000000
--- a/.github/readmes/go/script/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Simple Golang Script Example
-
-This example shows how to use the Prisma client in a **simple Golang script** to read and write data in a database.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/go/script
-__INLINE(../_setup-2.md)__
-
-### 4. Run the script
-
-Execute the script with this command:
-
-```
-go run main.go
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/node/_next-steps.md b/.github/readmes/node/_next-steps.md
deleted file mode 100644
index 8b6bd7f82a95..000000000000
--- a/.github/readmes/node/_next-steps.md
+++ /dev/null
@@ -1,5 +0,0 @@
-## Next steps
-
-- [Use Prisma with an existing database](https://www.prisma.io/docs/-a003/)
-- [Explore the Prisma client API](https://www.prisma.io/client/client-javascript)
-- [Learn more about the GraphQL schema](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e/)
\ No newline at end of file
diff --git a/.github/readmes/node/_setup-1.md b/.github/readmes/node/_setup-1.md
deleted file mode 100644
index f5fcb69916cb..000000000000
--- a/.github/readmes/node/_setup-1.md
+++ /dev/null
@@ -1,13 +0,0 @@
-## How to use
-
-### 1. Download example & install dependencies
-
-Clone the repository:
-
-```
-git clone git@github.com:prisma/prisma-examples.git
-```
-
-Install Node dependencies:
-
-```
\ No newline at end of file
diff --git a/.github/readmes/node/_setup-2.md b/.github/readmes/node/_setup-2.md
deleted file mode 100644
index d05c2a47bc45..000000000000
--- a/.github/readmes/node/_setup-2.md
+++ /dev/null
@@ -1,64 +0,0 @@
-npm install
-```
-
-### 2. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 3. Set up database & deploy Prisma datamodel
-
-For this example, you'll use a free _demo database_ (AWS Aurora) hosted in Prisma Cloud. To set up your database, run:
-
-```
-prisma deploy
-```
-
-Then, follow these steps in the interactive CLI wizard:
-
-1. Select **Demo server**
-1. **Authenticate** with Prisma Cloud in your browser (if necessary)
-1. Back in your terminal, **confirm all suggested values**
-
-
- Alternative: Run Prisma locally via Docker
-
-1. Ensure you have Docker installed on your machine. If not, you can get it from [here](https://store.docker.com/search?offering=community&type=edition).
-1. Create `docker-compose.yml` for MySQL (see [here](https://www.prisma.io/docs/prisma-server/database-connector-POSTGRES-jgfr/) for Postgres):
- ```yml
- version: '3'
- services:
- prisma:
- image: prismagraphql/prisma:1.27
- restart: always
- ports:
- - "4466:4466"
- environment:
- PRISMA_CONFIG: |
- port: 4466
- databases:
- default:
- connector: mysql
- host: mysql
- port: 3306
- user: root
- password: prisma
- migrations: true
- mysql:
- image: mysql:5.7
- restart: always
- environment:
- MYSQL_ROOT_PASSWORD: prisma
- volumes:
- - mysql:/var/lib/mysql
- volumes:
- mysql:
- ```
-1. Run `docker-compose up -d`
-1. Set the `endpoint` in `prisma.yml` to `http://localhost:4466`
-1. Run `prisma deploy`
-
-
\ No newline at end of file
diff --git a/.github/readmes/node/_start-graphql-server.md b/.github/readmes/node/_start-graphql-server.md
deleted file mode 100644
index de3531c94450..000000000000
--- a/.github/readmes/node/_start-graphql-server.md
+++ /dev/null
@@ -1,9 +0,0 @@
-### 4. Start the GraphQL server
-
-Launch your GraphQL server with this command:
-
-```
-npm run start
-```
-
-Navigate to [http://localhost:4000](http://localhost:4000) in your browser to explore the API of your GraphQL server in a [GraphQL Playground](https://github.com/prisma/graphql-playground).
\ No newline at end of file
diff --git a/.github/readmes/node/cli-app/README.md b/.github/readmes/node/cli-app/README.md
deleted file mode 100644
index 5fa3a64335c4..000000000000
--- a/.github/readmes/node/cli-app/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Simple TODO-App Example (CLI)
-
-This example shows how to implement a **TODO-app as a CLI tool** with Node.js and Prisma.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/cli-app
-__INLINE(../_setup-2.md)__
-
-### 4. Use the CLI app
-
-```
-npm run cli
-```
-
-#### Add a `Todo` item
-
-```
-npm run cli add Groceries
-```
-
-#### List all `Todo` items
-
-```
-npm run cli list
-```
-
-#### Delete a `Todo` item
-
-```
-npm run cli delete Groceries
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/node/docker-mongodb/README.md b/.github/readmes/node/docker-mongodb/README.md
deleted file mode 100644
index a41c4a721dd3..000000000000
--- a/.github/readmes/node/docker-mongodb/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# MongoDB with Docker Example
-
-This example shows how to **set up Prisma using Docker and MongoDB** locally on your machine. It then uses the Prisma client in a simple Node script to read and write data in the database.
-
-> When using MongoDB with Prisma, you use a [new datamodel format](https://www.prisma.io/docs/-b6a7/). Learn more in the [docs](https://www.prisma.io/docs/-b6o5/).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/docker-mongodb
-npm install
-```
-
-### 2. Launch Prisma with Docker
-
-This example is based on Docker. If you don't have Docker installed, you can get it from [here](https://store.docker.com/search?type=edition&offering=community). Use the Docker Compose CLI to launch the Docker containers specified in [docker-compose.yml](./docker-compose.yml):
-
-```
-docker-compose up -d
-```
-
-### 3. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 4. Set up database & deploy Prisma datamodel
-
-To deploy the datamodel for this example, run the following command:
-
-```
-prisma deploy
-```
-
-### 5. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/node/docker-mysql/README.md b/.github/readmes/node/docker-mysql/README.md
deleted file mode 100644
index a3c48649e4ed..000000000000
--- a/.github/readmes/node/docker-mysql/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# MySQL with Docker Example
-
-This example shows how to **set up Prisma using Docker and MySQL** locally on your machine. It then uses the Prisma client in a simple Node script to read and write data in the database.
-
-> This example uses a new and empty database. **Learn how to connect Prisma to your existing database [here](https://www.prisma.io/docs/-a003/)**.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/docker-mysql
-npm install
-```
-
-### 2. Launch Prisma with Docker
-
-This example is based on Docker. If you don't have Docker installed, you can get it from [here](https://store.docker.com/search?type=edition&offering=community). Use the Docker Compose CLI to launch the Docker containers specified in [docker-compose.yml](./docker-compose.yml):
-
-```
-docker-compose up -d
-```
-
-### 3. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 4. Set up database & deploy Prisma datamodel
-
-To deploy the datamodel for this example, run the following command:
-
-```
-prisma deploy
-```
-
-### 5. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/node/docker-postgres/README.md b/.github/readmes/node/docker-postgres/README.md
deleted file mode 100644
index ccb3646a4d1e..000000000000
--- a/.github/readmes/node/docker-postgres/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# PostgreSQL with Docker Example
-
-This example shows how to **set up Prisma using Docker and PostgreSQL** locally on your machine. It then uses the Prisma client in a simple Node script to read and write data in the database.
-
-> This example uses a new and empty database. **Learn how to connect Prisma to your existing database [here](https://www.prisma.io/docs/-a003/)**.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/docker-postgres
-npm install
-```
-
-### 2. Launch Prisma with Docker
-
-This example is based on Docker. If you don't have Docker installed, you can get it from [here](https://store.docker.com/search?type=edition&offering=community). Use the Docker Compose CLI to launch the Docker containers specified in [docker-compose.yml](./docker-compose.yml):
-
-```
-docker-compose up -d
-```
-
-### 3. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 4. Set up database & deploy Prisma datamodel
-
-To deploy the datamodel for this example, run the following command:
-
-```
-prisma deploy
-```
-
-### 5. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/node/graphql-auth/README.md b/.github/readmes/node/graphql-auth/README.md
deleted file mode 100644
index ecd7d1ae712b..000000000000
--- a/.github/readmes/node/graphql-auth/README.md
+++ /dev/null
@@ -1,223 +0,0 @@
-# GraphQL Server with Authentication & Permissions
-
-This example shows how to implement a **GraphQL server with an email-password-based authentication workflow and authentication rules** based on Prisma, [graphql-yoga](https://github.com/prisma/graphql-yoga) & [graphql-shield](https://github.com/maticzav/graphql-shield).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/graphql-auth
-__INLINE(../_setup-2.md)__
-
-__INLINE(../_start-graphql-server.md)__
-
-__INLINE(../../_using-the-graphql-api-auth.md)__
-
-### 6. Evolving the example
-
-If you want to change the GraphQL API, you need to adjust the GraphQL schema in [`./src/schema.graphql`](./src/schema.graphql) and the respective resolver functions.
-
-Adding an operation without updating the datamodel
-
-To add new operation that can be based on the current [datamodel](./prisma/datamodel.prisma), you first need to add the operation to the GraphQL schema's `Query` or `Mutation` type and then add the corresponding resolver function.
-
-For example, to add a new mutation that updates a user's name, you can extend the `Mutation` type as follows:
-
-```diff
-type Mutation {
- signupUser(email: String!, name: String): User!
- createDraft(title: String!, content: String, authorEmail: String!): Post!
- deletePost(id: ID!): Post
- publish(id: ID!): Post
-+ updateUserName(id: ID!, newName: String!): User
-}
-```
-
-Then add the new resolver to the `Mutation` object in [`./src/resolvers/Mutation.js`](./src/resolvers/Mutation.js):
-
-```diff
-const Mutation = {
- // ...
-+ updateUserName(parent, { id, newName }, context) {
-+ return context.prisma.updateUser({
-+ where: {
-+ id
-+ },
-+ data: {
-+ name: newName
-+ }
-+ })
-+ }
-}
-```
-
-You can now send the following mutation to your GraphQL API:
-
-```graphql
-mutation {
- updateUserName(
- id: "__USER_ID__"
- newName: "John")
- ) {
- id
- name
- }
-}
-```
-
-
-
-Adding an operation and updating the datamodel
-
-Some new API features can't be covered with the existing datamodel. For example, you might want to add _comment_ feature to the API, so that users can leave comments on posts.
-
-For that, you first need to adjust the Prisma datamodel in [`./prisma/datamodel.prisma`](./prisma/datamodel.prisma):
-
-```diff
-type User {
- id: ID! @unique
- email: String! @unique
- name: String
- posts: [Post!]!
-+ comments: [Comment!]!
-}
-
-type Post {
- id: ID! @unique
- createdAt: DateTime!
- updatedAt: DateTime!
- published: Boolean! @default(value: "false")
- title: String!
- content: String
- author: User!
-+ comments: [Comment!]!
-}
-
-+ type Comment {
-+ id: ID! @unique
-+ text: String!
-+ writtenBy: User!
-+ post: Post!
-+ }
-```
-
-After having updated the datamodel, you need to deploy the changes:
-
-```
-prisma deploy
-```
-
-Note that this also invokes `prisma generate` (because of the `post-deploy` hook in [`prisma.yml`](./prisma/prisma.yml)) which regenerates the Prisma client in [`./src/generated/prisma-client`](./src/generated/prisma-client).
-
-To now enable users to add comments to posts, you need to add the `Comment` type as well as the corresponding operation to the GraphQL schema in [`./src/schema.graphql`](./src/schema.graphql):
-
-```diff
-type Query {
- # ... as before
-}
-
-type Mutation {
- signupUser(email: String!, name: String): User!
- createDraft(title: String!, content: String, authorEmail: String!): Post!
- deletePost(id: ID!): Post
- publish(id: ID!): Post
- updateUserName(id: ID!, newName: String!): User
-+ writeComment(text: String!, postId: ID!): Comment
-}
-
-type User {
- id: ID!
- email: String!
- name: String
- posts: [Post!]!
-+ comments: [Comment!]!
-}
-
-type Post {
- id: ID!
- createdAt: DateTime!
- updatedAt: DateTime!
- published: Boolean!
- title: String!
- content: String
- author: User!
-+ comments: [Comment!]!
-}
-
-+ type Comment {
-+ id: ID!
-+ text: String!
-+ writtenBy: User!
-+ post: Post!
-+ }
-```
-
-Next, you need to implement the resolver for the new operation in [`./src/resolvers/Mutation.js`](./src/resolvers/Mutation.js):
-
-```diff
-const resolvers = {
- // ...
- Mutation: {
- // ...
-+ writeComment(parent, { postId, userId }, context) {
-+ const userId = getUserId(context)
-+ return context.prisma.createComment({
-+ text,
-+ post: {
-+ connect: { id: postId }
-+ },
-+ writtenBy: {
-+ connect: { id: userId }
-+ }
-+ })
-+ }
- }
-}
-```
-
-Finally, because `Comment` has a relation to `Post` and `User`, you need to update the type resolvers as well so that the relation can be properly resolved (learn more about why this is necessary in [this](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e/) blog article):
-
-```diff
-const resolvers = {
- // ...
- User: {
- // ...
-+ comments: ({ id }, args, context) {
-+ return context.prisma.user({ id }).comments()
-+ }
- },
- Post: {
- // ...
-+ comments: ({ id }, args, context) {
-+ return context.prisma.post({ id }).comments()
-+ }
- },
-+ Comment: {
-+ writtenBy: ({ id }, args, context) {
-+ return context.prisma.comment({ id }).writtenBy()
-+ },
-+ post: ({ id }, args, context) {
-+ return context.prisma.comment({ id }).post()
-+ },
-+ }
-}
-```
-
-You can now send the following mutation to your GraphQL API. Note that this mutation only works if you're authenticated through a valid token in the `Authorization` header.
-
-```graphql
-mutation {
- writeComment(
- postId: "__POST_ID__"
- text: "I like turtles 🐢"
- ) {
- id
- name
- }
-}
-```
-
-
-
-__INLINE(../_next-steps.md)__
-
-## The idea behind the example
-
-The Prisma client is used as a replacement for a traditional ORM in this example. It bridges the gap between your GraphQL resolvers and your database by providing a powerful CRUD API for the types that are defined in your Prisma datamodel.
diff --git a/.github/readmes/node/graphql-subscriptions/README.md b/.github/readmes/node/graphql-subscriptions/README.md
deleted file mode 100644
index b398a9abcf08..000000000000
--- a/.github/readmes/node/graphql-subscriptions/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# GraphQL Server with Realtime Subscriptions Example
-
-This example shows how to implement **GraphQL server with realtime subscriptions** based on Prisma & [graphql-yoga](https://github.com/prisma/graphql-yoga).
-
-> To learn more about implementing GraphQL subscriptions with Prisma, visit [this](https://www.prisma.io/tutorials/build-a-realtime-graphql-server-with-subscriptions-ct11/) tutorial.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/graphql-subscriptions
-__INLINE(../_setup-2.md)__
-
-__INLINE(../_start-graphql-server.md)__
-
-__INLINE(../../_using-the-graphql-api-subs.md)__
-
-__INLINE(../_next-steps.md)__
diff --git a/.github/readmes/node/graphql/README.md b/.github/readmes/node/graphql/README.md
deleted file mode 100644
index b059da96cda6..000000000000
--- a/.github/readmes/node/graphql/README.md
+++ /dev/null
@@ -1,226 +0,0 @@
-# GraphQL Server Example
-
-This example shows how to implement a **GraphQL server with Node.js** based on Prisma & [graphql-yoga](https://github.com/prisma/graphql-yoga).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/graphql
-__INLINE(../_setup-2.md)__
-
-__INLINE(../_start-graphql-server.md)__
-
-__INLINE(../../_using-the-graphql-api.md)__
-
-### 6. Evolving the example
-
-If you want to change the GraphQL API, you need to adjust the GraphQL schema in [`./src/schema.graphql`](./src/schema.graphql) and the respective resolver functions.
-
-Adding an operation without updating the datamodel
-
-To add new operation that can be based on the current [datamodel](./prisma/datamodel.prisma), you first need to add the operation to the GraphQL schema's `Query` or `Mutation` type and then add the corresponding resolver function.
-
-For example, to add a new mutation that updates a user's name, you can extend the `Mutation` type as follows:
-
-```diff
-type Mutation {
- signupUser(email: String!, name: String): User!
- createDraft(title: String!, content: String, authorEmail: String!): Post!
- deletePost(id: ID!): Post
- publish(id: ID!): Post
-+ updateUserName(id: ID!, newName: String!): User
-}
-```
-
-Then add the new resolver to the `resolvers` object in [`./src/index.js`](./src/index.js):
-
-```diff
-const resolvers = {
- // ...
- Mutation: {
- // ...
-+ updateUserName(parent, { id, newName }, context) {
-+ return context.prisma.updateUser({
-+ where: {
-+ id
-+ },
-+ data: {
-+ name: newName
-+ }
-+ })
-+ }
- }
-}
-```
-
-You can now send the following mutation to your GraphQL API:
-
-```graphql
-mutation {
- updateUserName(
- id: "__USER_ID__"
- newName: "John")
- ) {
- id
- name
- }
-}
-```
-
-
-
-Adding an operation and updating the datamodel
-
-Some new API features can't be covered with the existing datamodel. For example, you might want to add _comment_ feature to the API, so that users can leave comments on posts.
-
-For that, you first need to adjust the Prisma datamodel in [`./prisma/datamodel.prisma`](./prisma/datamodel.prisma):
-
-```diff
-type User {
- id: ID! @unique
- email: String! @unique
- name: String
- posts: [Post!]!
-+ comments: [Comment!]!
-}
-
-type Post {
- id: ID! @unique
- createdAt: DateTime!
- updatedAt: DateTime!
- published: Boolean! @default(value: "false")
- title: String!
- content: String
- author: User!
-+ comments: [Comment!]!
-}
-
-+ type Comment {
-+ id: ID! @unique
-+ text: String!
-+ writtenBy: User!
-+ post: Post!
-+ }
-```
-
-After having updated the datamodel, you need to deploy the changes:
-
-```
-prisma deploy
-```
-
-Note that this also invokes `prisma generate` (because of the `post-deploy` hook in [`prisma.yml`](./prisma/prisma.yml)) which regenerates the Prisma client in [`./src/generated/prisma-client`](./src/generated/prisma-client).
-
-To now enable users to add comments to posts, you need to add the `Comment` type as well as the corresponding operation to the GraphQL schema in [`./src/schema.graphql`](./src/schema.graphql):
-
-```diff
-type Query {
- # ... as before
-}
-
-type Mutation {
- signupUser(email: String!, name: String): User!
- createDraft(title: String!, content: String, authorEmail: String!): Post!
- deletePost(id: ID!): Post
- publish(id: ID!): Post
- updateUserName(id: ID!, newName: String!): User
-+ writeComment(text: String!, postId: ID!, userId!: ID!): Comment
-}
-
-type User {
- id: ID!
- email: String!
- name: String
- posts: [Post!]!
-+ comments: [Comment!]!
-}
-
-type Post {
- id: ID!
- createdAt: DateTime!
- updatedAt: DateTime!
- published: Boolean!
- title: String!
- content: String
- author: User!
-+ comments: [Comment!]!
-}
-
-+ type Comment {
-+ id: ID!
-+ text: String!
-+ writtenBy: User!
-+ post: Post!
-+ }
-```
-
-Next, you need to implement the resolver for the new operation in [`./src/index.js`](./src/index.js):
-
-```diff
-const resolvers = {
- // ...
- Mutation: {
- // ...
-+ writeComment(parent, { postId, userId}, context) {
-+ return context.prisma.createComment({
-+ text,
-+ post: {
-+ connect: { id: postId }
-+ },
-+ writtenBy: {
-+ connect: { id: userId }
-+ }
-+ })
-+ }
- }
-}
-```
-
-Finally, because `Comment` has a relation to `Post` and `User`, you need to update the type resolvers as well so that the relation can be properly resolved (learn more about why this is necessary in [this](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e/) blog article):
-
-```diff
-const resolvers = {
- // ...
- User: {
- // ...
-+ comments: ({ id }, args, context) {
-+ return context.prisma.user({ id }).comments()
-+ }
- },
- Post: {
- // ...
-+ comments: ({ id }, args, context) {
-+ return context.prisma.post({ id }).comments()
-+ }
- },
-+ Comment: {
-+ writtenBy: ({ id }, args, context) {
-+ return context.prisma.comment({ id }).writtenBy()
-+ },
-+ post: ({ id }, args, context) {
-+ return context.prisma.comment({ id }).post()
-+ },
-+ }
-}
-```
-
-You can now send the following mutation to your GraphQL API:
-
-```graphql
-mutation {
- writeComment(
- userId: "__USER_ID__"
- postId: "__POST_ID__"
- text: "I like turtles 🐢"
- ) {
- id
- name
- }
-}
-```
-
-
-
-__INLINE(../_next-steps.md)__
-
-## The idea behind the example
-
-The Prisma client is used as a replacement for a traditional ORM in this example. It bridges the gap between your GraphQL resolvers and your database by providing a powerful CRUD API for the types that are defined in your Prisma datamodel.
\ No newline at end of file
diff --git a/.github/readmes/node/grpc/README.md b/.github/readmes/node/grpc/README.md
deleted file mode 100644
index 9c0bd918b57b..000000000000
--- a/.github/readmes/node/grpc/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# gRPC Server Example
-
-This example shows how to implement a **gRPC API with Node.js** and Prisma.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/grpc
-__INLINE(../_setup-2.md)__
-
-### 4. Start the gRPC server
-
-```
-npm run start
-```
-
-The server is now running on `0.0.0.0:50051`.
-
-### 5. Using the gRPC API
-
-To use the gRPC API, you need a gRPC client. We provide several client scripts inside the [`./client`](./client) directory. Each script is named according to the operation it performs against the gRPC API (e.g. the [`feed.js`](./client/feed.js) script sends the [`Feed`](./service.proto#L7) operation). Each script can be invoked by running the corresponding NPM script defined in [`package.json`](./package.json), e.g. `npm run feed`.
-
-In case you prefer a GUI client, we recommend [BloomRPC](https://github.com/uw-labs/bloomrpc):
-
-
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/node/rest-express/README.md b/.github/readmes/node/rest-express/README.md
deleted file mode 100644
index 80323f58fb00..000000000000
--- a/.github/readmes/node/rest-express/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# REST API Example
-
-This example shows how to implement a **REST API** using [Express.JS](https://expressjs.com/de/) and Prisma.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/rest-express
-__INLINE(../_setup-2.md)__
-
-### 4. Start the REST API server
-
-```
-npm run start
-```
-
-The server is now running on `http://localhost:3000`. You can send the API requests implemented in `index.js`, e.g. [`http://localhost:3000/feed`](http://localhost:3000/feed).
-
-__INLINE(../../_using-the-rest-api.md)__
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/node/script/README.md b/.github/readmes/node/script/README.md
deleted file mode 100644
index 36a552ebc7d3..000000000000
--- a/.github/readmes/node/script/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Simple Node Script Example
-
-This example shows how to use the Prisma client in a **simple Node script** to read and write data in a database.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/node/script
-__INLINE(../_setup-2.md)__
-
-### 4. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/_next-steps.md b/.github/readmes/typescript/_next-steps.md
deleted file mode 100644
index 46a39a7defe5..000000000000
--- a/.github/readmes/typescript/_next-steps.md
+++ /dev/null
@@ -1,5 +0,0 @@
-## Next steps
-
-- [Use Prisma with an existing database](https://www.prisma.io/docs/-t003/)
-- [Explore the Prisma client API](https://www.prisma.io/client/client-typescript)
-- [Learn more about the GraphQL schema](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e/)
\ No newline at end of file
diff --git a/.github/readmes/typescript/_setup-1.md b/.github/readmes/typescript/_setup-1.md
deleted file mode 100644
index f5fcb69916cb..000000000000
--- a/.github/readmes/typescript/_setup-1.md
+++ /dev/null
@@ -1,13 +0,0 @@
-## How to use
-
-### 1. Download example & install dependencies
-
-Clone the repository:
-
-```
-git clone git@github.com:prisma/prisma-examples.git
-```
-
-Install Node dependencies:
-
-```
\ No newline at end of file
diff --git a/.github/readmes/typescript/_setup-2.md b/.github/readmes/typescript/_setup-2.md
deleted file mode 100644
index d05c2a47bc45..000000000000
--- a/.github/readmes/typescript/_setup-2.md
+++ /dev/null
@@ -1,64 +0,0 @@
-npm install
-```
-
-### 2. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 3. Set up database & deploy Prisma datamodel
-
-For this example, you'll use a free _demo database_ (AWS Aurora) hosted in Prisma Cloud. To set up your database, run:
-
-```
-prisma deploy
-```
-
-Then, follow these steps in the interactive CLI wizard:
-
-1. Select **Demo server**
-1. **Authenticate** with Prisma Cloud in your browser (if necessary)
-1. Back in your terminal, **confirm all suggested values**
-
-
- Alternative: Run Prisma locally via Docker
-
-1. Ensure you have Docker installed on your machine. If not, you can get it from [here](https://store.docker.com/search?offering=community&type=edition).
-1. Create `docker-compose.yml` for MySQL (see [here](https://www.prisma.io/docs/prisma-server/database-connector-POSTGRES-jgfr/) for Postgres):
- ```yml
- version: '3'
- services:
- prisma:
- image: prismagraphql/prisma:1.27
- restart: always
- ports:
- - "4466:4466"
- environment:
- PRISMA_CONFIG: |
- port: 4466
- databases:
- default:
- connector: mysql
- host: mysql
- port: 3306
- user: root
- password: prisma
- migrations: true
- mysql:
- image: mysql:5.7
- restart: always
- environment:
- MYSQL_ROOT_PASSWORD: prisma
- volumes:
- - mysql:/var/lib/mysql
- volumes:
- mysql:
- ```
-1. Run `docker-compose up -d`
-1. Set the `endpoint` in `prisma.yml` to `http://localhost:4466`
-1. Run `prisma deploy`
-
-
\ No newline at end of file
diff --git a/.github/readmes/typescript/_start-graphql-server.md b/.github/readmes/typescript/_start-graphql-server.md
deleted file mode 100644
index de3531c94450..000000000000
--- a/.github/readmes/typescript/_start-graphql-server.md
+++ /dev/null
@@ -1,9 +0,0 @@
-### 4. Start the GraphQL server
-
-Launch your GraphQL server with this command:
-
-```
-npm run start
-```
-
-Navigate to [http://localhost:4000](http://localhost:4000) in your browser to explore the API of your GraphQL server in a [GraphQL Playground](https://github.com/prisma/graphql-playground).
\ No newline at end of file
diff --git a/.github/readmes/typescript/circleci/README.md b/.github/readmes/typescript/circleci/README.md
deleted file mode 100644
index 8535c4e9ffb3..000000000000
--- a/.github/readmes/typescript/circleci/README.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# CircleCI Configuration Example
-
-This example shows how to configute a CI setup using [CircleCI](https://circleci.com/) for Prisma.
-
-## Get started
-
-> **Note**: The project setup in this example is minimalistic. You can use it as a reference example for your own project, but you might want to evolve it into a more advanced setup.
-
-### 1. Download the example
-
-Clone the repository:
-
-```
-git clone git@github.com:prisma/prisma-examples.git
-```
-
-Install Node dependencies:
-
-```
-cd prisma-examples/typescript-circleci
-```
-
-### 2. Set up repository locally and on GitHub
-
-Next, navigate into the downloaded folder and initiate a new git repository:
-
-```sh
-cd typescript-circleci
-git init .
-git add .
-git commit -m "Initial commit"
-```
-
-In your GitHub account, create a new repository and copy its git URL, e.g.: `git@github.com:w0wka91/circleci-prisma.git`
-
-Add a new remote to your local git repository:
-
-```sh
-git remote add origin git@github.com:w0wka91/circleci-prisma.git
-```
-
-Push your project to github:
-
-```sh
-git push --set-upstream origin master
-```
-
-### 3. Add project in CircleCI
-
-Now, log in your [CircleCI](https://circleci.com/dashboard) account, add your github repository as a new project and click on `Start Building`.
-
-### 4. Verify the build
-
-In your CircleCI account, review the build and confirm that the build went through.
-
-Here is a description of the performed steps that are expected to happen (compare to `.circleci/config.yml` as well):
-
-1. We spin up a new Prisma server and database using `docker-compose up -d`.
-2. We confirm that the Docker setup is correct with `docker ps`.
-3. We install the `npm` dependencies with `npm install`.
-4. We sleep 20 seconds to allow for the two Docker containers to finish their setup.
-5. We run `prisma deploy` with the locally installed version of Prisma. This will set up a new service `circleci` at stage `test` and seed some data according to `prisma.yml`.
-6. We run a short jest test where we fetch all users from the prisma server using prisma-client
diff --git a/.github/readmes/typescript/cli-app/README.md b/.github/readmes/typescript/cli-app/README.md
deleted file mode 100644
index f46e3fb7d558..000000000000
--- a/.github/readmes/typescript/cli-app/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Simple TODO-App Example (CLI)
-
-This example shows how to implement a **TODO-app as a CLI tool** with TypeScript and Prisma.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/cli-app
-__INLINE(../_setup-2.md)__
-
-### 4. Use the CLI app
-
-```
-npm run cli
-```
-
-#### Add a `Todo` item
-
-```
-npm run cli add Groceries
-```
-
-#### List all `Todo` items
-
-```
-npm run cli list
-```
-
-#### Delete a `Todo` item
-
-```
-npm run cli delete Groceries
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/docker-mongodb/README.md b/.github/readmes/typescript/docker-mongodb/README.md
deleted file mode 100644
index cc0d0824d662..000000000000
--- a/.github/readmes/typescript/docker-mongodb/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# MongoDB with Docker Example
-
-This example shows how to **set up Prisma using Docker and MongoDB** locally on your machine. It then uses the Prisma client in a simple TypeScript script to read and write data in the database.
-
-> When using MongoDB with Prisma, you use a [new datamodel format](https://www.prisma.io/docs/-b6a7/). Learn more in the [docs](https://www.prisma.io/docs/-b6o5/).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/docker-mongodb
-npm install
-```
-
-### 2. Launch Prisma with Docker
-
-This example is based on Docker. If you don't have Docker installed, you can get it from [here](https://store.docker.com/search?type=edition&offering=community). Use the Docker Compose CLI to launch the Docker containers specified in [docker-compose.yml](./docker-compose.yml):
-
-```
-docker-compose up -d
-```
-
-### 3. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 4. Set up database & deploy Prisma datamodel
-
-To deploy the datamodel for this example, run the following command:
-
-```
-prisma deploy
-```
-
-### 5. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/docker-mysql/README.md b/.github/readmes/typescript/docker-mysql/README.md
deleted file mode 100644
index 154460c06f4b..000000000000
--- a/.github/readmes/typescript/docker-mysql/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# MySQL with Docker Example
-
-This example shows how to **set up Prisma using Docker and MySQL** locally on your machine. It then uses the Prisma client in a simple TypeScript script to read and write data in the database.
-
-> This example uses a new and empty database. **Learn how to connect Prisma to your existing database [here](https://www.prisma.io/docs/-t003/)**.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/docker-mysql
-npm install
-```
-
-### 2. Launch Prisma with Docker
-
-This example is based on Docker. If you don't have Docker installed, you can get it from [here](https://store.docker.com/search?type=edition&offering=community). Use the Docker Compose CLI to launch the Docker containers specified in [docker-compose.yml](./docker-compose.yml):
-
-```
-docker-compose up -d
-```
-
-### 3. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 4. Set up database & deploy Prisma datamodel
-
-To deploy the datamodel for this example, run the following command:
-
-```
-prisma deploy
-```
-
-### 5. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/docker-postgres/README.md b/.github/readmes/typescript/docker-postgres/README.md
deleted file mode 100644
index aa22b2c35d75..000000000000
--- a/.github/readmes/typescript/docker-postgres/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# PostgreSQL with Docker Example
-
-This example shows how to **set up Prisma using Docker and PostgreSQL** locally on your machine. It then uses the Prisma client in a simple TypeScript script to read and write data in the database.
-
-> This example uses a new and empty database. **Learn how to connect Prisma to your existing database [here](https://www.prisma.io/docs/-t003/)**.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/docker-postgres
-npm install
-```
-
-### 2. Launch Prisma with Docker
-
-This example is based on Docker. If you don't have Docker installed, you can get it from [here](https://store.docker.com/search?type=edition&offering=community). Use the Docker Compose CLI to launch the Docker containers specified in [docker-compose.yml](./docker-compose.yml):
-
-```
-docker-compose up -d
-```
-
-### 3. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 4. Set up database & deploy Prisma datamodel
-
-To deploy the datamodel for this example, run the following command:
-
-```
-prisma deploy
-```
-
-### 5. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/graphql-auth/README.md b/.github/readmes/typescript/graphql-auth/README.md
deleted file mode 100644
index 9f1e734c0b3c..000000000000
--- a/.github/readmes/typescript/graphql-auth/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# GraphQL Server with Authentication & Permissions
-
-This example shows how to implement a **GraphQL server with an email-password-based authentication workflow and authentication rules**, based on Prisma, [graphql-yoga](https://github.com/prisma/graphql-yoga), [graphql-shield](https://github.com/maticzav/graphql-shield) & [GraphQL Nexus](https://graphql-nexus.com/).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/graphql-auth
-__INLINE(../_setup-2.md)__
-
-__INLINE(../_start-graphql-server.md)__
-
-__INLINE(../../_using-the-graphql-api-auth.md)__
-
-### 6. Changing the GraphQL schema
-
-To make changes to the GraphQL schema, you need to manipulate the [`Query`](./src/resolvers/Query.ts) and [`Mutation`](./src/resolvers/Mutation.ts) types.
-
-Note that the [`start`](./package.json#L6) script also starts a development server that automatically updates your schema every time you save a file. This way, the auto-generated [GraphQL schema](./src/generated/schema.graphql) updates whenever you make changes in to the `Query` or `Mutation` types inside your TypeScript code.
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/graphql-crud/README.md b/.github/readmes/typescript/graphql-crud/README.md
deleted file mode 100644
index 944f5ebcacae..000000000000
--- a/.github/readmes/typescript/graphql-crud/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# CRUD GraphQL API Example
-
-This example shows how to implement a **CRUD GraphQL API with TypeScript** based on Prisma, [graphql-yoga](https://github.com/prisma/graphql-yoga) and [GraphQL Nexus](https://graphql-nexus.com/).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/graphql-crud
-__INLINE(../_setup-2.md)__
-
-__INLINE(../_start-graphql-server.md)__
-
-__INLINE(../../_using-the-graphql-api-crud.md)__
-
-### 6. Changing the GraphQL schema
-
-To make changes to the GraphQL schema, you need to manipulate the `Query` and `Mutation` types that are defined in [`index.ts`](./src/index.ts).
-
-Note that the [`start`](./package.json#L6) script also starts a development server that automatically updates your schema every time you save a file. This way, the auto-generated [GraphQL schema](./src/generated/schema.graphql) updates whenever you make changes in to the `Query` or `Mutation` types inside your TypeScript code.
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/graphql-subscriptions/README.md b/.github/readmes/typescript/graphql-subscriptions/README.md
deleted file mode 100644
index c7651ad043bb..000000000000
--- a/.github/readmes/typescript/graphql-subscriptions/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# GraphQL Server with Realtime Subscriptions Example
-
-This example shows how to implement **GraphQL server with realtime subscriptions** based on Prisma & [graphql-yoga](https://github.com/prisma/graphql-yoga).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/graphql-subscriptions
-__INLINE(../_setup-2.md)__
-
-__INLINE(../_start-graphql-server.md)__
-
-__INLINE(../../_using-the-graphql-api-subs.md)__
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/graphql/README.md b/.github/readmes/typescript/graphql/README.md
deleted file mode 100644
index bb29f0f94bb3..000000000000
--- a/.github/readmes/typescript/graphql/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# GraphQL Server Example
-
-This example shows how to implement a **GraphQL server with TypeScript** based on Prisma, [graphql-yoga](https://github.com/prisma/graphql-yoga) and [GraphQL Nexus](https://graphql-nexus.com/).
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/graphql
-__INLINE(../_setup-2.md)__
-
-__INLINE(../_start-graphql-server.md)__
-
-__INLINE(../../_using-the-graphql-api.md)__
-
-### 6. Changing the GraphQL schema
-
-To make changes to the GraphQL schema, you need to manipulate the `Query` and `Mutation` types that are defined in [`index.ts`](./src/index.ts).
-
-Note that the [`start`](./package.json#L6) script also starts a development server that automatically updates your schema every time you save a file. This way, the auto-generated [GraphQL schema](./src/generated/schema.graphql) updates whenever you make changes in to the `Query` or `Mutation` types inside your TypeScript code.
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/grpc/README.md b/.github/readmes/typescript/grpc/README.md
deleted file mode 100644
index 722f85741684..000000000000
--- a/.github/readmes/typescript/grpc/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# gRPC Server Example
-
-This example shows how to implement a **gRPC API with TypeScript** and Prisma.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/grpc
-__INLINE(../_setup-2.md)__
-
-### 4. Start the gRPC server
-
-```
-npm run start
-```
-
-The server is now running on `0.0.0.0:50051`.
-
-### 5. Using the gRPC API
-
-To use the gRPC API, you need a gRPC client. We provide several client scripts inside the [`./client`](./client) directory. Each script is named according to the operation it performs against the gRPC API (e.g. the [`feed.js`](./client/feed.js) script sends the [`Feed`](./service.proto#L7) operation). Each script can be invoked by running the corresponding NPM script defined in [`package.json`](./package.json), e.g. `npm run feed`.
-
-In case you prefer a GUI client, we recommend [BloomRPC](https://github.com/uw-labs/bloomrpc):
-
-
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/rest-express/README.md b/.github/readmes/typescript/rest-express/README.md
deleted file mode 100644
index 0d138c9e7d6b..000000000000
--- a/.github/readmes/typescript/rest-express/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# REST API Example
-
-This example shows how to implement a **REST API with TypeScript** using [Express.JS](https://expressjs.com/de/) and Prisma.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/rest-express
-__INLINE(../_setup-2.md)__
-
-### 4. Start the REST API server
-
-```
-npm run start
-```
-
-The server is now running on `http://localhost:3000`. You can send the API requests implemented in `index.js`, e.g. [`http://localhost:3000/feed`](http://localhost:3000/feed).
-
-__INLINE(../../_using-the-rest-api.md)__
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/readmes/typescript/script/README.md b/.github/readmes/typescript/script/README.md
deleted file mode 100644
index 74d4c3d389aa..000000000000
--- a/.github/readmes/typescript/script/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Simple TypeScript Script Example
-
-This example shows how to use the Prisma client in a **simple TypeScript script** to read and write data in a database.
-
-__INLINE(../_setup-1.md)__
-cd prisma-examples/typescript/script
-__INLINE(../_setup-2.md)__
-
-### 4. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-__INLINE(../_next-steps.md)__
\ No newline at end of file
diff --git a/.github/renovate.json b/.github/renovate.json
index 52b9e0974747..1f923479a3cd 100644
--- a/.github/renovate.json
+++ b/.github/renovate.json
@@ -1,11 +1,28 @@
{
- "extends": [
- "config:base",
- "docker:disable",
- ":skipStatusChecks"
- ],
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "extends": ["config:recommended", ":disableRateLimiting", "docker:disable"],
+ "schedule": ["before 8am every weekday", "every weekend"],
+ "rebaseWhen": "conflicted",
+ "prConcurrentLimit": 30,
"automerge": true,
"major": {
"automerge": false
- }
+ },
+ "rangeStrategy": "pin",
+ "baseBranches": ["latest"],
+ "reviewers": ["nikolasburk", "jharrell"],
+ "configMigration": true,
+ "packageRules": [
+ {
+ "matchBaseBranches": ["latest"],
+ "matchPackageNames": ["nexus-plugin-prisma"],
+ "enabled": true
+ },
+ {
+ "matchBaseBranches": ["latest"],
+ "matchPackageNames": ["prisma", "@prisma/client"],
+ "enabled": true,
+ "matchUpdateTypes": ["major"]
+ }
+ ]
}
diff --git a/.github/scripts/get-packages.js b/.github/scripts/get-packages.js
new file mode 100644
index 000000000000..ce20f2e3c9a4
--- /dev/null
+++ b/.github/scripts/get-packages.js
@@ -0,0 +1,38 @@
+const glob = require('glob')
+const path = require('path')
+
+const core = require('@actions/core')
+
+const getTestName = (filePath) => {
+ return path.dirname(filePath).split(path.sep).pop()
+}
+
+const getBaseFolder = (filePath) => {
+ let pathTokens = path.dirname(filePath).split(path.sep)
+ pathTokens.pop()
+ return pathTokens.pop()
+}
+
+async function main() {
+ const cwd = process.cwd()
+
+ const files = glob
+ .sync('**/package.json', {
+ cwd: cwd,
+ ignore: '**/node_modules/**',
+ })
+ .filter((file) => {
+ const folder = getBaseFolder(file)
+ const allowList = ['orm', 'databases', 'data-modeling']
+ return allowList.includes(folder)
+ })
+ .map((file) => {
+ const folder = getBaseFolder(file)
+ const test = getTestName(file)
+ return { path: `${folder}/${test}` }
+ })
+
+ core.setOutput('matrix', JSON.stringify({ include: files }))
+}
+
+main()
diff --git a/.github/scripts/package.json b/.github/scripts/package.json
new file mode 100644
index 000000000000..56a9427eba24
--- /dev/null
+++ b/.github/scripts/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "scripts",
+ "version": "1.0.0",
+ "main": "index.js",
+ "license": "MIT",
+ "devDependencies": {
+ "glob": "10.4.5"
+ },
+ "dependencies": {
+ "@actions/core": "1.11.1"
+ }
+}
diff --git a/.github/scripts/test-all.sh b/.github/scripts/test-all.sh
new file mode 100644
index 000000000000..89936daedc96
--- /dev/null
+++ b/.github/scripts/test-all.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+set -eu
+
+item="$1"
+dir="$(pwd)"
+
+echo ""
+echo ""
+echo ""
+echo ""
+echo ""
+echo ""
+echo "---------------------"
+echo "running $item"
+
+case "$item" in
+ *".github"*|*"deployment-platforms"*|*"databases"*)
+ echo "ignoring $item"
+ exit 0
+ ;;
+esac
+
+cd "$(dirname "$item")/"
+
+## ACTION
+
+echo "+++++++++++"
+echo "executing .github/tests/$(dirname "$item")/run.sh (tests)"
+run_file="$dir/.github/tests/$(dirname "$item")/run.sh"
+
+if [ -f "$run_file" ]; then
+ set +e
+ bash "$run_file"
+ code=$?
+ set -e
+
+ cd "$dir"
+
+ if [ $code -ne 0 ]; then
+ echo "$(dirname "$item") failed"
+ exit $code
+ fi
+else
+ echo "no test file set up for $item,"
+ echo "please create a test shell file at $run_file"
+ exit 1
+fi
+
+## END
+
+echo "$item done"
+
+# somehow ports are still in use in GitHub actions, so kill everything here again
+pkill node || true
diff --git a/.github/stale.yml b/.github/stale.yml
deleted file mode 100644
index 93be6ab21739..000000000000
--- a/.github/stale.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Number of days of inactivity before an issue becomes stale
-daysUntilStale: 45
-# Number of days of inactivity before a stale issue is closed
-daysUntilClose: 10
-# Issues with these labels will never be considered stale
-exemptLabels:
- - status/on-hold
- - status/candidate
-# Label to use when marking an issue as stale
-staleLabel: status/stale
-# Comment to post when marking an issue as stale. Set to `false` to disable
-markComment: >
- This issue has been automatically marked as stale because it has not had
- recent activity. It will be closed in 10 days if no further activity occurs.
- Thank you for your contributions.
-# Comment to post when closing a stale issue. Set to `false` to disable
-closeComment: false
-# Limit to only `issues`
-only: issues
diff --git a/.github/tests/README.md b/.github/tests/README.md
new file mode 100644
index 000000000000..e6bfe5a5a4fd
--- /dev/null
+++ b/.github/tests/README.md
@@ -0,0 +1,6 @@
+# Tests
+
+This internal directory defines test scripts for our CI. Each project gets its
+own test script, but we use this hidden directory so we don't need to define it
+in each public project, since users checking out our examples don't care about
+that.
diff --git a/.github/tests/data-modeling/delegated-types/run.sh b/.github/tests/data-modeling/delegated-types/run.sh
new file mode 100644
index 000000000000..7aab6f474a72
--- /dev/null
+++ b/.github/tests/data-modeling/delegated-types/run.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -eu
+
+npm install
+npx prisma migrate dev --name init
+npm run test
diff --git a/.github/tests/databases/postgresql-supabase/run.sh b/.github/tests/databases/postgresql-supabase/run.sh
new file mode 100644
index 000000000000..ab052ffa23e9
--- /dev/null
+++ b/.github/tests/databases/postgresql-supabase/run.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# A blank script that always passes
+true
diff --git a/.github/tests/databases/prisma-postgres/run.sh b/.github/tests/databases/prisma-postgres/run.sh
new file mode 100644
index 000000000000..8e4ebd1ca802
--- /dev/null
+++ b/.github/tests/databases/prisma-postgres/run.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+set -euo pipefail
+
+# Move to Prisma project
+cd ../../../..
+cd databases/prisma-postgres
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [[ "$WAITED" -ge "$MAX_WAIT" ]]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Go back to databases/prisma-postgres
+
+# Run migration
+echo "📐 Running prisma migrate dev..."
+npx prisma migrate dev --name init --skip-seed
+
+# Run queries (if any)
+echo "🧪 Running queries..."
+npm run queries || echo "ℹ️ No queries script defined."
+
+# Cleanup
+echo "🛑 Shutting down Prisma Dev (PID $NODE_PID)..."
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/databases/sql-server/run.sh b/.github/tests/databases/sql-server/run.sh
new file mode 100644
index 000000000000..ab052ffa23e9
--- /dev/null
+++ b/.github/tests/databases/sql-server/run.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# A blank script that always passes
+true
diff --git a/.github/tests/orm/ai-sdk-nextjs/run.sh b/.github/tests/orm/ai-sdk-nextjs/run.sh
new file mode 100644
index 000000000000..c284b89201bf
--- /dev/null
+++ b/.github/tests/orm/ai-sdk-nextjs/run.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/ai-sdk-nextjs"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null
+
+npm install
+npx prisma migrate dev --name init --schema prisma/schema.prisma
+npx prisma db seed
+npm run dev &
+pid=$!
+
+sleep 15
+
+# check frontend
+curl --fail 'http://localhost:3000/'
+
+kill "$pid"
+echo "🛑 App stopped (PID $pid)"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/astro/run.sh b/.github/tests/orm/astro/run.sh
new file mode 100644
index 000000000000..1f1111d69ae2
--- /dev/null
+++ b/.github/tests/orm/astro/run.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/astro"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null
+
+npm install
+npx prisma migrate dev --name init --schema prisma/schema.prisma
+npm run dev &
+pid=$!
+
+sleep 15
+
+# check frontend
+curl --fail 'http://localhost:4321/'
+
+
+kill "$pid"
+echo "🛑 App stopped (PID $pid)"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/authjs-nextjs/run.sh b/.github/tests/orm/authjs-nextjs/run.sh
new file mode 100644
index 000000000000..21e22765a624
--- /dev/null
+++ b/.github/tests/orm/authjs-nextjs/run.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/authjs-nextjs"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null
+
+npm install
+npx prisma migrate dev --name init --schema prisma/schema.prisma
+npx prisma db seed
+npm run dev &
+pid=$!
+
+sleep 15
+
+# check frontend
+curl --fail 'http://localhost:3000/'
+
+kill "$pid"
+echo "🛑 App stopped (PID $pid)"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/betterauth-nextjs/run.sh b/.github/tests/orm/betterauth-nextjs/run.sh
new file mode 100644
index 000000000000..8c225943cdce
--- /dev/null
+++ b/.github/tests/orm/betterauth-nextjs/run.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/betterauth-nextjs"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null
+
+npm install
+npx prisma migrate dev --name init --schema prisma/schema.prisma
+npx prisma db seed
+npm run dev &
+pid=$!
+
+sleep 15
+
+# check frontend
+curl --fail 'http://localhost:3000/'
+
+kill "$pid"
+echo "🛑 App stopped (PID $pid)"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/clerk-nextjs/run.sh b/.github/tests/orm/clerk-nextjs/run.sh
new file mode 100644
index 000000000000..c01289666f19
--- /dev/null
+++ b/.github/tests/orm/clerk-nextjs/run.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/clerk-nextjs"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null
+
+npm install
+npx prisma migrate dev --name init
+npm run dev &
+pid=$!
+
+sleep 15
+
+# check frontend
+curl --fail 'http://localhost:3000/'
+
+kill "$pid"
+echo "🛑 App stopped (PID $pid)"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/express/run.sh b/.github/tests/orm/express/run.sh
new file mode 100755
index 000000000000..1ac18f61645a
--- /dev/null
+++ b/.github/tests/orm/express/run.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/express"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to databases/prisma-postgres
+
+# Run migrations + seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run Postman tests (relative to where the script was originally called)
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/rest.json" --bail
+
+
+kill "$pid"
+echo "🛑 App stopped (PID $pid)"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/fastify-graphql-sdl-first/run.sh b/.github/tests/orm/fastify-graphql-sdl-first/run.sh
new file mode 100644
index 000000000000..bf5c405993a9
--- /dev/null
+++ b/.github/tests/orm/fastify-graphql-sdl-first/run.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for fastify-graphql-sdl-first..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/fastify-graphql-sdl-first"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/fastify-graphql-sdl-first
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run GraphQL Postman collection
+echo "🧪 Running Postman tests..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/graphql-hapi.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/fastify-graphql/run.sh b/.github/tests/orm/fastify-graphql/run.sh
new file mode 100644
index 000000000000..97b81285598f
--- /dev/null
+++ b/.github/tests/orm/fastify-graphql/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for fastify-graphql..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/fastify-graphql"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/fastify-graphql
+
+# Run migrations and seed
+npx prisma migrate reset --force --skip-seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run GraphQL Postman tests
+echo "🧪 Running Postman tests..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/graphql-hapi.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/fastify/run.sh b/.github/tests/orm/fastify/run.sh
new file mode 100644
index 000000000000..ce97da683288
--- /dev/null
+++ b/.github/tests/orm/fastify/run.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for fastify..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/fastify"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/fastify
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run REST Postman tests
+echo "🧪 Running Postman tests..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/rest.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/graphql-auth/run.sh b/.github/tests/orm/graphql-auth/run.sh
new file mode 100644
index 000000000000..153290cf1432
--- /dev/null
+++ b/.github/tests/orm/graphql-auth/run.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for graphql-auth..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/graphql-auth"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/graphql-auth
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+npm run dev &
+pid=$!
+
+sleep 15
+
+# Test GraphQL endpoint
+echo "🧪 Testing GraphQL API..."
+curl --fail 'http://localhost:4000/' \
+ -H 'Accept-Encoding: gzip, deflate, br' \
+ -H 'Content-Type: application/json' \
+ -H 'Accept: application/json' \
+ -H 'Connection: keep-alive' \
+ -H 'DNT: 1' \
+ -H 'Origin: http://localhost:4000' \
+ --data-binary '{"query":"query {\n feed {\n id\n content\n author {\n id\n name\n email\n }\n }\n}"}' \
+ --compressed
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/graphql-nexus/run.sh b/.github/tests/orm/graphql-nexus/run.sh
new file mode 100644
index 000000000000..5942d32c008a
--- /dev/null
+++ b/.github/tests/orm/graphql-nexus/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for graphql-nexus..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/graphql-nexus"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/graphql-nexus
+
+# Run migrations and seed
+npx prisma migrate reset --force --skip-seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run GraphQL Newman test
+echo "🧪 Running Newman tests..."
+npx newman run ../../.github/tests/postman_collections/graphql.json --bail --verbose
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/graphql-sdl-first/run.sh b/.github/tests/orm/graphql-sdl-first/run.sh
new file mode 100644
index 000000000000..24eda9d645eb
--- /dev/null
+++ b/.github/tests/orm/graphql-sdl-first/run.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for graphql-sdl-first..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/graphql-sdl-first"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/graphql-sdl-first
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run GraphQL Newman test
+echo "🧪 Running Newman tests..."
+npx newman run ../../.github/tests/postman_collections/graphql.json --bail
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/graphql-subscriptions/run.sh b/.github/tests/orm/graphql-subscriptions/run.sh
new file mode 100644
index 000000000000..4d00d09639d9
--- /dev/null
+++ b/.github/tests/orm/graphql-subscriptions/run.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for graphql-subscriptions..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/graphql-subscriptions"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/graphql-subscriptions
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the GraphQL subscriptions server
+echo "🚀 Starting app..."
+npm run dev &
+pid=$!
+
+sleep 15
+
+# Run test query
+echo "🔎 Running sample GraphQL query..."
+curl --fail 'http://localhost:4000/graphql' \
+ -H 'Accept-Encoding: gzip, deflate, br' \
+ -H 'Content-Type: application/json' \
+ -H 'Accept: application/json' \
+ -H 'Connection: keep-alive' \
+ -H 'DNT: 1' \
+ -H 'Origin: http://localhost:4000' \
+ --data-binary '{"query":"query {\n feed {\n id\n title\n content\n }\n}"}' \
+ --compressed
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/graphql/run.sh b/.github/tests/orm/graphql/run.sh
new file mode 100644
index 000000000000..df45db90b3d9
--- /dev/null
+++ b/.github/tests/orm/graphql/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for graphql..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/graphql"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/graphql
+
+# Run migrations and seed
+npx prisma migrate reset --force --skip-seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run GraphQL Postman collection
+echo "🧪 Running Postman tests..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/graphql.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/grpc/run.sh b/.github/tests/orm/grpc/run.sh
new file mode 100644
index 000000000000..2c7475d63d77
--- /dev/null
+++ b/.github/tests/orm/grpc/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for grpc..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/grpc"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/grpc
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the gRPC app
+echo "🚀 Starting gRPC app..."
+npm run dev &
+pid=$!
+
+sleep 10
+
+# Trigger gRPC query logic (e.g. feeding test data)
+echo "🧪 Running feed task..."
+npm run feed
+
+# Cleanup
+echo "🛑 Shutting down gRPC app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/hapi-graphql-sdl-first/run.sh b/.github/tests/orm/hapi-graphql-sdl-first/run.sh
new file mode 100644
index 000000000000..88e94af66f6b
--- /dev/null
+++ b/.github/tests/orm/hapi-graphql-sdl-first/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for hapi-graphql-sdl-first..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/hapi-graphql-sdl-first"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/hapi-graphql-sdl-first
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting Hapi GraphQL app..."
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run Postman test
+echo "🧪 Running Newman test for GraphQL Hapi..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/graphql-hapi.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down Hapi app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/hapi-graphql/run.sh b/.github/tests/orm/hapi-graphql/run.sh
new file mode 100644
index 000000000000..1cf3ba81cb58
--- /dev/null
+++ b/.github/tests/orm/hapi-graphql/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for hapi-graphql..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/hapi-graphql"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/hapi-graphql
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting Hapi GraphQL app..."
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run Postman test
+echo "🧪 Running Newman test for GraphQL Hapi..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/graphql-hapi.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down Hapi app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/hapi/run.sh b/.github/tests/orm/hapi/run.sh
new file mode 100644
index 000000000000..f0b734f5fc30
--- /dev/null
+++ b/.github/tests/orm/hapi/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for hapi..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/hapi"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/hapi
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting Hapi app..."
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run REST tests via Postman
+echo "🧪 Running Newman test for REST API..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/rest.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down Hapi app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/hono/run.sh b/.github/tests/orm/hono/run.sh
new file mode 100644
index 000000000000..7d10e7676f8d
--- /dev/null
+++ b/.github/tests/orm/hono/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for hono..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/hono"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/hono
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting Hono app..."
+npm run dev &
+pid=$!
+
+sleep 15
+
+# Check frontend
+echo "🔎 Verifying root frontend route..."
+curl --fail 'http://localhost:3000/'
+
+# Cleanup
+echo "🛑 Shutting down Hono app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/koa/run.sh b/.github/tests/orm/koa/run.sh
new file mode 100644
index 000000000000..8f4103b0b8a2
--- /dev/null
+++ b/.github/tests/orm/koa/run.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for koa..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/koa"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/koa
+
+# Run migrations and seed
+npx prisma migrate reset --force --skip-seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting Koa app..."
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run Postman test
+echo "🧪 Running Newman test for REST Koa..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/rest.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down Koa app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/nest-graphql-sdl-first/run.sh b/.github/tests/orm/nest-graphql-sdl-first/run.sh
new file mode 100644
index 000000000000..38f301ab0c63
--- /dev/null
+++ b/.github/tests/orm/nest-graphql-sdl-first/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for nest-graphql-sdl-first..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/nest-graphql-sdl-first"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/nest-graphql-sdl-first
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting NestJS GraphQL app..."
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run Postman GraphQL test
+echo "🧪 Running Newman test for NestJS GraphQL..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/graphql-nestjs.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down NestJS app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/nest-graphql/run.sh b/.github/tests/orm/nest-graphql/run.sh
new file mode 100644
index 000000000000..2273f55d3d48
--- /dev/null
+++ b/.github/tests/orm/nest-graphql/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for nest-graphql..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/nest-graphql"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/nest-graphql
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting NestJS GraphQL app..."
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run Postman test
+echo "🧪 Running Newman test for NestJS GraphQL..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/graphql-nestjs.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down NestJS app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/nest/run.sh b/.github/tests/orm/nest/run.sh
new file mode 100644
index 000000000000..1767486756cf
--- /dev/null
+++ b/.github/tests/orm/nest/run.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for nest..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/nest"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/nest
+
+# Run migrations and seed
+npx prisma migrate reset --force --skip-seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting NestJS app..."
+npm run dev &
+pid=$!
+
+sleep 20
+
+# Run Postman test
+echo "🧪 Running Newman test for REST NestJS..."
+npx newman run "$REPO_ROOT/.github/tests/postman_collections/rest.json" --bail
+
+# Cleanup
+echo "🛑 Shutting down NestJS app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/nextjs-graphql/run.sh b/.github/tests/orm/nextjs-graphql/run.sh
new file mode 100644
index 000000000000..8a4aaba08b3a
--- /dev/null
+++ b/.github/tests/orm/nextjs-graphql/run.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for nextjs-graphql..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/nextjs-graphql"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/nextjs-graphql
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting Next.js app..."
+npm run dev &
+pid=$!
+
+sleep 15
+
+# Check GraphQL API
+echo "🔎 Verifying /api/graphql endpoint..."
+curl --fail 'http://localhost:3000/api/graphql' \
+ -H 'Accept-Encoding: gzip, deflate, br' \
+ -H 'Content-Type: application/json' \
+ -H 'Accept: application/json' \
+ -H 'Connection: keep-alive' \
+ -H 'DNT: 1' \
+ -H 'Origin: http://localhost:4000' \
+ --data-binary '{"query":"query {\n feed {\n id\n content\n author {\n id\n name\n email\n }\n }\n}"}' \
+ --compressed
+
+# Check frontend
+echo "🔎 Verifying root frontend route..."
+curl --fail 'http://localhost:3000/'
+
+# Cleanup
+echo "🛑 Shutting down Next.js app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/nextjs-trpc/run.sh b/.github/tests/orm/nextjs-trpc/run.sh
new file mode 100644
index 000000000000..159c0d53a754
--- /dev/null
+++ b/.github/tests/orm/nextjs-trpc/run.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for nextjs-trpc..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/nextjs-trpc"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install --legacy-peer-deps
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null
+
+# Run migrations
+npx prisma migrate dev --name init
+
+# Start the app
+echo "🚀 Starting Next.js app..."
+npm run dev &
+pid=$!
+
+sleep 15
+
+# Check frontend (Next defaults to port 3000)
+echo "🔎 Verifying root frontend route..."
+curl --fail 'http://localhost:3000/'
+
+# Cleanup
+echo "🛑 Shutting down Next.js app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
+
+
diff --git a/.github/tests/orm/nextjs/run.sh b/.github/tests/orm/nextjs/run.sh
new file mode 100644
index 000000000000..cf632322516e
--- /dev/null
+++ b/.github/tests/orm/nextjs/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for nextjs..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/nextjs"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/nextjs
+
+# Run migrations and seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🚀 Starting Next.js app..."
+npm run dev &
+pid=$!
+
+sleep 15
+
+# Check frontend
+echo "🔎 Verifying root frontend route..."
+curl --fail 'http://localhost:3000/'
+
+# Cleanup
+echo "🛑 Shutting down Next.js app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/nuxt-prisma-module/run.sh b/.github/tests/orm/nuxt-prisma-module/run.sh
new file mode 100644
index 000000000000..d1e6d88a2695
--- /dev/null
+++ b/.github/tests/orm/nuxt-prisma-module/run.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+# This script simply returns true
+exit 0
diff --git a/.github/tests/orm/nuxt/run.sh b/.github/tests/orm/nuxt/run.sh
new file mode 100644
index 000000000000..ae5fbe2f90d5
--- /dev/null
+++ b/.github/tests/orm/nuxt/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for nuxt..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/nuxt"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/nuxt
+
+# Run migration + seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Start the app
+echo "🧪 Starting Nuxt app..."
+npm run dev &
+pid=$!
+
+sleep 15
+
+# Check frontend
+echo "🔎 Checking http://localhost:3000/"
+curl --fail 'http://localhost:3000/'
+
+# Cleanup
+echo "🛑 Shutting down Nuxt app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/postgis-express/run.sh b/.github/tests/orm/postgis-express/run.sh
new file mode 100644
index 000000000000..1ef02f838dce
--- /dev/null
+++ b/.github/tests/orm/postgis-express/run.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+set -eu
+
+npm install && npm run test
diff --git a/.github/tests/orm/prisma-mocking-javascript/run.sh b/.github/tests/orm/prisma-mocking-javascript/run.sh
new file mode 100644
index 000000000000..c0474751b08c
--- /dev/null
+++ b/.github/tests/orm/prisma-mocking-javascript/run.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -eu
+
+npm install
+npx prisma generate
+
+npm run test
diff --git a/.github/tests/orm/react-router-7/run.sh b/.github/tests/orm/react-router-7/run.sh
new file mode 100644
index 000000000000..087721f9043f
--- /dev/null
+++ b/.github/tests/orm/react-router-7/run.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for react-router-7..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/react-router-7"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/react-router-7
+
+# Run migrations and seed
+echo "📐 Running Prisma migrations and seeding..."
+DATABASE_URL="$DATABASE_URL" npx prisma migrate reset --force --skip-seed
+DATABASE_URL="$DATABASE_URL" npx prisma migrate dev --name init
+DATABASE_URL="$DATABASE_URL" npx prisma db seed
+
+# Start the app
+echo "🚀 Starting the React Router 7 app..."
+npm run dev &
+pid=$!
+
+# Wait for server
+sleep 15
+
+# Test frontend
+echo "🧪 Checking frontend response..."
+curl --fail 'http://localhost:5173/'
+
+# Cleanup
+echo "🛑 Shutting down React Router app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/script/run.sh b/.github/tests/orm/script/run.sh
new file mode 100644
index 000000000000..73762b826565
--- /dev/null
+++ b/.github/tests/orm/script/run.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for script..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/script"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/script
+
+# Run migrations (reset and dev)
+npx prisma migrate dev --name init
+
+# Run script (assumes it terminates; remove `&` if it blocks)
+npm run dev
+
+# Cleanup Prisma Dev server
+echo "🛑 Shutting down Prisma Dev (PID $NODE_PID)..."
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/solid-start/run.sh b/.github/tests/orm/solid-start/run.sh
new file mode 100644
index 000000000000..2a152354c85f
--- /dev/null
+++ b/.github/tests/orm/solid-start/run.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for solid-start..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/solid-start"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/solid-start
+
+# Run migrations
+npx prisma migrate dev --name init
+
+# Start the app
+echo "🧪 Starting app..."
+npm run dev &
+pid=$!
+
+sleep 15
+
+# Check frontend
+echo "🔎 Checking http://localhost:3000/"
+curl --fail 'http://localhost:3000/'
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/starter/run.sh b/.github/tests/orm/starter/run.sh
new file mode 100644
index 000000000000..47eca0c26905
--- /dev/null
+++ b/.github/tests/orm/starter/run.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+set -eu
+
+npm install
+npm run build
diff --git a/.github/tests/orm/sveltekit/run.sh b/.github/tests/orm/sveltekit/run.sh
new file mode 100644
index 000000000000..60043b80d814
--- /dev/null
+++ b/.github/tests/orm/sveltekit/run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for sveltekit..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/sveltekit"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/sveltekit
+
+# Run migrations + seed
+npx prisma migrate dev --name init --schema prisma/schema.prisma
+npx prisma db seed
+
+# Start the app
+echo "🧪 Starting app..."
+npm run dev &
+pid=$!
+
+sleep 15
+
+# Check frontend
+echo "🔎 Checking http://localhost:5173/"
+curl --fail 'http://localhost:5173/'
+
+# Cleanup
+echo "🛑 Shutting down app (PID $pid) and Prisma Dev (PID $NODE_PID)..."
+kill "$pid"
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/testing-express/run.sh b/.github/tests/orm/testing-express/run.sh
new file mode 100644
index 000000000000..11ff07d97770
--- /dev/null
+++ b/.github/tests/orm/testing-express/run.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+set -eu
+
+echo "🔍 Starting test setup for testing-express..."
+
+echo "📂 Current working directory before REPO_ROOT: $(pwd)"
+echo "📁 Listing contents:"
+ls -la
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+echo "📌 Detected repo root: $REPO_ROOT"
+
+cd "$REPO_ROOT/orm/testing-express"
+echo "📂 Changed directory to: $(pwd)"
+
+echo "📦 Installing test deps..."
+npm install
+
+# Go to Node script dir and install its deps
+NODE_SCRIPT_DIR="../../.github/get-ppg-dev"
+pushd "$NODE_SCRIPT_DIR" > /dev/null
+npm install
+
+# Start Prisma Dev server
+LOG_FILE="./ppg-dev-url.log"
+rm -f "$LOG_FILE"
+touch "$LOG_FILE"
+
+echo "🚀 Starting Prisma Dev in background..."
+node index.js >"$LOG_FILE" &
+NODE_PID=$!
+
+# Wait for DATABASE_URL
+echo "🔎 Waiting for Prisma Dev to emit DATABASE_URL..."
+MAX_WAIT=60
+WAITED=0
+until grep -q '^prisma+postgres://' "$LOG_FILE"; do
+ sleep 1
+ WAITED=$((WAITED + 1))
+ if [ "$WAITED" -ge "$MAX_WAIT" ]; then
+ echo "❌ Timeout waiting for DATABASE_URL"
+ cat "$LOG_FILE"
+ kill "$NODE_PID" || true
+ exit 1
+ fi
+done
+
+DB_URL=$(grep '^prisma+postgres://' "$LOG_FILE" | tail -1)
+export DATABASE_URL="$DB_URL"
+echo "✅ DATABASE_URL: $DATABASE_URL"
+
+popd > /dev/null # Back to orm/testing-express
+
+# Run migrations + seed
+npx prisma migrate dev --name init
+npx prisma db seed
+
+# Run test suite
+echo "🧪 Running tests..."
+npm run test
+
+# Cleanup
+echo "🛑 Shutting down Prisma Dev (PID $NODE_PID)..."
+kill "$NODE_PID"
+wait "$NODE_PID" || true
diff --git a/.github/tests/orm/typedsql/run.sh b/.github/tests/orm/typedsql/run.sh
new file mode 100644
index 000000000000..15a976e00e3b
--- /dev/null
+++ b/.github/tests/orm/typedsql/run.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -eu
+
+npm install
+npx prisma migrate dev --name init
+npx prisma generate --sql
+npm run test
diff --git a/.github/tests/package.json b/.github/tests/package.json
deleted file mode 100644
index 63f5781aed28..000000000000
--- a/.github/tests/package.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "name": "prisma-examples",
- "version": "1.0.0",
- "repository": "git@github.com:prisma/prisma-examples.git",
- "license": "MIT",
- "scripts": {
- "test": "yarn prettier-check && yarn build-readmes",
- "build-readmes": "inline-markdown --input ../readmes --output ../..",
- "prettier-check": "prettier-check --config .prettierrc \"../../{node,flow,typescript}/*/{src,test,prisma}/**/*.{ts,js}\"",
- "prettier-fix": "prettier --config .prettierrc --write \"../../{node,flow,typescript}/*/{src,test,prisma}/**/*.{ts,js}\""
- },
- "devDependencies": {
- "inline-markdown": "0.1.6",
- "prettier": "1.16.4",
- "prettier-check": "2.0.0"
- }
-}
diff --git a/.github/tests/postman_collections/graphql-hapi.json b/.github/tests/postman_collections/graphql-hapi.json
new file mode 100644
index 000000000000..61215675449a
--- /dev/null
+++ b/.github/tests/postman_collections/graphql-hapi.json
@@ -0,0 +1,564 @@
+{
+ "info": {
+ "_postman_id": "ce5cf911-9948-44ef-8a34-b00b90c1cba6",
+ "name": "prisma-examples-graphql-hapi",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "users",
+ "item": [
+ {
+ "name": "signup",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const signupUser = {\r",
+ " \"data\": {\r",
+ " \"signupUser\": {\r",
+ " \"id\": 4\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(signupUser);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n signupUser(data: { name: \"Sarah\", email: \"sarah@prisma.io\" }) {\r\n id\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "createDraft",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const draft = {\r",
+ " \"data\": {\r",
+ " \"createDraft\": {\r",
+ " \"id\": 5,\r",
+ " \"viewCount\": 0,\r",
+ " \"published\": false,\r",
+ " \"author\": {\r",
+ " \"id\": 1,\r",
+ " \"name\": \"Alice\"\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(draft);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n createDraft(\r\n data: { title: \"Join the Prisma Discord\", content: \"https://pris.ly/discord/" }\r\n authorEmail: \"alice@prisma.io\"\r\n ) {\r\n id\r\n viewCount\r\n published\r\n author {\r\n id\r\n name\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
+ "name": "posts",
+ "item": [
+ {
+ "name": "feed",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": 1,\r",
+ " \"name\": \"Alice\",\r",
+ " \"email\": \"alice@prisma.io\"\r",
+ " }\r",
+ " },\r",
+ " {\r",
+ " \"id\": 2,\r",
+ " \"title\": \"Follow Prisma on Twitter\",\r",
+ " \"content\": \"https://www.twitter.com/prisma/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": 2,\r",
+ " \"name\": \"Nilu\",\r",
+ " \"email\": \"nilu@prisma.io\"\r",
+ " }\r",
+ " },\r",
+ " {\r",
+ " \"id\": 3,\r",
+ " \"title\": \"Ask a question about Prisma on GitHub\",\r",
+ " \"content\": \"https://www.github.com/prisma/prisma/discussions/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": 3,\r",
+ " \"name\": \"Mahmoud\",\r",
+ " \"email\": \"mahmoud@prisma.io\"\r",
+ " }\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "query {\r\n feed {\r\n id\r\n title\r\n content\r\n published\r\n author {\r\n id\r\n name\r\n email\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "feed-searchString",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true\r",
+ " },\r",
+ " {\r",
+ " \"id\": 2,\r",
+ " \"title\": \"Follow Prisma on Twitter\",\r",
+ " \"content\": \"https://www.twitter.com/prisma/",\r",
+ " \"published\": true\r",
+ " },\r",
+ " {\r",
+ " \"id\": 3,\r",
+ " \"title\": \"Ask a question about Prisma on GitHub\",\r",
+ " \"content\": \"https://www.github.com/prisma/prisma/discussions/",\r",
+ " \"published\": true\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n feed(\r\n searchString: \"Prisma\"\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "feed-pagination_order",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n feed(\r\n skip: 2\r\n take: 2\r\n orderBy: { updatedAt: desc }\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "postById",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"postById\": {\r",
+ " \"id\": 4,\r",
+ " \"title\": \"Prisma on YouTube\",\r",
+ " \"content\": \"https://pris.ly/youtube/",\r",
+ " \"published\": false\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n postById(id: 4) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "draftsByUser",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const draftsByUser = {\r",
+ " \"data\": {\r",
+ " \"draftsByUser\": [\r",
+ " {\r",
+ " \"id\": 4,\r",
+ " \"title\": \"Prisma on YouTube\",\r",
+ " \"content\": \"https://pris.ly/youtube/",\r",
+ " \"published\": false,\r",
+ " \"author\": {\r",
+ " \"id\": 3,\r",
+ " \"name\": \"Mahmoud\",\r",
+ " \"email\": \"mahmoud@prisma.io\"\r",
+ " }\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(draftsByUser);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n draftsByUser(\r\n userUniqueInput: {\r\n email: \"mahmoud@prisma.io\"\r\n }\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n author {\r\n id\r\n name\r\n email\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "togglePublishPost",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"togglePublishPost\": {\r",
+ " \"id\": 5,\r",
+ " \"published\": true\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n togglePublishPost(id: 5) {\r\n id\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "incrementPostViewCount",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"incrementPostViewCount\": {\r",
+ " \"id\": 5,\r",
+ " \"viewCount\": 1\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n incrementPostViewCount(id: 5) {\r\n id\r\n viewCount\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "deletePost",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"deletePost\": {\r",
+ " \"id\": 5\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n deletePost(id: 5) {\r\n id\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000/graphql",
+ "host": ["localhost"],
+ "port": "4000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/.github/tests/postman_collections/graphql-nestjs.json b/.github/tests/postman_collections/graphql-nestjs.json
new file mode 100644
index 000000000000..8e3ffcafc078
--- /dev/null
+++ b/.github/tests/postman_collections/graphql-nestjs.json
@@ -0,0 +1,564 @@
+{
+ "info": {
+ "_postman_id": "f321f81e-ceea-46a9-82a5-16cb5119f671",
+ "name": "prisma-examples-graphql-nestjs",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "users",
+ "item": [
+ {
+ "name": "signup",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const signupUser = {\r",
+ " \"data\": {\r",
+ " \"signupUser\": {\r",
+ " \"id\": 4\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(signupUser);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n signupUser(data: { name: \"Sarah\", email: \"sarah@prisma.io\" }) {\r\n id\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "createDraft",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const draft = {\r",
+ " \"data\": {\r",
+ " \"createDraft\": {\r",
+ " \"id\": 5,\r",
+ " \"viewCount\": 0,\r",
+ " \"published\": false,\r",
+ " \"author\": {\r",
+ " \"id\": 1,\r",
+ " \"name\": \"Alice\"\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(draft);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n createDraft(\r\n data: { title: \"Join the Prisma Discord\", content: \"https://pris.ly/discord/" }\r\n authorEmail: \"alice@prisma.io\"\r\n ) {\r\n id\r\n viewCount\r\n published\r\n author {\r\n id\r\n name\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
+ "name": "posts",
+ "item": [
+ {
+ "name": "feed",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": 1,\r",
+ " \"name\": \"Alice\",\r",
+ " \"email\": \"alice@prisma.io\"\r",
+ " }\r",
+ " },\r",
+ " {\r",
+ " \"id\": 2,\r",
+ " \"title\": \"Follow Prisma on Twitter\",\r",
+ " \"content\": \"https://www.twitter.com/prisma/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": 2,\r",
+ " \"name\": \"Nilu\",\r",
+ " \"email\": \"nilu@prisma.io\"\r",
+ " }\r",
+ " },\r",
+ " {\r",
+ " \"id\": 3,\r",
+ " \"title\": \"Ask a question about Prisma on GitHub\",\r",
+ " \"content\": \"https://www.github.com/prisma/prisma/discussions/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": 3,\r",
+ " \"name\": \"Mahmoud\",\r",
+ " \"email\": \"mahmoud@prisma.io\"\r",
+ " }\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "query {\r\n feed {\r\n id\r\n title\r\n content\r\n published\r\n author {\r\n id\r\n name\r\n email\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "feed-searchString",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true\r",
+ " },\r",
+ " {\r",
+ " \"id\": 2,\r",
+ " \"title\": \"Follow Prisma on Twitter\",\r",
+ " \"content\": \"https://www.twitter.com/prisma/",\r",
+ " \"published\": true\r",
+ " },\r",
+ " {\r",
+ " \"id\": 3,\r",
+ " \"title\": \"Ask a question about Prisma on GitHub\",\r",
+ " \"content\": \"https://www.github.com/prisma/prisma/discussions/",\r",
+ " \"published\": true\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n feed(\r\n searchString: \"Prisma\"\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "feed-pagination_order",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n feed(\r\n skip: 2\r\n take: 2\r\n orderBy: { updatedAt: desc }\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "postById",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"postById\": {\r",
+ " \"id\": 4,\r",
+ " \"title\": \"Prisma on YouTube\",\r",
+ " \"content\": \"https://pris.ly/youtube/",\r",
+ " \"published\": false\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n postById(id: 4) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "draftsByUser",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const draftsByUser = {\r",
+ " \"data\": {\r",
+ " \"draftsByUser\": [\r",
+ " {\r",
+ " \"id\": 4,\r",
+ " \"title\": \"Prisma on YouTube\",\r",
+ " \"content\": \"https://pris.ly/youtube/",\r",
+ " \"published\": false,\r",
+ " \"author\": {\r",
+ " \"id\": 3,\r",
+ " \"name\": \"Mahmoud\",\r",
+ " \"email\": \"mahmoud@prisma.io\"\r",
+ " }\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(draftsByUser);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n draftsByUser(\r\n userUniqueInput: {\r\n email: \"mahmoud@prisma.io\"\r\n }\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n author {\r\n id\r\n name\r\n email\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "togglePublishPost",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"togglePublishPost\": {\r",
+ " \"id\": 5,\r",
+ " \"published\": true\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n togglePublishPost(id: 5) {\r\n id\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "incrementPostViewCount",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"incrementPostViewCount\": {\r",
+ " \"id\": 5,\r",
+ " \"viewCount\": 1\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n incrementPostViewCount(id: 5) {\r\n id\r\n viewCount\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "deletePost",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"deletePost\": {\r",
+ " \"id\": 5\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n deletePost(id: 5) {\r\n id\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:3000/graphql",
+ "host": ["localhost"],
+ "port": "3000",
+ "path": ["graphql"]
+ }
+ },
+ "response": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/.github/tests/postman_collections/graphql-typegraphql.json b/.github/tests/postman_collections/graphql-typegraphql.json
new file mode 100644
index 000000000000..4118d85840b0
--- /dev/null
+++ b/.github/tests/postman_collections/graphql-typegraphql.json
@@ -0,0 +1,554 @@
+{
+ "info": {
+ "_postman_id": "a2666eb5-efb3-45b4-8064-8b57823aed94",
+ "name": "prisma-examples-graphql-typegraphql",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "users",
+ "item": [
+ {
+ "name": "signup",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const signupUser = {\r",
+ " \"data\": {\r",
+ " \"signupUser\": {\r",
+ " \"id\": \"4\"\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(signupUser);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n signupUser(data: { name: \"Sarah\", email: \"sarah@prisma.io\" }) {\r\n id\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "createDraft",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const draft = {\r",
+ " \"data\": {\r",
+ " \"createDraft\": {\r",
+ " \"id\": \"5\",\r",
+ " \"viewCount\": 0,\r",
+ " \"published\": false,\r",
+ " \"author\": {\r",
+ " \"id\": \"1\",\r",
+ " \"name\": \"Alice\"\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(draft);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n createDraft(\r\n data: { title: \"Join the Prisma Discord\", content: \"https://pris.ly/discord/" }\r\n authorEmail: \"alice@prisma.io\"\r\n ) {\r\n id\r\n viewCount\r\n published\r\n author {\r\n id\r\n name\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
+ "name": "posts",
+ "item": [
+ {
+ "name": "feed",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": \"1\",\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": \"1\",\r",
+ " \"name\": \"Alice\",\r",
+ " \"email\": \"alice@prisma.io\"\r",
+ " }\r",
+ " },\r",
+ " {\r",
+ " \"id\": \"2\",\r",
+ " \"title\": \"Follow Prisma on Twitter\",\r",
+ " \"content\": \"https://www.twitter.com/prisma/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": \"2\",\r",
+ " \"name\": \"Nilu\",\r",
+ " \"email\": \"nilu@prisma.io\"\r",
+ " }\r",
+ " },\r",
+ " {\r",
+ " \"id\": \"3\",\r",
+ " \"title\": \"Ask a question about Prisma on GitHub\",\r",
+ " \"content\": \"https://www.github.com/prisma/prisma/discussions/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": \"3\",\r",
+ " \"name\": \"Mahmoud\",\r",
+ " \"email\": \"mahmoud@prisma.io\"\r",
+ " }\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "query {\r\n feed {\r\n id\r\n title\r\n content\r\n published\r\n author {\r\n id\r\n name\r\n email\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "feed-searchString",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": \"1\",\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true\r",
+ " },\r",
+ " {\r",
+ " \"id\": \"2\",\r",
+ " \"title\": \"Follow Prisma on Twitter\",\r",
+ " \"content\": \"https://www.twitter.com/prisma/",\r",
+ " \"published\": true\r",
+ " },\r",
+ " {\r",
+ " \"id\": \"3\",\r",
+ " \"title\": \"Ask a question about Prisma on GitHub\",\r",
+ " \"content\": \"https://www.github.com/prisma/prisma/discussions/",\r",
+ " \"published\": true\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n feed(\r\n searchString: \"Prisma\"\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "feed-pagination_order",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": \"1\",\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n feed(\r\n skip: 2\r\n take: 2\r\n orderBy: { updatedAt: desc }\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "postById",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"postById\": {\r",
+ " \"id\": \"4\",\r",
+ " \"title\": \"Prisma on YouTube\",\r",
+ " \"content\": \"https://pris.ly/youtube/",\r",
+ " \"published\": false\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n postById(id: 4) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "draftsByUser",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const draftsByUser = {\r",
+ " \"data\": {\r",
+ " \"draftsByUser\": [\r",
+ " {\r",
+ " \"id\": \"4\",\r",
+ " \"title\": \"Prisma on YouTube\",\r",
+ " \"content\": \"https://pris.ly/youtube/",\r",
+ " \"published\": false,\r",
+ " \"author\": {\r",
+ " \"id\": \"3\",\r",
+ " \"name\": \"Mahmoud\",\r",
+ " \"email\": \"mahmoud@prisma.io\"\r",
+ " }\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(draftsByUser);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n draftsByUser(\r\n userUniqueInput: {\r\n email: \"mahmoud@prisma.io\"\r\n }\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n author {\r\n id\r\n name\r\n email\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "togglePublishPost",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"togglePublishPost\": {\r",
+ " \"id\": \"5\",\r",
+ " \"published\": true\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n togglePublishPost(id: 5) {\r\n id\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "incrementPostViewCount",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"incrementPostViewCount\": {\r",
+ " \"id\": \"5\",\r",
+ " \"viewCount\": 1\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n incrementPostViewCount(id: 5) {\r\n id\r\n viewCount\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "deletePost",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"deletePost\": {\r",
+ " \"id\": \"5\"\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n deletePost(id: 5) {\r\n id\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/.github/tests/postman_collections/graphql.json b/.github/tests/postman_collections/graphql.json
new file mode 100644
index 000000000000..3fc74ed20966
--- /dev/null
+++ b/.github/tests/postman_collections/graphql.json
@@ -0,0 +1,554 @@
+{
+ "info": {
+ "_postman_id": "2ebc4c96-bff0-4d4a-a0c0-d2ada09847a1",
+ "name": "prisma-examples-graphql",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "users",
+ "item": [
+ {
+ "name": "signup",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const signupUser = {\r",
+ " \"data\": {\r",
+ " \"signupUser\": {\r",
+ " \"id\": 4\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(signupUser);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n signupUser(data: { name: \"Sarah\", email: \"sarah@prisma.io\" }) {\r\n id\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "createDraft",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const draft = {\r",
+ " \"data\": {\r",
+ " \"createDraft\": {\r",
+ " \"id\": 5,\r",
+ " \"viewCount\": 0,\r",
+ " \"published\": false,\r",
+ " \"author\": {\r",
+ " \"id\": 1,\r",
+ " \"name\": \"Alice\"\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(draft);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n createDraft(\r\n data: { title: \"Join the Prisma Discord\", content: \"https://pris.ly/discord/" }\r\n authorEmail: \"alice@prisma.io\"\r\n ) {\r\n id\r\n viewCount\r\n published\r\n author {\r\n id\r\n name\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
+ "name": "posts",
+ "item": [
+ {
+ "name": "feed",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": 1,\r",
+ " \"name\": \"Alice\",\r",
+ " \"email\": \"alice@prisma.io\"\r",
+ " }\r",
+ " },\r",
+ " {\r",
+ " \"id\": 2,\r",
+ " \"title\": \"Follow Prisma on Twitter\",\r",
+ " \"content\": \"https://www.twitter.com/prisma/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": 2,\r",
+ " \"name\": \"Nilu\",\r",
+ " \"email\": \"nilu@prisma.io\"\r",
+ " }\r",
+ " },\r",
+ " {\r",
+ " \"id\": 3,\r",
+ " \"title\": \"Ask a question about Prisma on GitHub\",\r",
+ " \"content\": \"https://www.github.com/prisma/prisma/discussions/",\r",
+ " \"published\": true,\r",
+ " \"author\": {\r",
+ " \"id\": 3,\r",
+ " \"name\": \"Mahmoud\",\r",
+ " \"email\": \"mahmoud@prisma.io\"\r",
+ " }\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "query {\r\n feed {\r\n id\r\n title\r\n content\r\n published\r\n author {\r\n id\r\n name\r\n email\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "feed-searchString",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true\r",
+ " },\r",
+ " {\r",
+ " \"id\": 2,\r",
+ " \"title\": \"Follow Prisma on Twitter\",\r",
+ " \"content\": \"https://www.twitter.com/prisma/",\r",
+ " \"published\": true\r",
+ " },\r",
+ " {\r",
+ " \"id\": 3,\r",
+ " \"title\": \"Ask a question about Prisma on GitHub\",\r",
+ " \"content\": \"https://www.github.com/prisma/prisma/discussions/",\r",
+ " \"published\": true\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n feed(\r\n searchString: \"Prisma\"\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "feed-pagination_order",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"feed\": [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"title\": \"Join the Prisma Discord\",\r",
+ " \"content\": \"https://pris.ly/discord/",\r",
+ " \"published\": true\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ "}\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n feed(\r\n skip: 2\r\n take: 2\r\n orderBy: { updatedAt: desc }\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "postById",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const feed = {\r",
+ " \"data\": {\r",
+ " \"postById\": {\r",
+ " \"id\": 4,\r",
+ " \"title\": \"Prisma on YouTube\",\r",
+ " \"content\": \"https://pris.ly/youtube/",\r",
+ " \"published\": false\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(feed);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n postById(id: 4 ) {\r\n id\r\n title\r\n content\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "draftsByUser",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const draftsByUser = {\r",
+ " \"data\": {\r",
+ " \"draftsByUser\": [\r",
+ " {\r",
+ " \"id\": 4,\r",
+ " \"title\": \"Prisma on YouTube\",\r",
+ " \"content\": \"https://pris.ly/youtube/",\r",
+ " \"published\": false,\r",
+ " \"author\": {\r",
+ " \"id\": 3,\r",
+ " \"name\": \"Mahmoud\",\r",
+ " \"email\": \"mahmoud@prisma.io\"\r",
+ " }\r",
+ " }\r",
+ " ]\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(draftsByUser);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n draftsByUser(\r\n userUniqueInput: {\r\n email: \"mahmoud@prisma.io\"\r\n }\r\n ) {\r\n id\r\n title\r\n content\r\n published\r\n author {\r\n id\r\n name\r\n email\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "togglePublishPost",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"togglePublishPost\": {\r",
+ " \"id\": 5,\r",
+ " \"published\": true\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n togglePublishPost(id: 5) {\r\n id\r\n published\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "incrementPostViewCount",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"incrementPostViewCount\": {\r",
+ " \"id\": 5,\r",
+ " \"viewCount\": 1\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n incrementPostViewCount(id: 5) {\r\n id\r\n viewCount\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "deletePost",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {\r",
+ " pm.response.to.have.status(200);\r",
+ "});\r",
+ "\r",
+ "pm.test(\"Response body is valid\", function () {\r",
+ " const post = {\r",
+ " \"data\": {\r",
+ " \"deletePost\": {\r",
+ " \"id\": 5\r",
+ " }\r",
+ " }\r",
+ " }\r",
+ " \r",
+ " const jsonData = pm.response.json();\r",
+ " pm.expect(jsonData).to.eql(post);\r",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation {\r\n deletePost(id: 5) {\r\n id\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "localhost:4000",
+ "host": ["localhost"],
+ "port": "4000"
+ }
+ },
+ "response": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/.github/tests/postman_collections/rest.json b/.github/tests/postman_collections/rest.json
new file mode 100644
index 000000000000..e6166330c61a
--- /dev/null
+++ b/.github/tests/postman_collections/rest.json
@@ -0,0 +1,473 @@
+{
+ "info": {
+ "_postman_id": "0f8cc0ab-4554-4537-b23f-fa62e80a6302",
+ "name": "prisma-examples-rest",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "users",
+ "item": [
+ {
+ "name": "allUsers",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test('Status code is 200', () => {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201])\r",
+ "})\r",
+ "\r",
+ "pm.test('Response body is valid', function () {\r",
+ " const allUsers = [\r",
+ " {\r",
+ " \"id\": 1,\r",
+ " \"email\": \"alice@prisma.io\",\r",
+ " \"name\": \"Alice\"\r",
+ " },\r",
+ " {\r",
+ " \"id\": 2,\r",
+ " \"email\": \"nilu@prisma.io\",\r",
+ " \"name\": \"Nilu\"\r",
+ " },\r",
+ " {\r",
+ " \"id\": 3,\r",
+ " \"email\": \"mahmoud@prisma.io\",\r",
+ " \"name\": \"Mahmoud\"\r",
+ " }\r",
+ " ]\r",
+ " \r",
+ " const jsonData = pm.response.json()\r",
+ " pm.expect(jsonData).to.eql(allUsers)\r",
+ "})\r",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:3000/users",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3000",
+ "path": [
+ "users"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "getUserDrafts",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test('Status code is 200', () => {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201])\r",
+ "})\r",
+ "\r",
+ "pm.test('Response body is valid', function () {\r",
+ " const jsonData = pm.response.json()\r",
+ " pm.expect(jsonData[0].id).to.eql(4)\r",
+ " pm.expect(jsonData[0].title).to.eql(\"Prisma on YouTube\")\r",
+ " pm.expect(jsonData[0].content).to.eql(\"https://pris.ly/youtube/")\r",
+ " pm.expect(jsonData[0].published).to.eql(false)\r",
+ " pm.expect(jsonData[0].viewCount).to.eql(0)\r",
+ " pm.expect(jsonData[0].authorId).to.eql(3)\r",
+ "})\r",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:3000/user/3/drafts",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3000",
+ "path": [
+ "user",
+ "3",
+ "drafts"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "signup",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test('Status code is 200', () => {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201])\r",
+ "})\r",
+ "\r",
+ "pm.test('Response body is valid', function () {\r",
+ " var jsonData = pm.response.json()\r",
+ " pm.expect(jsonData.id).to.eql(4)\r",
+ " pm.expect(jsonData.name).to.eql(\"Alex\")\r",
+ " pm.expect(jsonData.email).to.eql(\"alex@prisma.io\")\r",
+ "})\r",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n\t\"name\": \"Alex\",\r\n\t\"email\": \"alex@prisma.io\",\r\n\t\"posts\":[\r\n\t\t{\r\n\t\t\t\"title\": \"Prisma and APIs\",\r\n \"content\": \"This works pretty smoothly with any type of API\"\r\n\t\t}\r\n\t]\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:3000/signup",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3000",
+ "path": [
+ "signup"
+ ]
+ }
+ },
+ "response": []
+ }
+ ],
+ "auth": {
+ "type": "noauth"
+ },
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "name": "posts",
+ "item": [
+ {
+ "name": "feed",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test('Status code is 200', () => {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201])\r",
+ "})\r",
+ "\r",
+ "pm.test('Response body is valid', function () {\r",
+ " const jsonData = pm.response.json()\r",
+ " pm.expect(jsonData[0].id).to.eql(1)\r",
+ " pm.expect(jsonData[0].title).to.eql(\"Join the Prisma Discord\")\r",
+ " pm.expect(jsonData[0].content).to.eql(\"https://pris.ly/discord/")\r",
+ " pm.expect(jsonData[0].published).to.eql(true)\r",
+ " pm.expect(jsonData[0].viewCount).to.eql(0)\r",
+ " pm.expect(jsonData[0].authorId).to.eql(1)\r",
+ "})"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:3000/feed?searchString=discord",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3000",
+ "path": [
+ "feed"
+ ],
+ "query": [
+ {
+ "key": "searchString",
+ "value": "discord"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "getPostById",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test('Status code is 200', () => {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201])\r",
+ "})\r",
+ "\r",
+ "pm.test('Response body is valid', function () { \r",
+ " const jsonData = pm.response.json()\r",
+ " pm.expect(jsonData.id).to.eql(3)\r",
+ " pm.expect(jsonData.title).to.eql(\"Ask a question about Prisma on GitHub\")\r",
+ " pm.expect(jsonData.content).to.eql(\"https://www.github.com/prisma/prisma/discussions/")\r",
+ " pm.expect(jsonData.published).to.eql(true)\r",
+ " pm.expect(jsonData.authorId).to.eql(3)\r",
+ "})"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:3000/post/3",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3000",
+ "path": [
+ "post",
+ "3"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "togglePublish",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test('Status code is 200', () => {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201])\r",
+ "})\r",
+ "\r",
+ "pm.test('Response body is valid', function () {\r",
+ " const jsonData = pm.response.json()\r",
+ " pm.expect(jsonData.id).to.eql(4)\r",
+ " pm.expect(jsonData.title).to.eql(\"Prisma on YouTube\")\r",
+ " pm.expect(jsonData.content).to.eql(\"https://pris.ly/youtube/")\r",
+ " pm.expect(jsonData.published).to.eql(true)\r",
+ " pm.expect(jsonData.viewCount).to.eql(0)\r",
+ " pm.expect(jsonData.authorId).to.eql(3)\r",
+ "})\r",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "PUT",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:3000/publish/4",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3000",
+ "path": [
+ "publish",
+ "4"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "incrementPostViewCount",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test('Status code is 200', () => {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201])\r",
+ "})\r",
+ "\r",
+ "pm.test('Response body is valid', function () {\r",
+ " const jsonData = pm.response.json()\r",
+ " pm.expect(jsonData.id).to.eql(4)\r",
+ " pm.expect(jsonData.title).to.eql(\"Prisma on YouTube\")\r",
+ " pm.expect(jsonData.content).to.eql(\"https://pris.ly/youtube/")\r",
+ " pm.expect(jsonData.published).to.eql(true)\r",
+ " pm.expect(jsonData.viewCount).to.eql(1)\r",
+ " pm.expect(jsonData.authorId).to.eql(3)\r",
+ "})\r",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "PUT",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:3000/post/4/views",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3000",
+ "path": [
+ "post",
+ "4",
+ "views"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "createDraft",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test('Status code is 200', () => {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201])\r",
+ "})\r",
+ "\r",
+ "pm.test('Response body is valid', function () {\r",
+ " const jsonData = pm.response.json()\r",
+ " pm.expect(jsonData.id).to.eql(6)\r",
+ " pm.expect(jsonData.title).to.eql(\"Postman and Newman - Testing APIs\")\r",
+ " pm.expect(jsonData.content).to.eql(null)\r",
+ " pm.expect(jsonData.published).to.eql(false)\r",
+ " pm.expect(jsonData.viewCount).to.eql(0)\r",
+ " pm.expect(jsonData.authorId).to.eql(2)\r",
+ "})\r",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n\t\"title\":\"Postman and Newman - Testing APIs\",\r\n\t\"authorEmail\":\"nilu@prisma.io\"\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:3000/post",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3000",
+ "path": [
+ "post"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "deletePost",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test('Status code is 200', () => {\r",
+ " pm.expect(pm.response.code).to.be.oneOf([200,201])\r",
+ "})\r",
+ "\r",
+ "pm.test('Response body is valid', function () {\r",
+ " const jsonData = pm.response.json()\r",
+ " pm.expect(jsonData.id).to.eql(6)\r",
+ " pm.expect(jsonData.title).to.eql(\"Postman and Newman - Testing APIs\")\r",
+ " pm.expect(jsonData.content).to.eql(null)\r",
+ " pm.expect(jsonData.published).to.eql(false)\r",
+ " pm.expect(jsonData.viewCount).to.eql(0)\r",
+ " pm.expect(jsonData.authorId).to.eql(2)\r",
+ "})\r",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "DELETE",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:3000/post/6",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "3000",
+ "path": [
+ "post",
+ "6"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+ }
+ ],
+ "variable": [
+ {
+ "key": "allUsers",
+ "value": "const users = [\r\n {\r\n \"id\": 1,\r\n \"email\": \"alice@prisma.io\",\r\n \"name\": \"Alice\"\r\n },\r\n {\r\n \"id\": 2,\r\n \"email\": \"nilu@prisma.io\",\r\n \"name\": \"Nilu\"\r\n },\r\n {\r\n \"id\": 3,\r\n \"email\": \"mahmoud@prisma.io\",\r\n \"name\": \"Mahmoud\"\r\n },\r\n {\r\n \"id\": 4,\r\n \"email\": \"alex@prisma.io\",\r\n \"name\": \"Alex\"\r\n }\r\n]"
+ }
+ ]
+}
diff --git a/.github/tests/yarn.lock b/.github/tests/yarn.lock
deleted file mode 100644
index 9daa4a00d2c7..000000000000
--- a/.github/tests/yarn.lock
+++ /dev/null
@@ -1,390 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"@types/mkdirp@^0.5.2":
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f"
- dependencies:
- "@types/node" "*"
-
-"@types/node@*":
- version "10.12.9"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.9.tgz#a07bfa74331471e1dc22a47eb72026843f7b95c8"
-
-"@types/yargs@^12.0.1":
- version "12.0.1"
- resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.1.tgz#c5ce4ad64499010ae4dc2acd9b14d49749a44233"
-
-ansi-regex@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
-
-ansi-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
-
-balanced-match@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
-
-brace-expansion@^1.1.7:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-camelcase@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42"
-
-cliui@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
- dependencies:
- string-width "^2.1.1"
- strip-ansi "^4.0.0"
- wrap-ansi "^2.0.0"
-
-code-point-at@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
-
-concat-map@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
-
-cross-spawn@^5.0.1:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
- dependencies:
- lru-cache "^4.0.1"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-cross-spawn@^6.0.0:
- version "6.0.5"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
- dependencies:
- nice-try "^1.0.4"
- path-key "^2.0.1"
- semver "^5.5.0"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-decamelize@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
-
-execa@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
- dependencies:
- cross-spawn "^6.0.0"
- get-stream "^3.0.0"
- is-stream "^1.1.0"
- npm-run-path "^2.0.0"
- p-finally "^1.0.0"
- signal-exit "^3.0.0"
- strip-eof "^1.0.0"
-
-execa@^0.6.0:
- version "0.6.3"
- resolved "https://registry.yarnpkg.com/execa/-/execa-0.6.3.tgz#57b69a594f081759c69e5370f0d17b9cb11658fe"
- dependencies:
- cross-spawn "^5.0.1"
- get-stream "^3.0.0"
- is-stream "^1.1.0"
- npm-run-path "^2.0.0"
- p-finally "^1.0.0"
- signal-exit "^3.0.0"
- strip-eof "^1.0.0"
-
-find-up@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
- dependencies:
- locate-path "^3.0.0"
-
-get-caller-file@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
-
-get-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
-
-inline-markdown@0.1.6:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/inline-markdown/-/inline-markdown-0.1.6.tgz#5ba1284c85058f586773313561c05b66afd0bbf8"
- dependencies:
- "@types/mkdirp" "^0.5.2"
- "@types/yargs" "^12.0.1"
- mkdirp "^0.5.1"
- recursive-readdir "^2.2.2"
- yargs "^12.0.5"
-
-invert-kv@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
-
-is-fullwidth-code-point@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
- dependencies:
- number-is-nan "^1.0.0"
-
-is-fullwidth-code-point@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
-
-is-stream@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
-
-isexe@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
-
-lcid@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
- dependencies:
- invert-kv "^2.0.0"
-
-locate-path@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
- dependencies:
- p-locate "^3.0.0"
- path-exists "^3.0.0"
-
-lru-cache@^4.0.1:
- version "4.1.4"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.4.tgz#51cc46e8e6d9530771c857e24ccc720ecdbcc031"
- dependencies:
- pseudomap "^1.0.2"
- yallist "^3.0.2"
-
-map-age-cleaner@^0.1.1:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
- dependencies:
- p-defer "^1.0.0"
-
-mem@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf"
- dependencies:
- map-age-cleaner "^0.1.1"
- mimic-fn "^1.0.0"
- p-is-promise "^1.1.0"
-
-mimic-fn@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
-
-minimatch@3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
- dependencies:
- brace-expansion "^1.1.7"
-
-minimist@0.0.8:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
-
-mkdirp@^0.5.1:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
- dependencies:
- minimist "0.0.8"
-
-nice-try@^1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
-
-npm-run-path@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
- dependencies:
- path-key "^2.0.0"
-
-number-is-nan@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
-
-os-locale@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620"
- dependencies:
- execa "^0.10.0"
- lcid "^2.0.0"
- mem "^4.0.0"
-
-p-defer@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
-
-p-finally@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
-
-p-is-promise@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
-
-p-limit@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec"
- dependencies:
- p-try "^2.0.0"
-
-p-locate@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
- dependencies:
- p-limit "^2.0.0"
-
-p-try@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1"
-
-path-exists@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
-
-path-key@^2.0.0, path-key@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
-
-prettier-check@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/prettier-check/-/prettier-check-2.0.0.tgz#edd086ee12d270579233ccb136a16e6afcfba1ae"
- dependencies:
- execa "^0.6.0"
-
-prettier@1.16.4:
- version "1.16.4"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.4.tgz#73e37e73e018ad2db9c76742e2647e21790c9717"
-
-pseudomap@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
-
-recursive-readdir@^2.2.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f"
- dependencies:
- minimatch "3.0.4"
-
-require-directory@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
-
-require-main-filename@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
-
-semver@^5.5.0:
- version "5.6.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
-
-set-blocking@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
-
-shebang-command@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
- dependencies:
- shebang-regex "^1.0.0"
-
-shebang-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
-
-signal-exit@^3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
-
-string-width@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
- dependencies:
- code-point-at "^1.0.0"
- is-fullwidth-code-point "^1.0.0"
- strip-ansi "^3.0.0"
-
-string-width@^2.0.0, string-width@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
- dependencies:
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^4.0.0"
-
-strip-ansi@^3.0.0, strip-ansi@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
- dependencies:
- ansi-regex "^2.0.0"
-
-strip-ansi@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
- dependencies:
- ansi-regex "^3.0.0"
-
-strip-eof@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
-
-which-module@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
-
-which@^1.2.9:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
- dependencies:
- isexe "^2.0.0"
-
-wrap-ansi@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
- dependencies:
- string-width "^1.0.1"
- strip-ansi "^3.0.1"
-
-"y18n@^3.2.1 || ^4.0.0":
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
-
-yallist@^3.0.2:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
-
-yargs-parser@^11.1.1:
- version "11.1.1"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
- dependencies:
- camelcase "^5.0.0"
- decamelize "^1.2.0"
-
-yargs@^12.0.5:
- version "12.0.5"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
- dependencies:
- cliui "^4.0.0"
- decamelize "^1.2.0"
- find-up "^3.0.0"
- get-caller-file "^1.0.1"
- os-locale "^3.0.0"
- require-directory "^2.1.1"
- require-main-filename "^1.0.1"
- set-blocking "^2.0.0"
- string-width "^2.0.0"
- which-module "^2.0.0"
- y18n "^3.2.1 || ^4.0.0"
- yargs-parser "^11.1.1"
diff --git a/.github/tests/.prettierrc b/.github/tools/.prettierrc
similarity index 100%
rename from .github/tests/.prettierrc
rename to .github/tools/.prettierrc
diff --git a/.github/tools/package.json b/.github/tools/package.json
new file mode 100644
index 000000000000..89a16b0d4589
--- /dev/null
+++ b/.github/tools/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "prisma-client-examples",
+ "version": "1.0.0",
+ "repository": "git@github.com:prisma/prisma-client-js.git",
+ "license": "MIT",
+ "scripts": {
+ "test": "yarn prettier-check",
+ "prettier-check": "prettier-check --config .prettierrc \"../../orm/*/{src,test,prisma}/**/*.{ts,tsx}\"",
+ "prettier-fix": "prettier --config .prettierrc --write \"../../orm/*/{src,test,prisma}/**/*.{ts,tsx}\""
+ },
+ "devDependencies": {
+ "inline-markdown": "0.1.6",
+ "prettier": "3.6.2",
+ "prettier-check": "2.0.0",
+ "watch": "1.0.2"
+ }
+}
diff --git a/.github/workflows/test-cockroachdb.yaml b/.github/workflows/test-cockroachdb.yaml
new file mode 100644
index 000000000000..30cc181255b2
--- /dev/null
+++ b/.github/workflows/test-cockroachdb.yaml
@@ -0,0 +1,43 @@
+name: test-cockroachdb
+on:
+ push:
+ paths:
+ - databases/cockroachdb/**
+ branches:
+ - latest
+ - dev
+ - patch-dev
+ pull_request:
+ paths:
+ - databases/cockroachdb/**
+
+env:
+ CI: 1
+ PRISMA_TELEMETRY_INFORMATION: 'prisma-examples test-cockroachdb.yaml'
+
+jobs:
+ test:
+ defaults:
+ run:
+ working-directory: databases/cockroachdb
+ runs-on: ubuntu-latest
+
+ env:
+ DATABASE_URL: postgresql://root@127.0.0.1:26257/prisma?sslmode=disable
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Start a single CockroachDB instance with Docker
+ env:
+ COCKROACHDB_DOCKER_TAG: 'cockroachdb/cockroach:latest-v21.2'
+ run: |
+ docker pull $COCKROACHDB_DOCKER_TAG
+ docker run -d --name roach --hostname roach -p 26257:26257 -p 8080:8080 -v "${{ github.workspace }}:/app" $COCKROACHDB_DOCKER_TAG start-single-node --insecure
+ sudo apt update && sudo apt install wait-for-it -y
+ wait-for-it -h localhost -p 26257
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '22.16.0'
+ - run: npm install
+ - run: npx prisma migrate dev --name "init"
+ - run: npm run test
diff --git a/.github/workflows/test-mongodb.yaml b/.github/workflows/test-mongodb.yaml
new file mode 100644
index 000000000000..9511b2028c6f
--- /dev/null
+++ b/.github/workflows/test-mongodb.yaml
@@ -0,0 +1,46 @@
+name: test-mongodb
+on:
+ push:
+ paths:
+ - databases/mongodb/**
+ branches:
+ - latest
+ - dev
+ - patch-dev
+ pull_request:
+ paths:
+ - databases/mongodb/**
+
+env:
+ CI: 1
+ PRISMA_TELEMETRY_INFORMATION: 'prisma-examples test-mongodb.yaml'
+
+jobs:
+ test:
+ defaults:
+ run:
+ working-directory: databases/mongodb
+ runs-on: ubuntu-latest
+ # Service containers to run with `container-job`
+ services:
+ # Label used to access the service container
+ mongodb:
+ # Docker Hub image
+ image: prismagraphql/mongo-single-replica:4.4.3-bionic
+ env:
+ MONGO_INITDB_ROOT_USERNAME: root
+ MONGO_INITDB_ROOT_PASSWORD: prisma
+ ports:
+ - 27017:27017
+
+ env:
+ DATABASE_URL: mongodb://root:prisma@localhost:27017/prisma-mongo?authSource=admin&retryWrites=true&w=majority
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '22.16.0'
+ - run: npm install
+ - run: npx prisma generate
+ - run: npm run test
diff --git a/.github/workflows/test-sql-server.yaml b/.github/workflows/test-sql-server.yaml
new file mode 100644
index 000000000000..e0348e174388
--- /dev/null
+++ b/.github/workflows/test-sql-server.yaml
@@ -0,0 +1,48 @@
+name: test-sql-server
+on:
+ push:
+ paths:
+ - databases/sql-server/**
+ branches:
+ - latest
+ - dev
+ - patch-dev
+ pull_request:
+ paths:
+ - databases/sql-server/**
+
+env:
+ CI: 1
+ PRISMA_TELEMETRY_INFORMATION: 'prisma-examples test-sql-server.yaml'
+
+jobs:
+ test:
+ defaults:
+ run:
+ working-directory: databases/sql-server
+ runs-on: ubuntu-latest
+ # Service containers to run with `container-job`
+ services:
+ # Label used to access the service container
+ sql-server:
+ # Docker Hub image
+ image: mcr.microsoft.com/mssql/server:2025-latest
+ env:
+ ACCEPT_EULA: Y
+ SA_PASSWORD: 'Pr1sm4_Pr1sm4'
+ # Maps tcp port 1433 on service container to the host
+ ports:
+ - '1433:1433'
+ options: --health-cmd="/opt/mssql-tools18/bin/sqlcmd -C -S localhost -U SA -P ${SA_PASSWORD} -Q 'SELECT 1' || exit 1" --health-interval 10s --health-timeout 5s --health-retries 5
+
+ env:
+ DATABASE_URL: sqlserver://localhost:1433;database=prisma-demo;user=SA;password=Pr1sm4_Pr1sm4;trustServerCertificate=true;encrypt=true
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '22.16.0'
+ - run: npm install
+ - run: npx prisma migrate dev --name "init"
+ - run: npm run test
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
new file mode 100644
index 000000000000..3e08dca62729
--- /dev/null
+++ b/.github/workflows/test.yaml
@@ -0,0 +1,75 @@
+name: test
+on:
+ push:
+ paths:
+ - orm/**
+ branches:
+ - latest
+ pull_request:
+
+env:
+ CI: 1
+ PRISMA_TELEMETRY_INFORMATION: 'prisma-examples test.yaml'
+ SLACK_WEBHOOK_URL_FAILING: ${{ secrets.SLACK_WEBHOOK_URL_FAILING }}
+ SKIP_PRISMA_VERSION_CHECK: true # Skip Prisma version check in typegraphl-prisma (https://github.com/MichalLytek/typegraphql-prisma/blob/fc7cfa756a60dd6671a902c38f00ee74698a681a/Readme.md#lifting-prisma-version-restriction)
+
+jobs:
+ projects-matrix:
+ if: github.repository_owner == 'prisma'
+ runs-on: ubuntu-latest
+ outputs:
+ matrix: ${{ steps.set-matrix.outputs.matrix }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '22.16.0'
+
+ - name: install deps
+ run: cd .github/scripts && yarn install
+
+ - name: get list of projects as json array
+ id: set-matrix
+ run: node .github/scripts/get-packages.js
+ test-prisma-postgres:
+ if: github.repository_owner == 'prisma'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Run prisma-postgres test
+ working-directory: .github/tests/databases/prisma-postgres
+ run: |
+ chmod +x run.sh
+ ./run.sh
+ test:
+ needs: projects-matrix
+ if: github.repository_owner == 'prisma'
+ runs-on: ubuntu-latest
+ env:
+ PPG_TEST_DATABASE_URL: ${{ secrets.PPG_TEST_DATABASE_URL }}
+ strategy:
+ fail-fast: false
+ matrix: ${{fromJson(needs.projects-matrix.outputs.matrix)}}
+ services:
+ postgres:
+ image: postgis/postgis:14-3.1-alpine
+ env:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: password
+ POSTGRES_DB: testing
+ # Set health checks to wait until postgres has started
+ options: >-
+ --health-cmd pg_isready
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ ports:
+ - '5432:5432'
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '22.16.0'
+
+ - name: test
+ run: bash .github/scripts/test-all.sh ./${{ matrix.path }}/package.json
diff --git a/.gitignore b/.gitignore
index 3a976e4e7310..7ce1e5f6c84d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,32 @@
-node_modules
-yarn-error.log
-vendor
-tmp
-dist
+# This gitignore file is used only internally for this repository,
+# you should not use this in your own projects. Instead, navigate into
+# an example folder and use the folder as the project root (it also contains a
+# projects-specific .gitignore).
+
+node_modules/
+generated/
+yarn-error.log/
+vendor/
+tmp/
+dist/
.DS_Store
.idea
tmp-resolvers
package-lock.json
flow-typed
-yarn.lock
\ No newline at end of file
+yarn.lock
+orm/**/migrations/
+misc/**/migrations/
+databases/**/migrations/
+orm/**/package-lock.json
+misc/**/package-lock.json
+experimental/**/package-lock.json
+
+databases/**/package-lock.json
+experimental/**/*.db
+.next
+.vscode/
+.nuxt
+dev.db
+*.env*
+!.env.example
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 000000000000..a77793ecc520
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+lts/hydrogen
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000000..9250d263397a
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,2 @@
+*.mdx
+*.md
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 000000000000..e3b414c7e090
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "all"
+}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 000000000000..526474604dde
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,5 @@
+{
+ "recommendations": [
+ "Prisma.prisma",
+ ]
+}
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2c6bbafca51b..749d850b75cc 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,5 +1,9 @@
# Contribution Guidelines
+## Commit messages
+
+Please use [conventional commits](https://www.conventionalcommits.org) (also known as _semantic commits_) to ensure consistent and descriptive commit messages when submitting PRs.
+
## General guidelines
Every example should follow a number of guidelines.
@@ -9,7 +13,6 @@ Every example should follow a number of guidelines.
- Simple and minimal instead of complex and production-ready
- Focus on one specific Prisma use case
- Easily extensible
-- Require global installation of the Prisma CLI but all other dependencies (e.g. `graphqlgen`) only as dev dependencies and invoked via a script (e.g. `npm run graphqlgen`)
### README guidelines
@@ -27,8 +30,8 @@ For each language, there should be one example that shows how to:
- build a **REST API** with Prisma client
- build a **CLI** application with Prisma client
-The datamodel and developed APIs should be consistent across languages. This enables easier testing of the examples. The domain for all applications (except the CLI app) is a simple blogging application.
-
+The schemas and developed APIs should be consistent across languages. This enables easier testing of the examples. The domain for all applications (except the CLI app) is a simple blogging application.
+
## Ways to contribute
@@ -323,23 +326,12 @@ The easiest way to contribute is by adding a missing example. Check [this](https
### Adding a new example
-Before submitting a PR for a new example, please first open an issue that explains the idea of the example and specifies what it will look like (e.g. how the Prisma datamodel will be defined or what kind of API will be built). It'll then be discussed in the issue whether your example is going to be added to the collection. To accelerate the process, you can ping @nikolasburk in the public [Prisma Slack](https://slack.prisma.io).
+Before submitting a PR for a new example, please first open an issue that explains the idea of the example and specifies what it will look like (e.g. how the Prisma datamodel will be defined or what kind of API will be built). It'll then be discussed in the issue whether your example is going to be added to the collection. To accelerate the process, you can ping @nikolasburk in the public [Prisma Discord](https://pris.ly/discord).
-Once approved, you can add your example to [list of missing examples](https://github.com/prisma/prisma-examples/issues/311) and start implementing it.
+Once approved, you can add your example to [list of missing examples](https://github.com/prisma/prisma-examples/issues/311) and start implementing it.
### Improving an existing example
-If you find a bug in an example, please feel free to open an issue or submit a PR so the bug gets fixed. If you want to make structural changes to an existing example (e.g. changing the datamodel or the API operations), please open an issue about this first where the changes can be discussed. To accelerate the process, you can ping @nikolasburk in the public [Prisma Slack](https://slack.prisma.io).
+If you find a bug in an example, please feel free to open an issue or submit a PR so the bug gets fixed. If you want to make structural changes to an existing example (e.g. changing the datamodel or the API operations), please open an issue about this first where the changes can be discussed. To accelerate the process, you can ping @nikolasburk in the public [Prisma Discord](https://pris.ly/discord).
Once approved, you can go ahead and implement the changes.
-
-### Improving a README
-
-The READMEs for all projects are being auto-generated based on the templates located in [`./github/readmes`](./github/readmes). If you find a typo or other parts of the README that should be improved, please do not edit the README directly but instead add your changes to the corresponding template.
-
-For example, if you found an issue in the `node/graphql` README, do not edit the [`./node/graphql/README.md`](./node/graphql/README.md) file but instead add your changes to [.`/.github/readmes/node/graphql/README.md`](./.github/readmes/node/graphql/README.md). Then build the READMEs using our custom script:
-
-```
-cd .github/tests
-yarn build-readmes
-```
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000000..261eeb9e9f8b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
index 78cc24453c57..a8e70c2bcc4d 100644
--- a/README.md
+++ b/README.md
@@ -1,68 +1,179 @@
-# Prisma Examples [](https://circleci.com/gh/prisma/prisma-examples)
+
-This repository contains a number of ready-to-run examples demonstrating various use cases of [Prisma](https://www.prisma.io). Pick an example and follow the instructions in the corresponding README.
+
+
+
+
+
+
+[](https://github.com/prisma/prisma-examples/actions?query=workflow%3Atest+branch%3Alatest)
+
+[View full CI status](#ci-status)
+
+
+
+
+
+This repository contains a number of ready-to-run example projects demonstrating various use cases of Prisma. Pick an example and follow the instructions in the corresponding README.
+
+You can also find links to [real-world and production ready examples](#real-world--production-ready-example-projects-with-prisma) further below in this README.
Are you missing an example? Please feel free to [open an issue](https://github.com/prisma/prisma-examples/issues/new) (read the [contribution guidelines](./CONTRIBUTING.md) for more info).
-## TypeScript
-
-| Demo | Description |
-|:------|:----------|
-| [`script`](https://github.com/prisma/prisma-examples/tree/master/typescript/script) | Simple usage of Prisma client in script |
-| [`graphql`](https://github.com/prisma/prisma-examples/tree/master/typescript/graphql) | Simple GraphQL server |
-| [`graphql-crud`](https://github.com/prisma/prisma-examples/tree/master/typescript/graphql-crud) | GraphQL server with full CRUD API |
-| [`graphql-auth`](https://github.com/prisma/prisma-examples/tree/master/typescript/graphql-auth) | GraphQL server with email-password authentication & permissions |
-| [`graphql-subscriptions`](https://github.com/prisma/prisma-examples/tree/master/typescript/graphql-subscriptions) | GraphQL server with realtime subscriptions |
-| [`rest-express`](https://github.com/prisma/prisma-examples/tree/master/typescript/rest-express) | Simple REST API with Express.JS |
-| [`grpc`](https://github.com/prisma/prisma-examples/tree/master/typescript/grpc) | Simple gRPC API |
-| [`docker-mongodb`](https://github.com/prisma/prisma-examples/tree/master/typescript/docker-mongodb) | Set up Prisma locally with MongoDB |
-| [`docker-mysql`](https://github.com/prisma/prisma-examples/tree/master/typescript/docker-mysql) | Set up Prisma locally with MySQL |
-| [`docker-postgres`](https://github.com/prisma/prisma-examples/tree/master/typescript/docker-postgres) | Set up Prisma locally with PostgreSQL |
-| [`cli-app`](https://github.com/prisma/prisma-examples/tree/master/typescript/cli-app) | Simple CLI TODO list app |
-
-## Node.js
-
-| Demo | Description |
-|:------|:----------|
-| [`script`](https://github.com/prisma/prisma-examples/tree/master/node/script) | Simple usage of Prisma client in script |
-| [`graphql`](https://github.com/prisma/prisma-examples/tree/master/node/graphql) | Simple GraphQL server |
-| [`graphql-auth`](https://github.com/prisma/prisma-examples/tree/master/node/graphql-auth) | GraphQL server with email-password authentication & permissions |
-| [`graphql-subscriptions`](https://github.com/prisma/prisma-examples/tree/master/node/graphql-subscriptions) | GraphQL server with realtime subscriptions |
-| [`rest-express`](https://github.com/prisma/prisma-examples/tree/master/node/rest-express) | Simple REST API with Express.JS |
-| [`grpc`](https://github.com/prisma/prisma-examples/tree/master/node/grpc) | Simple gRPC API |
-| [`docker-mongodb`](https://github.com/prisma/prisma-examples/tree/master/node/docker-mongodb) | Set up Prisma locally with MongoDB |
-| [`docker-mysql`](https://github.com/prisma/prisma-examples/tree/master/node/docker-mysql) | Set up Prisma locally with MySQL |
-| [`docker-postgres`](https://github.com/prisma/prisma-examples/tree/master/node/docker-postgres) | Set up Prisma locally with PostgreSQL |
-| [`cli-app`](https://github.com/prisma/prisma-examples/tree/master/node/cli-app) | Simple CLI TODO list app |
-
-
-## Golang
-
-| Demo | Description |
-|:------|:----------|
-| [`script`](https://github.com/prisma/prisma-examples/tree/master/go/script) | Simple usage of Prisma client in script |
-| [`graphql`](https://github.com/prisma/prisma-examples/tree/master/go/graphql) | Simple GraphQL server |
-| [`rest-gin`](https://github.com/prisma/prisma-examples/tree/master/go/rest-gin) | Simple REST API with [Gin](https://github.com/gin-gonic/gin) |
-| [`http-mux`](https://github.com/prisma/prisma-examples/tree/master/go/http-mux) | Simple REST API with [gorilla/mux](https://github.com/gorilla/mux) |
-| [`docker-mongodb`](https://github.com/prisma/prisma-examples/tree/master/go/docker-mongodb) | Set up Prisma locally with MongoDB |
-| [`docker-mysql`](https://github.com/prisma/prisma-examples/tree/master/go/docker-mysql) | Set up Prisma locally with MySQL |
-| [`docker-postgres`](https://github.com/prisma/prisma-examples/tree/master/go/docker-postgres) | Set up Prisma locally with PostgreSQL |
-| [`cli-app`](https://github.com/prisma/prisma-examples/tree/master/go/cli-app) | Simple CLI TODO list app |
-
-## Flow
-
-| Demo | Description |
-|:------|:----------|
-| [`script`](https://github.com/prisma/prisma-examples/tree/master/flow/script) | Simple usage of Prisma client in script |
-| [`graphql`](https://github.com/prisma/prisma-examples/tree/master/flow/graphql) | Simple GraphQL server |
-
-
-## Reference Implementations
-
-If you're looking for a more complex real-world application you can check out the following repositories:
-
-| Repo | Language | Description |
-|:-----|:--------:|:-------------|
-| [`graphql-prisma-typescript`](https://github.com/prisma/graphql-prisma-typescript) | [TypeScript](https://www.typescriptlang.org/) | TypeScript-based GraphQL server (Airbnb clone) |
+## Prisma ORM
+
+### Fullstack
+
+| Demo | Description |
+| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| [`nextjs-api-routes`](https://github.com/prisma/prisma-examples/tree/latest/orm/nextjs-api-routes) | [Next.js](https://nextjs.org/) app with a REST API (using [Next.js API routes](https://nextjs.org/docs/api-routes/introduction)) |
+| [`nextjs-graphql`](https://github.com/prisma/prisma-examples/tree/latest/orm/nextjs-graphql) | [Next.js](https://nextjs.org/) app with a GraphQL API (using [Apollo Server](https://github.com/apollographql/apollo-server) and [GraphQL Nexus](https://github.com/graphql-nexus/nexus)) |
+| [`nextjs-trpc`](https://github.com/prisma/prisma-examples/tree/latest/orm/nextjs-trpc) | [Next.js](https://nextjs.org/) app with [tRPC ](https://trpc.io/) |
+| [`nuxt`](https://github.com/prisma/prisma-examples/tree/latest/orm/nuxt) | [Nuxt.js](https://nuxt.com/) app with a REST API |
+| [`sveltekit`](https://github.com/prisma/prisma-examples/tree/latest/orm/sveltekit) | [SvelteKit](https://kit.svelte.dev/) app using SvelteKit's [actions](https://kit.svelte.dev/docs/form-actions) and [load](https://kit.svelte.dev/docs/form-actions#loading-data) functions |
+| [`remix`](https://github.com/prisma/prisma-examples/tree/latest/orm/remix) | [Remix](https://remix.run/) app |
+| [`nuxt-prisma-module`](https://github.com/prisma/prisma-examples/tree/latest/orm/nuxt-prisma-module) | A nuxt example app using the [Prisma Nuxt module](https://github.com/prisma/nuxt-prisma) |
+
+### Backend only
+
+| Demo | Description |
+| :----------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| [`graphql-auth`](https://github.com/prisma/prisma-examples/tree/latest/orm/graphql-auth) | GraphQL server with email-password authentication & permissions |
+| [`graphql-sdl-first`](https://github.com/prisma/prisma-examples/tree/latest/orm/graphql-sdl-first) | GraphQL server based on [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server) |
+| [`graphql-subscriptions`](https://github.com/prisma/prisma-examples/tree/latest/orm/graphql-subscriptions) | GraphQL server with realtime subscriptions based on [`apollo-server`](https://www.apollographql.com/docs/apollo-server/) and [Nexus Schema](https://github.com/graphql-nexus/schema) |
+| [`graphql-typegraphql`](https://github.com/prisma/prisma-examples/tree/latest/orm/graphql-typegraphql) | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) and [TypeGraphQL](https://github.com/MichalLytek/type-graphql) |
+| [`graphql-typegraphql-crud`](https://github.com/prisma/prisma-examples/tree/latest/orm/graphql-typegraphql-crud) | CRUD GraphQL API based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) and [TypeGraphQL](https://github.com/MichalLytek/type-graphql) |
+| [`fastify-graphql`](https://github.com/prisma/prisma-examples/tree/latest/orm/fastify-graphql) | GraphQL server based on [Fastify](https://fastify.io/), [Mercurius](https://mercurius.dev/), and the SDL-first approach of [`graphql-tools`](https://www.graphql-tools.com/docs/generate-schema/) |
+| [`fastify-graphql-sdl-first`](https://github.com/prisma/prisma-examples/tree/latest/orm/fastify-graphql-sdl-first) | GraphQL server based on [Fastify](https://fastify.io/), [Mercurius](https://mercurius.dev/), and the SDL-first approach of [`graphql-tools`](https://www.graphql-tools.com/docs/generate-schema/) |
+| [`hapi-graphql`](https://github.com/prisma/prisma-examples/tree/latest/orm/hapi-graphql) | GraphQL server based on [Hapi](https://hapi.dev/) and [Nexus Schema](https://github.com/graphql-nexus/schema) |
+| [`hapi-graphql-sdl-first`](https://github.com/prisma/prisma-examples/tree/latest/orm/hapi-graphql-sdl-first) | GraphQL server based on [Hapi](https://hapi.dev/) and the SDL-first approach of [Apollo Server Integration for Hapi](https://www.npmjs.com/package/@as-integrations/hapi) |
+| [`nest-graphql`](https://github.com/prisma/prisma-examples/tree/latest/orm/nest-graphql) | GraphQL server based on [NestJS](https://nestjs.com/) (code-first) |
+| [`nest-graphql-sdl-first`](https://github.com/prisma/prisma-examples/tree/latest/orm/nest-graphql-sdl-first) | GraphQL server based on [NestJS](https://nestjs.com/) and the SDL-first approach of [`graphql-tools`](https://www.apollographql.com/docs/graphql-tools/) |
+| [`graphql`](https://github.com/prisma/prisma-examples/tree/latest/orm/graphql) | GraphQL server based on [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server) and [Pothos](https://pothos-graphql.dev/) |
+| [`graphql-nexus`](https://github.com/prisma/prisma-examples/tree/latest/orm/graphql-nexus) | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) and [Nexus Schema](https://github.com/graphql-nexus/schema) |
+| [`grpc`](https://github.com/prisma/prisma-examples/tree/latest/orm/grpc) | gRPC API including runnable client scripts for testing |
+| [`postgis-express`](https://github.com/prisma/prisma-examples/tree/latest/orm/postgis-express) | Demo of spatial queries using [Postgis](http://postgis.net/) and [Express](https://expressjs.com/) |
+| [`express`](https://github.com/prisma/prisma-examples/tree/latest/orm/express) | REST API with [Express](https://expressjs.com/) |
+| [`fastify`](https://github.com/prisma/prisma-examples/tree/latest/orm/fastify) | REST API with [Fastify](https://www.fastify.io/) |
+| [`koa`](https://github.com/prisma/prisma-examples/tree/latest/orm/koa) | REST API with [Koa](https://koajs.com/) |
+| [`hapi`](https://github.com/prisma/prisma-examples/tree/latest/orm/hapi) | REST API with [hapi](https://hapi.dev/) |
+| [`nest`](https://github.com/prisma/prisma-examples/tree/latest/orm/nest) | REST API with [NestJS](https://docs.nestjs.com/) |
+| [`script`](https://github.com/prisma/prisma-examples/tree/latest/orm/script) | Usage of Prisma Client JS in a TypeScript script |
+| [`testing-express`](https://github.com/prisma/prisma-examples/tree/latest/orm/testing-express) | Demo of integration tests with [Jest](https://jestjs.io/), [Supertest](https://github.com/visionmedia/supertest) and [Express](https://expressjs.com/) |
+
+### New `prisma-client` generator
+
+The following examples are fullstack examples using the new [`prisma-client`](https://www.prisma.io/docs/orm/prisma-schema/overview/generators#prisma-client-early-access) generator:
+| Demo | Description |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
+| [`nextjs-starter-webpack`](https://github.com/prisma/prisma-examples/tree/latest/generator-prisma-client/nextjs-starter-webpack) | A Next.js 15 starter that uses Webpack 5 as the bundler and runs on Node.js. |
+| [`nextjs-starter-turbopack`](https://github.com/prisma/prisma-examples/tree/latest/generator-prisma-client/nextjs-starter-turbopack) | A Next.js 15 starter powered by Turbopack (alpha) for bundling, running on Node.js. |
+| [`neextjs-starter-webpack-monorepo`](https://github.com/prisma/prisma-examples/tree/latest/generator-prisma-client/neextjs-starter-webpack-monorepo) | A monorepo-based Next.js 15 starter using Webpack 5 and Node.js, managed with `pnpm`. |
+| [`nextjs-starter-webpack-with-middleware`](https://github.com/prisma/prisma-examples/tree/latest/generator-prisma-client/nextjs-starter-webpack-with-middleware) | A Next.js 15 starter with Webpack 5, running on Node.js for main pages and Vercel Edge Light for middleware. |
+
+
+## Prisma Accelerate
+
+The [`accelerate`](./accelerate) folder contains examples of projects using [Prisma Accelerate](https://www.prisma.io/data-platform/accelerate) for connection pooling and global caching.
+
+| Demo | Description |
+| -------------------------------------------------------- | --------------------------------------------------------------------------------- |
+| [`starter`](./accelerate/starter) | A simple starter project using Prisma Accelerate's caching and connection pooling |
+| [`nextjs-starter`](./accelerate/nextjs-starter) | A Next.js project using Prisma Accelerate's caching and connection pooling |
+| [`svelte-starter`](./accelerate/svelte-starter/) | A SvelteKit project using Prisma Accelerate's caching and connection pooling |
+| [`solidstart-starter`](./accelerate/solidstart-starter/) | A Solidstart project using Prisma Accelerate's caching and connection pooling |
+| [`remix-starter`](./accelerate/remix-starter/) | A Remix project using Prisma Accelerate's caching and connection pooling |
+| [`nuxt-starter`](./accelerate/nuxtjs-starter/) | A Nuxt.js project using Prisma Accelerate's caching and connection pooling |
+| [`astro-starter`](./accelerate/astro-starter/) | An Astro project using Prisma Accelerate's caching and connection pooling |
+
+## Prisma Optimize
+
+The [`optimize`](./optimize) folder contains examples of projects using [Prisma Optimize](https://www.prisma.io/data-platform/optimize) to identify and improve the performance of slow queries.
+| Demo | Description |
+| ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
+| [`starter`](./optimize/starter) | A Prisma Optimize starter app |
+| [`optimize-excessive-rows`](./optimize/optimize-excessive-rows) | An example app demonstrating the "Excessive number of rows returned" recommendation provided by Optimize. |
+| [`optimize-full-table-scan`](./optimize/optimize-full-table-scan) | An example app demonstrating the "Full table scans caused by `LIKE` operations" recommendation provided by Optimize. |
+| [`optimize-unindexed-column`](./optimize/optimize-unindexed-column) | An example app demonstrating the "Query filtering on an unindexed column" recommendation provided by Optimize. |
+
+## Deployment platforms
+
+The projects in the [`deployment-platforms`](./deployment-platforms) directory show what "Prisma Client"-based deployment setups look like for various deployment providers. Learn more about [deployment](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/deployment) in the Prisma documentation.
+
+## Real-world & production-ready example projects with Prisma
+
+- [Inbox Zero](https://github.com/elie222/inbox-zero): Open source email management tools to reach inbox zero fast
+- [NextCRM](https://github.com/pdovhomilja/nextcrm-app): An open-source Customer Relationship Management system (CRM)
+- [Papermark](https://github.com/mfts/papermark/): An open-source DocSend alternative with built-in analytics and custom domains
+- [Hoppscotch](https://github.com/hoppscotch/hoppscotch): An open-source API development ecosystem
+- [FeastQR](https://github.com/jakubczarnowski/FeastQR): An open-source SaaS online menu system for restaurants
+- [Formbricks](https://github.com/formbricks/formbricks): An open-source survey and experience management tool
+- [OpenformStack](https://github.com/naveennaidu/OpenformStack): An open-source form backend that allows you to collect form submissions without writing any backend code
+- [Documenso](https://documenso.com/): An open-source alternative to Docusign
+- [abby](https://github.com/tryabby/abby): An open-source feature flag, remote config and A/B testing platform for developers
+- [ghostfolio](https://ghostfol.io/en/start): An open-source dashboard for your personal finances
+- [revert](https://www.revert.dev/): An open-source unified API to build B2B product integrations
+- [Scholarsome](https://scholarsome.com/): An interactive, studying system
+- [Dittofeed](https://www.dittofeed.com): An open-source customer engagement; intuitive marketing tools that scale
+- [Trigger.dev](https://trigger.dev/): Effortless automation built for developers (Zapier alternative)
+- [Webstudio](https://github.com/webstudio-is/webstudio-designer): A NoCode visual design tool for building apps and websites
+- [Dyrector](https://github.com/dyrector-io/dyrectorio): A self-hosted container management platform
+- [reduced.to](https://github.com/origranot/reduced.to): An open-source link shortener
+- [Linen](https://github.com/Linen-dev/linen.dev): An open-source alternative to Slack and Discord with lots of great features
+- [Coolify](https://github.com/coollabsio/coolify): An open-source & self-hostable Heroku / Netlify alternative
+- [Dub.co](https://dub.co): An open-source link management platform for modern marketing teams
+- [Umami](https://github.com/mikecao/umami): A simple, fast, privacy-focused alternative to Google Analytics
+- [Rallly](https://github.com/lukevella/rallly): A self-hostable doodle poll alternative (based on Next.js, tRPC, and TailwindCSS)
+- [Typebot](https://github.com/baptisteArno/typebot.io): A conversational form builder that you can self-host
+- [Cal.com](https://github.com/calcom/cal.com): An open-source alternative to Calendly (calender-based event scheduling service)
+- [Beam](https://github.com/planetscale/beam): A simple tool that allows members to write posts to share across your organization (based on Next.js)
+- [Dundring](https://github.com/sivertschou/dundring): An in-browser training application created to control and track you training with a smart bike trainer
+- [Expense.fyi](https://github.com/gokulkrishh/expense.fyi): A tool for tracking and managing expenses
+- [Letterpad](https://github.com/letterpad/letterpad): A publishing platform for creatives
+- [Teable](https://github.com/teableio/teable): A no-code real-time database built on Postgres with a simple interface for enterprise-level app development.
+
+
+## Starter kits
+
+- [T3 Stack](https://create.t3.gg/): Starter kit based on Next.js, TypeScript, tRPC, Prisma, Tailwind CSS, and NextAuth.js.
+- [Indie Stack](https://github.com/remix-run/indie-stack): Remix Stack for deploying to Fly with SQLite, authentication, testing, linting, and formatting.
+- [Blues Stack](https://github.com/remix-run/blues-stack): Remix Stack for deploying to Fly with PostgreSQL, authentication, testing, linting, and formatting.
+- [NestJS Prisma Starter](https://github.com/notiz-dev/nestjs-prisma-starter): NestJS, Prisma, and authentication starter template.
+- [Supastarter](https://supastarter.dev/): Full-stack SaaS starter kit using Next.js/Nuxt.js/SvelteKit and Prisma with authentication, emails, payment, testing, linting, and formatting.
+- [Saas Kit Prisma](https://github.com/Saas-Starter-Kit/Saas-Kit-prisma): Full-stack SaaS starter kit using React.js, Next.js, TypeScript, Tailwind, Shadcn, Stripe, NextAuth, Prisma, Postgres, and Playwright.
+- [Saas Kit Prisma by BoxyHQ](https://github.com/boxyhq/saas-starter-kit): An open-source enterprise SaaS starter kit using Prisma ORM.
+- [NextReady](https://nextready.dev): A ready-to-use Next.js boilerplate with Prisma, TypeScript, Tailwind CSS, and more.
+
+## Badges
+
+[](https://prisma.io) [](https://prisma.io)
+
+Built something awesome with Prisma? 🌟 Show it off with these [badges](https://github.com/prisma/presskit?tab=readme-ov-file#badges), perfect for your readme or website.
+
+```
+[](https://prisma.io)
+```
+
+```
+[](https://prisma.io)
+```
+
+## Security
+
+If you have a security issue to report, please contact us at [security@prisma.io](mailto:security@prisma.io?subject=[GitHub]%20Prisma%202%20Security%20Report%20Examples)
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000000..5d93b0ad8d99
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,3 @@
+# Security Policy
+
+If you have a security issue to report, please contact us at [security@prisma.io](mailto:security@prisma.io).
diff --git a/accelerate/accelerate-hacker-news/.env.example b/accelerate/accelerate-hacker-news/.env.example
new file mode 100644
index 000000000000..ec5b630d21d1
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/.env.example
@@ -0,0 +1,2 @@
+DIRECT_URL=
+DATABASE_URL=
diff --git a/accelerate/accelerate-hacker-news/.eslintrc.json b/accelerate/accelerate-hacker-news/.eslintrc.json
new file mode 100644
index 000000000000..37224185490e
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": ["next/core-web-vitals", "next/typescript"]
+}
diff --git a/accelerate/accelerate-hacker-news/.gitignore b/accelerate/accelerate-hacker-news/.gitignore
new file mode 100644
index 000000000000..1dadbb67dd23
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/.gitignore
@@ -0,0 +1,39 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
+
+prisma/migrations
+package-lock.json
diff --git a/accelerate/accelerate-hacker-news/README.md b/accelerate/accelerate-hacker-news/README.md
new file mode 100644
index 000000000000..3a2ed477aef2
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/README.md
@@ -0,0 +1,89 @@
+# Prisma Accelerate Hacker News Clone
+
+This project showcases how to use Prisma ORM with Prisma Accelerate, leveraging caching and on-demand cache invalidation, in a Next.js application to build a minimal Hacker News clone.
+
+This app retrieves and caches the [top 20 latest posts](/app/page.tsx#L8) with a long Time-to-Live ([TTL](https://www.prisma.io/docs/accelerate/caching#time-to-live-ttl)). The cache is invalidated on-demand whenever a post is [upvoted](/app/actions/addVotes.ts) or a [new post is added](/app/submit/actions/addPost.ts).
+
+
+
+## Prerequisites
+
+To successfully run the project, you will need the following:
+
+- The **connection string** of a PostgreSQL database
+- Your **Accelerate connection string** (containing your **Accelerate API key**) which you can get by enabling Accelerate in a project in your [Prisma Data Platform](https://pris.ly/pdp) account (learn more in the [docs](https://www.prisma.io/docs/platform/concepts/environments#api-keys))
+
+## Getting started
+
+### 1. Clone the repository
+
+Clone the repository, navigate into it and install dependencies:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+cd prisma-examples/accelerate/accelerate-hacker-news
+npm install
+```
+
+### 2. Configure environment variables
+
+Create a `.env` in the root of the project directory:
+
+```bash
+cp .env.example .env
+```
+
+Now, open the `.env` file and set the `DATABASE_URL` and `DIRECT_URL` environment variables with the values of your connection string and your Accelerate connection string:
+
+```bash
+# .env
+
+# Accelerate connection string (used for queries by Prisma Client)
+DATABASE_URL="__YOUR_ACCELERATE_CONNECTION_STRING__"
+
+# Database connection string (used for migrations by Prisma Migrate)
+DIRECT_URL="__YOUR_DATABASE_CONNECTION_STRING__"
+```
+
+Note that `__YOUR_DATABASE_CONNECTION_STRING__` and `__YOUR_ACCELERATE_CONNECTION_STRING__` are placeholder values that you need to replace with the values of your database and Accelerate connection strings. Notice that the Accelerate connection string has the following structure: `prisma://accelerate.prisma-data.net/?api_key=__YOUR_ACCELERATE_API_KEY__`.
+
+### 3. Run a migration to create the `Post` table
+
+The Prisma schema file contains a single `Post` model. You can map this model to the database and create the corresponding `Post` table using the following command:
+
+```
+npx prisma migrate dev --name init
+```
+
+### 4. Generate Prisma Client for Accelerate
+
+When using Accelerate, Prisma Client doesn't need a query engine. That's why you should generate it as follows:
+
+```
+npx prisma generate --no-engine
+```
+
+### 5. Start the app
+
+You can run the app with the following command:
+
+```
+npm run dev
+```
+
+You should now be able to:
+
+- See the most recent post at http://localhost:3000 and upvote it by clicking the ▲ button.
+- Submit a new post by navigating to http://localhost:3000/submit.
+
+When you make changes, it might take a few seconds to invalidate the cache and display the latest changes.
+
+## Resources
+
+- [Accelerate Speed Test](https://accelerate-speed-test.vercel.app/)
+- [Accelerate documentation](https://www.prisma.io/docs/accelerate)
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/accelerate/accelerate-hacker-news/app/actions/addVotes.ts b/accelerate/accelerate-hacker-news/app/actions/addVotes.ts
new file mode 100644
index 000000000000..2f209ea7a4d3
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/app/actions/addVotes.ts
@@ -0,0 +1,26 @@
+'use server'
+
+import prisma from '@/lib/db'
+
+export async function addVotes(id: number) {
+ // console.log({
+ // updating: id,
+ // })
+
+ await prisma.post.update({
+ where: {
+ id: id,
+ },
+ data: {
+ vote: {
+ increment: 1,
+ },
+ },
+ })
+
+ await prisma.$accelerate.invalidate({
+ tags: ['posts'],
+ })
+
+ return id
+}
diff --git a/accelerate/accelerate-hacker-news/app/favicon.ico b/accelerate/accelerate-hacker-news/app/favicon.ico
new file mode 100644
index 000000000000..718d6fea4835
Binary files /dev/null and b/accelerate/accelerate-hacker-news/app/favicon.ico differ
diff --git a/accelerate/accelerate-hacker-news/app/fonts/GeistMonoVF.woff b/accelerate/accelerate-hacker-news/app/fonts/GeistMonoVF.woff
new file mode 100644
index 000000000000..f2ae185cbfd1
Binary files /dev/null and b/accelerate/accelerate-hacker-news/app/fonts/GeistMonoVF.woff differ
diff --git a/accelerate/accelerate-hacker-news/app/fonts/GeistVF.woff b/accelerate/accelerate-hacker-news/app/fonts/GeistVF.woff
new file mode 100644
index 000000000000..1b62daacff96
Binary files /dev/null and b/accelerate/accelerate-hacker-news/app/fonts/GeistVF.woff differ
diff --git a/accelerate/accelerate-hacker-news/app/globals.css b/accelerate/accelerate-hacker-news/app/globals.css
new file mode 100644
index 000000000000..13d40b892057
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/app/globals.css
@@ -0,0 +1,27 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ --background: #ffffff;
+ --foreground: #171717;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --background: #0a0a0a;
+ --foreground: #ededed;
+ }
+}
+
+body {
+ color: var(--foreground);
+ background: var(--background);
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+@layer utilities {
+ .text-balance {
+ text-wrap: balance;
+ }
+}
diff --git a/accelerate/accelerate-hacker-news/app/layout.tsx b/accelerate/accelerate-hacker-news/app/layout.tsx
new file mode 100644
index 000000000000..ffed14949dba
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/app/layout.tsx
@@ -0,0 +1,37 @@
+import type { Metadata } from 'next'
+import localFont from 'next/font/local'
+import './globals.css'
+
+const geistSans = localFont({
+ src: './fonts/GeistVF.woff',
+ variable: '--font-geist-sans',
+ weight: '100 900',
+})
+const geistMono = localFont({
+ src: './fonts/GeistMonoVF.woff',
+ variable: '--font-geist-mono',
+ weight: '100 900',
+})
+
+export const metadata: Metadata = {
+ title: 'Accelerate Hacker News Clone',
+ description: 'A minimal hackernews clone using Prisma Accelerate',
+}
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode
+}>) {
+ return (
+
+
+
+
+
+ )
+}
diff --git a/accelerate/accelerate-hacker-news/app/page.tsx b/accelerate/accelerate-hacker-news/app/page.tsx
new file mode 100644
index 000000000000..6e2911a80d5c
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/app/page.tsx
@@ -0,0 +1,50 @@
+import { Post } from '@/components/Posts'
+import prisma from '@/lib/db'
+
+export const dynamic = 'force-dynamic'
+export const revalidate = 0
+
+export default async function Home() {
+ const { data, info } = await prisma.post
+ .findMany({
+ take: 20,
+ orderBy: {
+ createdAt: 'desc',
+ },
+ cacheStrategy: {
+ ttl: 400,
+ tags: ['posts'],
+ },
+ })
+ .withAccelerateInfo()
+
+ console.log({ info })
+
+ return (
+ <>
+
+
+
+ {data.map((post, itemNo) => (
+
+
+
+ ))}
+
+
+ >
+ )
+}
diff --git a/accelerate/accelerate-hacker-news/app/submit/actions/addPost.ts b/accelerate/accelerate-hacker-news/app/submit/actions/addPost.ts
new file mode 100644
index 000000000000..a22f66fc3b21
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/app/submit/actions/addPost.ts
@@ -0,0 +1,25 @@
+'use server'
+
+import prisma from '@/lib/db'
+
+export async function createPost(formData: FormData) {
+ const title = formData.get('title')
+ const text = formData.get('text')
+ const url = formData.get('url')
+
+ const newPost = await prisma.post.create({
+ data: {
+ title: title?.toString() ?? '',
+ content: text?.toString() ?? '',
+ url: url?.toString() ?? '',
+ vote: 0,
+ },
+ })
+
+ await prisma.$accelerate.invalidate({
+ tags: ['posts'],
+ })
+
+ // console.log({ newPost }, 'has been created.')
+ return newPost
+}
diff --git a/accelerate/accelerate-hacker-news/app/submit/page.tsx b/accelerate/accelerate-hacker-news/app/submit/page.tsx
new file mode 100644
index 000000000000..02de69d93099
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/app/submit/page.tsx
@@ -0,0 +1,14 @@
+import { PostForm } from '@/components/PostSubmissionForm'
+
+export default function Submit() {
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/accelerate/accelerate-hacker-news/components/PostSubmissionForm.tsx b/accelerate/accelerate-hacker-news/components/PostSubmissionForm.tsx
new file mode 100644
index 000000000000..3c90c7dc677e
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/components/PostSubmissionForm.tsx
@@ -0,0 +1,69 @@
+'use client'
+import { createPost } from '@/app/submit/actions/addPost'
+import { useRef } from 'react'
+
+export const PostForm = () => {
+ const ref = useRef(null)
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/accelerate/accelerate-hacker-news/components/Posts.tsx b/accelerate/accelerate-hacker-news/components/Posts.tsx
new file mode 100644
index 000000000000..a9ce09ea3aea
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/components/Posts.tsx
@@ -0,0 +1,43 @@
+'use client'
+
+import { addVotes } from '@/app/actions/addVotes'
+import { useEffect, useState } from 'react'
+
+interface PostProps {
+ id: number
+ itemNo: number
+ title: string
+ url: string
+ votes: number
+}
+
+export const Post = ({ itemNo, title, url, votes, id }: PostProps) => {
+ useEffect(() => {}, [votes])
+
+ const [vote, controlVote] = useState(votes)
+
+ const increaseVotes = async () => {
+ try {
+ await addVotes(id)
+ controlVote((prev) => prev + 1)
+ } catch (error) {
+ console.log(error)
+ }
+ }
+
+ return (
+
+
+ {`${itemNo}. `}
+
+ ▲
+ {' '}
+ {title}{' '}
+
+ {`(${url})`}
+
+
+
{vote} points
+
+ )
+}
diff --git a/accelerate/accelerate-hacker-news/demo.gif b/accelerate/accelerate-hacker-news/demo.gif
new file mode 100644
index 000000000000..bcf9f03d9ace
Binary files /dev/null and b/accelerate/accelerate-hacker-news/demo.gif differ
diff --git a/accelerate/accelerate-hacker-news/lib/db.ts b/accelerate/accelerate-hacker-news/lib/db.ts
new file mode 100644
index 000000000000..3a89a2e8bc61
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/lib/db.ts
@@ -0,0 +1,16 @@
+import { PrismaClient } from '@prisma/client'
+import { withAccelerate } from '@prisma/extension-accelerate'
+
+const prismaClientSingleton = () => {
+ return new PrismaClient().$extends(withAccelerate())
+}
+
+declare const globalThis: {
+ prismaGlobal: ReturnType
+} & typeof global
+
+const prisma = globalThis.prismaGlobal ?? prismaClientSingleton()
+
+export default prisma
+
+if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma
diff --git a/accelerate/accelerate-hacker-news/next.config.mjs b/accelerate/accelerate-hacker-news/next.config.mjs
new file mode 100644
index 000000000000..4678774e6d60
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/next.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+export default nextConfig;
diff --git a/accelerate/accelerate-hacker-news/package.json b/accelerate/accelerate-hacker-news/package.json
new file mode 100644
index 000000000000..7fce1acdd579
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "accelerate-hacker-news",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "@prisma/extension-accelerate": "2.0.2",
+ "next": "15.3.5",
+ "react": "19.1.0",
+ "react-dom": "19.1.0"
+ },
+ "devDependencies": {
+ "prisma": "6.9.0",
+ "@faker-js/faker": "9.9.0",
+ "@types/node": "22.15.32",
+ "@types/react": "19.1.8",
+ "@types/react-dom": "19.1.6",
+ "eslint": "8.57.1",
+ "eslint-config-next": "15.3.5",
+ "postcss": "8.5.6",
+ "tailwindcss": "3.4.17",
+ "tsx": "4.20.6",
+ "typescript": "5.8.2"
+ },
+ "prisma": {
+ "seed": "tsx ./prisma/seed.ts"
+ }
+}
diff --git a/accelerate/accelerate-hacker-news/postcss.config.mjs b/accelerate/accelerate-hacker-news/postcss.config.mjs
new file mode 100644
index 000000000000..1a69fd2a450a
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/postcss.config.mjs
@@ -0,0 +1,8 @@
+/** @type {import('postcss-load-config').Config} */
+const config = {
+ plugins: {
+ tailwindcss: {},
+ },
+};
+
+export default config;
diff --git a/accelerate/accelerate-hacker-news/prisma/schema.prisma b/accelerate/accelerate-hacker-news/prisma/schema.prisma
new file mode 100644
index 000000000000..edc39f967e58
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/prisma/schema.prisma
@@ -0,0 +1,19 @@
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ url String
+ content String
+ vote Int
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
diff --git a/accelerate/accelerate-hacker-news/prisma/seed.ts b/accelerate/accelerate-hacker-news/prisma/seed.ts
new file mode 100644
index 000000000000..64842ad15683
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/prisma/seed.ts
@@ -0,0 +1,34 @@
+import { PrismaClient } from '@prisma/client'
+import { faker } from '@faker-js/faker'
+
+const prisma = new PrismaClient()
+
+const main = async () => {
+ await prisma.post.deleteMany()
+
+ for (let index = 0; index < 25; index++) {
+ const post = await prisma.post.create({
+ data: {
+ title: `${faker.animal.dog()} ${faker.airline.airplane().name}`,
+ content: faker.lorem.paragraph(),
+ url: faker.internet.url(),
+ vote: faker.number.int({
+ min: 2,
+ max: 111,
+ }),
+ },
+ })
+ console.log(`Seeded post ${index + 1}:`, post.title)
+ }
+}
+
+main()
+ .then(() => {
+ console.log('All seeds completed successfully')
+ })
+ .catch((e) => {
+ console.error('Seeding failed:', e)
+ })
+ .finally(() => {
+ prisma.$disconnect()
+ })
diff --git a/accelerate/accelerate-hacker-news/tailwind.config.ts b/accelerate/accelerate-hacker-news/tailwind.config.ts
new file mode 100644
index 000000000000..d43da912d03f
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/tailwind.config.ts
@@ -0,0 +1,19 @@
+import type { Config } from "tailwindcss";
+
+const config: Config = {
+ content: [
+ "./pages/**/*.{js,ts,jsx,tsx,mdx}",
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
+ ],
+ theme: {
+ extend: {
+ colors: {
+ background: "var(--background)",
+ foreground: "var(--foreground)",
+ },
+ },
+ },
+ plugins: [],
+};
+export default config;
diff --git a/accelerate/accelerate-hacker-news/tsconfig.json b/accelerate/accelerate-hacker-news/tsconfig.json
new file mode 100644
index 000000000000..e7ff90fd2767
--- /dev/null
+++ b/accelerate/accelerate-hacker-news/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/accelerate/astro-starter/.env.example b/accelerate/astro-starter/.env.example
new file mode 100644
index 000000000000..56a56ccfcadb
--- /dev/null
+++ b/accelerate/astro-starter/.env.example
@@ -0,0 +1,4 @@
+DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=__XX_XX_XX__"
+DIRECT_URL="postgresql://username:password@host:port/db_name"
+NODE_ENV="development"
+ASTRO_PUBLIC_URL="http://localhost:4321/"
\ No newline at end of file
diff --git a/accelerate/astro-starter/.gitignore b/accelerate/astro-starter/.gitignore
new file mode 100644
index 000000000000..198e6f789426
--- /dev/null
+++ b/accelerate/astro-starter/.gitignore
@@ -0,0 +1,26 @@
+# build output
+dist/
+
+# generated types
+.astro/
+
+# dependencies
+node_modules/
+
+# logs
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# environment variables
+.env
+.env.production
+
+# macOS-specific files
+.DS_Store
+
+# jetbrains setting folder
+.idea/
+
+!.env.example
\ No newline at end of file
diff --git a/accelerate/astro-starter/Astro-Accelerate-App.gif b/accelerate/astro-starter/Astro-Accelerate-App.gif
new file mode 100644
index 000000000000..0985e5d9d7e8
Binary files /dev/null and b/accelerate/astro-starter/Astro-Accelerate-App.gif differ
diff --git a/accelerate/astro-starter/Prisma-Studio-Image.png b/accelerate/astro-starter/Prisma-Studio-Image.png
new file mode 100644
index 000000000000..9180399bd1c7
Binary files /dev/null and b/accelerate/astro-starter/Prisma-Studio-Image.png differ
diff --git a/accelerate/astro-starter/README.md b/accelerate/astro-starter/README.md
new file mode 100644
index 000000000000..fc35b5827e07
--- /dev/null
+++ b/accelerate/astro-starter/README.md
@@ -0,0 +1,103 @@
+# Prisma Accelerate Example: Astro Starter
+
+This project showcases how to use Prisma ORM with Prisma Accelerate in a Astro application. It [demonstrates](./src/pages/route.ts#L13-16) every available [caching strategy in Accelerate](https://www.prisma.io/docs/accelerate/caching#cache-strategies).
+
+## Prerequisites
+
+To successfully run the project, you will need the following:
+
+- The **connection string** of a publicly accessible database.
+- Your **Accelerate connection string** (containing your **Accelerate API key**) which you can get by enabling Accelerate in a project in your [Prisma Data Platform](https://pris.ly/pdp) account (learn more in the [docs](https://www.prisma.io/docs/platform/about#api-keys)).
+
+## Getting started
+
+### 1. Clone the repository
+
+Clone the repository, navigate into it and install dependencies:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+cd prisma-examples/accelerate/astro-starter
+npm install
+```
+
+### 2. Configure environment variables
+
+Copy the `.env.example` env file in the root of the project directory:
+
+```bash
+cp .env.example .env
+```
+
+Now, open the `.env` file and set the `DIRECT_URL` and `DATABASE_URL` environment variables with the values of your connection string and your Accelerate connection string respectively:
+
+```bash
+# .env
+
+# Accelerate connection string (used for queries by Prisma Client)
+DATABASE_URL="__YOUR_ACCELERATE_CONNECTION_STRING__"
+
+# Database connection string (used for migrations by Prisma Migrate)
+DIRECT_URL="__YOUR_DATABASE_CONNECTION_STRING__"
+
+```
+
+Note that `__YOUR_DATABASE_CONNECTION_STRING__` and `__YOUR_ACCELERATE_CONNECTION_STRING__` are placeholder values that you need to replace with the values of your database and Accelerate connection strings. Notice that the Accelerate connection string has the following structure: `prisma://accelerate.prisma-data.net/?api_key=__YOUR_ACCELERATE_API_KEY__`.
+
+### 3. Run a migration to create the `Quote` table and seed the database
+
+The Prisma schema file contains a single `Quote` model. You can map this model to the database and create the corresponding `Quote` table using the following command:
+
+```
+npx prisma migrate dev --name init
+```
+
+You now have an empty `Quote` table in your database. Next, run the [seed script](./prisma/seed.ts) to create some sample records in the table:
+
+```
+npx prisma db seed
+```
+
+### 4. Generate Prisma Client for Accelerate
+
+When using Accelerate, Prisma Client doesn't need a query engine. That's why you should generate it as follows:
+
+```
+npx prisma generate --no-engine
+```
+
+### 5. Start the app
+
+You can run the app with the following command:
+
+```
+npm run dev
+```
+
+The application will start on PORT 4321 and you should be able to see the performance and other stats (e.g. cache/hit) for the different Accelerate cache strategies at the bottom of the UI:
+
+
+
+This application queries the most recent Quote with all the different cache strategies available in Accelerate.
+
+Optionally, to add your own quote and see the caching strategies in action, you can add a new quote through Prisma Studio by running the following command:
+
+```
+npx prisma studio
+```
+
+Once the Prisma Studio is running, you can add a new quote by clicking on the `Quote` table and then the `Add Record` button as shown in the screenshot below.
+
+
+
+After adding a new record, you can refresh the Astro application to see the new quote and the caching strategies in action.
+
+## Resources
+
+- [Accelerate Speed Test](https://accelerate-speed-test.vercel.app/)
+- [Accelerate documentation](https://www.prisma.io/docs/accelerate)
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/accelerate/astro-starter/astro.config.mjs b/accelerate/astro-starter/astro.config.mjs
new file mode 100644
index 000000000000..e98a1916d2c9
--- /dev/null
+++ b/accelerate/astro-starter/astro.config.mjs
@@ -0,0 +1,8 @@
+import { defineConfig } from 'astro/config'
+import tailwind from '@astrojs/tailwind'
+import react from '@astrojs/react'
+
+// https://astro.build/config
+export default defineConfig({
+ integrations: [tailwind(), react()],
+})
diff --git a/accelerate/astro-starter/package.json b/accelerate/astro-starter/package.json
new file mode 100644
index 000000000000..593578125569
--- /dev/null
+++ b/accelerate/astro-starter/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "astro-prisma-accelerate-starter-app",
+ "type": "module",
+ "version": "0.0.1",
+ "scripts": {
+ "dev": "astro dev",
+ "start": "astro dev",
+ "build": "astro check && astro build",
+ "preview": "astro preview",
+ "astro": "astro"
+ },
+ "dependencies": {
+ "@astrojs/check": "0.9.4",
+ "@astrojs/react": "4.3.0",
+ "@astrojs/tailwind": "6.0.2",
+ "@types/react": "19.1.8",
+ "@types/react-dom": "19.1.6",
+ "astro": "5.10.2",
+ "prisma": "6.9.0",
+ "react": "19.1.0",
+ "react-dom": "19.1.0",
+ "tailwindcss": "3.4.17",
+ "typescript": "5.8.2",
+ "@prisma/client": "6.9.0",
+ "@prisma/extension-accelerate": "2.0.2"
+ },
+ "devDependencies": {
+ "prisma": "6.9.0",
+ "tsx": "4.20.6"
+ },
+ "prisma": {
+ "seed": "tsx prisma/seed.ts"
+ }
+}
diff --git a/accelerate/astro-starter/prisma/migrations/20240708100736_init/migration.sql b/accelerate/astro-starter/prisma/migrations/20240708100736_init/migration.sql
new file mode 100644
index 000000000000..d98d1812b531
--- /dev/null
+++ b/accelerate/astro-starter/prisma/migrations/20240708100736_init/migration.sql
@@ -0,0 +1,8 @@
+-- CreateTable
+CREATE TABLE "Quote" (
+ "id" SERIAL NOT NULL,
+ "text" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+ CONSTRAINT "Quote_pkey" PRIMARY KEY ("id")
+);
diff --git a/accelerate/astro-starter/prisma/migrations/migration_lock.toml b/accelerate/astro-starter/prisma/migrations/migration_lock.toml
new file mode 100644
index 000000000000..fbffa92c2bb7
--- /dev/null
+++ b/accelerate/astro-starter/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "postgresql"
\ No newline at end of file
diff --git a/accelerate/astro-starter/prisma/schema.prisma b/accelerate/astro-starter/prisma/schema.prisma
new file mode 100644
index 000000000000..bec04763ca89
--- /dev/null
+++ b/accelerate/astro-starter/prisma/schema.prisma
@@ -0,0 +1,18 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
+}
+
+model Quote {
+ id Int @id @default(autoincrement())
+ text String
+ createdAt DateTime @default(now())
+}
diff --git a/accelerate/astro-starter/prisma/seed.ts b/accelerate/astro-starter/prisma/seed.ts
new file mode 100644
index 000000000000..6d3661e1bc08
--- /dev/null
+++ b/accelerate/astro-starter/prisma/seed.ts
@@ -0,0 +1,56 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+const main = async () => {
+ console.log('Seeding database 🌱')
+ console.time('Seeding complete 🌱')
+
+ await prisma.quote.createMany({
+ skipDuplicates: true,
+ data: [
+ { text: 'The only way to do great work is to love what you do.' },
+ {
+ text: 'Success is not final, failure is not fatal: It is the courage to continue that counts.',
+ },
+ { text: 'In the middle of every difficulty lies opportunity.' },
+ { text: "Believe you can and you're halfway there." },
+ { text: 'The best way to predict the future is to create it.' },
+ { text: "Don't watch the clock; do what it does. Keep going." },
+ { text: 'The only thing we have to fear is fear itself.' },
+ { text: 'The journey of a thousand miles begins with a single step.' },
+ { text: 'If you can dream it, you can achieve it.' },
+ { text: 'Innovation distinguishes between a leader and a follower.' },
+ {
+ text: 'The greatest glory in living lies not in never falling, but in rising every time we fall.',
+ },
+ { text: "You miss 100% of the shots you don't take." },
+ {
+ text: 'The only limit to our realization of tomorrow will be our doubts of today.',
+ },
+ { text: 'Change your thoughts and you change your world.' },
+ {
+ text: 'To be yourself in a world that is constantly trying to make you something else is the greatest accomplishment.',
+ },
+ {
+ text: "The only thing standing between you and your goal is the story you keep telling yourself as to why you can't achieve it.",
+ },
+ { text: 'Life is 10% what happens to us and 90% how we react to it.' },
+ {
+ text: 'The future belongs to those who believe in the beauty of their dreams.',
+ },
+ {
+ text: 'Do not wait for the perfect moment, take the moment and make it perfect.',
+ },
+ { text: 'The only source of knowledge is experience.' },
+ ],
+ })
+
+ console.timeEnd('Seeding complete 🌱')
+}
+
+main()
+ .then(() => {
+ console.log('Process completed')
+ })
+ .catch((e) => console.log(e))
diff --git a/accelerate/astro-starter/public/favicon.svg b/accelerate/astro-starter/public/favicon.svg
new file mode 100644
index 000000000000..f157bd1c5e28
--- /dev/null
+++ b/accelerate/astro-starter/public/favicon.svg
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/accelerate/astro-starter/src/components/Quote.astro b/accelerate/astro-starter/src/components/Quote.astro
new file mode 100644
index 000000000000..20236628284d
--- /dev/null
+++ b/accelerate/astro-starter/src/components/Quote.astro
@@ -0,0 +1,99 @@
+---
+import type { QuoteResult } from '../types/quote';
+
+interface Props {
+ title: string;
+ type: string;
+ result: QuoteResult;
+}
+
+const { title, type, result } = Astro.props;
+const { data, info, time } = result;
+---
+
+
+
+
+
+ ID {data.id} ⸺ {'"'}
+ {data.text}
+ {'"'}
+
+
+
+ Created At ⸺
+ {new Date(data.createdAt).toLocaleString("en-US")}
+
+
+
+
+
+
+
+ Cache Node Region ⸺
+
+ {info.region}
+
+
+
+
+ Cached Modified at ⸺
+
+ {new Date(info.lastModified).toLocaleString("en-US")}
+
+
+
+
+ Cache status ⸺
+
+ {info.cacheStatus.toUpperCase().concat(info.cacheStatus === "swr" || info.cacheStatus === "ttl" ? " CACHE HIT" : "")}
+
+
+
+
+ Time taken: {time}ms
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/accelerate/astro-starter/src/components/QuoteWrapper.astro b/accelerate/astro-starter/src/components/QuoteWrapper.astro
new file mode 100644
index 000000000000..f66c30c6eece
--- /dev/null
+++ b/accelerate/astro-starter/src/components/QuoteWrapper.astro
@@ -0,0 +1,22 @@
+---
+interface Props {
+ title: string;
+ type: string;
+ children: any;
+}
+
+const { title, type, children } = Astro.props;
+---
+
+
+
+
+ {title}
+
+
+
+ {type}
+
+
+
{children}
+
\ No newline at end of file
diff --git a/accelerate/astro-starter/src/components/Quotes.astro b/accelerate/astro-starter/src/components/Quotes.astro
new file mode 100644
index 000000000000..cfbb0aa457f1
--- /dev/null
+++ b/accelerate/astro-starter/src/components/Quotes.astro
@@ -0,0 +1,22 @@
+---
+import Quote from './Quote.astro';
+import type { QuoteResult } from '../types/quote';
+
+interface Props {
+ cacheStrategies: {
+ ttl: QuoteResult;
+ swr: QuoteResult;
+ both: QuoteResult;
+ none: QuoteResult;
+ };
+}
+
+const { cacheStrategies } = Astro.props;
+---
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/accelerate/astro-starter/src/env.d.ts b/accelerate/astro-starter/src/env.d.ts
new file mode 100644
index 000000000000..8c34fb45e7cf
--- /dev/null
+++ b/accelerate/astro-starter/src/env.d.ts
@@ -0,0 +1 @@
+///
\ No newline at end of file
diff --git a/accelerate/astro-starter/src/layouts/Layout.astro b/accelerate/astro-starter/src/layouts/Layout.astro
new file mode 100644
index 000000000000..c701b5d738b6
--- /dev/null
+++ b/accelerate/astro-starter/src/layouts/Layout.astro
@@ -0,0 +1,51 @@
+---
+interface Props {
+ title: string;
+}
+
+const { title } = Astro.props;
+---
+
+
+
+
+
+
+
+
+
+ {title}
+
+
+
+
+
+
diff --git a/accelerate/astro-starter/src/lib/utils/helper.ts b/accelerate/astro-starter/src/lib/utils/helper.ts
new file mode 100644
index 000000000000..1a6e6612f55e
--- /dev/null
+++ b/accelerate/astro-starter/src/lib/utils/helper.ts
@@ -0,0 +1 @@
+export const HOST = process.env.ASTRO_PUBLIC_URL ?? 'http://localhost:4321/'
diff --git a/accelerate/astro-starter/src/lib/utils/query.ts b/accelerate/astro-starter/src/lib/utils/query.ts
new file mode 100644
index 000000000000..e0b12352524b
--- /dev/null
+++ b/accelerate/astro-starter/src/lib/utils/query.ts
@@ -0,0 +1,21 @@
+import prisma from '../../pages/db.ts'
+
+export const getQuotes = async (strategy?: any) => {
+ const start = Date.now()
+
+ const result = await prisma.quote
+ .findMany({
+ cacheStrategy: strategy,
+ orderBy: {
+ id: 'desc',
+ },
+ take: 1,
+ })
+ .withAccelerateInfo()
+
+ return {
+ data: result?.data?.[0],
+ info: result.info,
+ time: Date.now() - start,
+ }
+}
diff --git a/accelerate/astro-starter/src/pages/db.ts b/accelerate/astro-starter/src/pages/db.ts
new file mode 100644
index 000000000000..05af8f9c8961
--- /dev/null
+++ b/accelerate/astro-starter/src/pages/db.ts
@@ -0,0 +1,18 @@
+import { PrismaClient } from '@prisma/client'
+import { withAccelerate } from '@prisma/extension-accelerate'
+
+// Learn more about instantiating PrismaClient in Next.js here: https://www.prisma.io/docs/data-platform/accelerate/getting-started
+
+const prismaClientSingleton = () => {
+ return new PrismaClient().$extends(withAccelerate())
+}
+
+declare const globalThis: {
+ prismaGlobal: ReturnType
+} & typeof global
+
+const prisma = globalThis.prismaGlobal ?? prismaClientSingleton()
+
+export default prisma
+
+if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma
diff --git a/accelerate/astro-starter/src/pages/index.astro b/accelerate/astro-starter/src/pages/index.astro
new file mode 100644
index 000000000000..cab4a9bd691a
--- /dev/null
+++ b/accelerate/astro-starter/src/pages/index.astro
@@ -0,0 +1,59 @@
+---
+import Layout from '../layouts/Layout.astro';
+import Quotes from '../components/Quotes.astro';
+import type { QuoteResult } from '../types/quote';
+import { HOST } from '../lib/utils/helper';
+
+let cacheStrategies: {
+ ttl: QuoteResult;
+ swr: QuoteResult;
+ both: QuoteResult;
+ none: QuoteResult;
+} = {
+ ttl: { data: { id: 0, text: '', createdAt: '' }, info: { cacheStatus: '', region: '', lastModified: '' }, time: 0 },
+ swr: { data: { id: 0, text: '', createdAt: '' }, info: { cacheStatus: '', region: '', lastModified: '' }, time: 0 },
+ both: { data: { id: 0, text: '', createdAt: '' }, info: { cacheStatus: '', region: '', lastModified: '' }, time: 0 },
+ none: { data: { id: 0, text: '', createdAt: '' }, info: { cacheStatus: '', region: '', lastModified: '' }, time: 0 }
+};
+
+try {
+ console.log('Fetching quotes...');
+ const response = await fetch(`${HOST}/route`);
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ const data = await response.json();
+ cacheStrategies = data.cacheStrategies;
+} catch (error) {
+ console.error('Error fetching quotes:', error);
+}
+---
+
+
+
+
+ Accelerated Quotes
+
+
+
+ Retrieves the most recently added quote with and without caching enabled
+
+
+
+ Refresh
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/accelerate/astro-starter/src/pages/route.ts b/accelerate/astro-starter/src/pages/route.ts
new file mode 100644
index 000000000000..2b2dcbc3ecc5
--- /dev/null
+++ b/accelerate/astro-starter/src/pages/route.ts
@@ -0,0 +1,32 @@
+import type { APIRoute } from 'astro'
+import { getQuotes } from '../lib/utils/query'
+
+export const GET: APIRoute = async () => {
+ const cacheStrategies = {
+ TTL: { ttl: 30 },
+ SWR: { swr: 30 },
+ BOTH: { ttl: 30, swr: 60 },
+ NONE: undefined,
+ }
+
+ const results = await Promise.all([
+ getQuotes(cacheStrategies.TTL),
+ getQuotes(cacheStrategies.SWR),
+ getQuotes(cacheStrategies.BOTH),
+ getQuotes(cacheStrategies.NONE),
+ ])
+
+ const response = {
+ cacheStrategies: {
+ ttl: results[0],
+ swr: results[1],
+ both: results[2],
+ none: results[3],
+ },
+ }
+
+ return new Response(JSON.stringify(response), {
+ headers: { 'Content-Type': 'application/json' },
+ status: 200,
+ })
+}
diff --git a/accelerate/astro-starter/src/types/quote.ts b/accelerate/astro-starter/src/types/quote.ts
new file mode 100644
index 000000000000..c8b4b1f247b6
--- /dev/null
+++ b/accelerate/astro-starter/src/types/quote.ts
@@ -0,0 +1,18 @@
+export interface QuoteData {
+ [x: string]: unknown
+ id: number
+ text: string
+ createdAt: string
+}
+
+export interface CacheInfo {
+ cacheStatus: string
+ region: string
+ lastModified: string
+}
+
+export interface QuoteResult {
+ data: QuoteData
+ info: CacheInfo
+ time: number
+}
diff --git a/accelerate/astro-starter/tailwind.config.mjs b/accelerate/astro-starter/tailwind.config.mjs
new file mode 100644
index 000000000000..19f0614dd65d
--- /dev/null
+++ b/accelerate/astro-starter/tailwind.config.mjs
@@ -0,0 +1,8 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+}
diff --git a/accelerate/astro-starter/tsconfig.json b/accelerate/astro-starter/tsconfig.json
new file mode 100644
index 000000000000..032ad645d6b7
--- /dev/null
+++ b/accelerate/astro-starter/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "astro/tsconfigs/strict",
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "jsxImportSource": "react"
+ }
+}
\ No newline at end of file
diff --git a/accelerate/nextjs-starter/.eslintrc.json b/accelerate/nextjs-starter/.eslintrc.json
new file mode 100644
index 000000000000..bffb357a7122
--- /dev/null
+++ b/accelerate/nextjs-starter/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
diff --git a/accelerate/nextjs-starter/.gitignore b/accelerate/nextjs-starter/.gitignore
new file mode 100644
index 000000000000..e47b79fb6d9f
--- /dev/null
+++ b/accelerate/nextjs-starter/.gitignore
@@ -0,0 +1,38 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+.env
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
+package-lock.json
diff --git a/accelerate/nextjs-starter/LICENSE b/accelerate/nextjs-starter/LICENSE
new file mode 100644
index 000000000000..f2b47fb8a371
--- /dev/null
+++ b/accelerate/nextjs-starter/LICENSE
@@ -0,0 +1,21 @@
+MIT License Copyright (c) 2024 ankur
+
+Permission is hereby granted, free of
+charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice
+(including the next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
+EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/accelerate/nextjs-starter/README.md b/accelerate/nextjs-starter/README.md
new file mode 100644
index 000000000000..d3afd5d87f2a
--- /dev/null
+++ b/accelerate/nextjs-starter/README.md
@@ -0,0 +1,93 @@
+# Prisma Accelerate Example: Next.js Starter
+
+This project showcases how to use Prisma ORM with Prisma Accelerate in a Next.js application. It [demonstrates](./app/api/route.ts#L15-46) every available [caching strategy in Accelerate](https://www.prisma.io/docs/data-platform/accelerate/concepts#cache-strategies).
+
+## Prerequisites
+
+To successfully run the project, you will need the following:
+
+- The **connection string** of a publicly accessible database
+- Your **Accelerate connection string** (containing your **Accelerate API key**) which you can get by enabling Accelerate in a project in your [Prisma Data Platform](https://pris.ly/pdp) account (learn more in the [docs](https://www.prisma.io/docs/platform/concepts/environments#api-keys))
+
+## Getting started
+
+### 1. Clone the repository
+
+Clone the repository, navigate into it and install dependencies:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+cd prisma-examples/accelerate/nextjs-starter
+npm install
+```
+
+### 2. Configure environment variables
+
+Create a `.env` in the root of the project directory:
+
+```bash
+touch .env
+```
+
+Now, open the `.env` file and set the `DATABASE_URL` and `DIRECT_URL` environment variables with the values of your connection string and your Accelerate connection string:
+
+```bash
+# .env
+
+# Accelerate connection string (used for queries by Prisma Client)
+DATABASE_URL="__YOUR_ACCELERATE_CONNECTION_STRING__"
+
+# Database connection string (used for migrations by Prisma Migrate)
+DIRECT_URL="__YOUR_DATABASE_CONNECTION_STRING__"
+
+NEXT_PUBLIC_URL="http://localhost:3000/"
+```
+
+Note that `__YOUR_DATABASE_CONNECTION_STRING__` and `__YOUR_ACCELERATE_CONNECTION_STRING__` are placeholder values that you need to replace with the values of your database and Accelerate connection strings. Notice that the Accelerate connection string has the following structure: `prisma://accelerate.prisma-data.net/?api_key=__YOUR_ACCELERATE_API_KEY__`.
+
+### 3. Run a migration to create the `Quotes` table and seed the database
+
+The Prisma schema file contains a single `Quotes` model. You can map this model to the database and create the corresponding `Quotes` table using the following command:
+
+```
+npx prisma migrate dev --name init
+```
+
+You now have an empty `Quotes` table in your database. Next, run the [seed script](./prisma/seed.ts) to create some sample records in the table:
+
+```
+npx prisma db seed
+```
+
+### 4. Generate Prisma Client for Accelerate
+
+When using Accelerate, Prisma Client doesn't need a query engine. That's why you should generate it as follows:
+
+```
+npx prisma generate --no-engine
+```
+
+### 5. Start the app
+
+You can run the app with the following command:
+
+```
+npm run dev
+```
+
+> If you encounter issues making `POST` requests to the database, particularly failures when adding a new quote—try setting the environment variable to bypass TLS certificate validation. In your development environment, run `export NODE_TLS_REJECT_UNAUTHORIZED='0'`.
+
+
+You can see the performancen and other stats (e.g. cache/hit) for the different Accelerate cache strategies at the bottom of the UI:
+
+
+
+## Resources
+
+- [Accelerate Speed Test](https://accelerate-speed-test.vercel.app/)
+- [Accelerate documentation](https://www.prisma.io/docs/accelerate)
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/accelerate/nextjs-starter/app/api/route.ts b/accelerate/nextjs-starter/app/api/route.ts
new file mode 100644
index 000000000000..193cbd2b0492
--- /dev/null
+++ b/accelerate/nextjs-starter/app/api/route.ts
@@ -0,0 +1,65 @@
+import { addQuote, getQuotes } from "@/lib/utils/query";
+import { z } from "zod";
+
+export const runtime = "edge";
+
+// disabling caching
+export const fetchCache = "force-no-store";
+export const revalidate = 0;
+
+export async function GET(request: Request) {
+ const url = new URL(request.url);
+ const searchParams = new URLSearchParams(url.search);
+
+ const parser = z.enum(["TTL", "SWR", "BOTH", "NONE"]);
+ const parsedOutput = await parser.safeParseAsync(searchParams.get("cache"));
+
+ if (!parsedOutput.success) {
+ return new Response(JSON.stringify("Invalid search parameter."), {
+ status: 400,
+ });
+ }
+
+ let map = new Map();
+
+ // When TTL is selected
+ map.set("TTL", {
+ ttl: 30,
+ });
+
+ // When SWR is selected
+ map.set("SWR", {
+ swr: 30,
+ });
+
+ // When TTL + SWR is selected
+ map.set("BOTH", {
+ ttl: 30,
+ swr: 60,
+ });
+
+ // This ensures no caching is performed and only the Accelerate connection pool is used
+ map.set("NONE", undefined);
+
+ const data = await getQuotes(map.get(parsedOutput.data));
+
+ return new Response(JSON.stringify(data), {
+ headers: { "Content-Type": "application/json" },
+ status: 200,
+ });
+}
+
+export async function POST(request: Request) {
+ const response = await fetch("http://github.com/service/https://api.quotable.io/random", {
+ cache: "no-cache",
+ });
+
+ const data = await response.json();
+
+ await addQuote(data.content);
+
+ return new Response(JSON.stringify({ quote: data.content }), {
+ headers: { "Content-Type": "application/json" },
+ status: 201,
+ });
+}
diff --git a/accelerate/nextjs-starter/app/favicon.ico b/accelerate/nextjs-starter/app/favicon.ico
new file mode 100644
index 000000000000..718d6fea4835
Binary files /dev/null and b/accelerate/nextjs-starter/app/favicon.ico differ
diff --git a/accelerate/nextjs-starter/app/globals.css b/accelerate/nextjs-starter/app/globals.css
new file mode 100644
index 000000000000..fd81e885836d
--- /dev/null
+++ b/accelerate/nextjs-starter/app/globals.css
@@ -0,0 +1,27 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ --foreground-rgb: 0, 0, 0;
+ --background-start-rgb: 214, 219, 220;
+ --background-end-rgb: 255, 255, 255;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --foreground-rgb: 255, 255, 255;
+ --background-start-rgb: 0, 0, 0;
+ --background-end-rgb: 0, 0, 0;
+ }
+}
+
+body {
+ color: rgb(var(--foreground-rgb));
+ background: linear-gradient(
+ to bottom,
+ transparent,
+ rgb(var(--background-end-rgb))
+ )
+ rgb(var(--background-start-rgb));
+}
diff --git a/accelerate/nextjs-starter/app/layout.tsx b/accelerate/nextjs-starter/app/layout.tsx
new file mode 100644
index 000000000000..629112e640fe
--- /dev/null
+++ b/accelerate/nextjs-starter/app/layout.tsx
@@ -0,0 +1,22 @@
+import "./globals.css";
+import type { Metadata } from "next";
+import { Inter } from "next/font/google";
+
+const inter = Inter({ subsets: ["latin"] });
+
+export const metadata: Metadata = {
+ title: "Accelerated Quotes",
+ description: "Accelerate starter",
+};
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/accelerate/nextjs-starter/app/page.tsx b/accelerate/nextjs-starter/app/page.tsx
new file mode 100644
index 000000000000..2bf3465b1ee0
--- /dev/null
+++ b/accelerate/nextjs-starter/app/page.tsx
@@ -0,0 +1,28 @@
+import { AddQuote } from '@/components/Quote/AddQuote'
+import { QuotesLoading } from '@/components/Quote/QuotesLoading'
+import { Quotes } from '@/components/Quote/Quotes'
+import { Suspense } from 'react'
+
+// Disable caching. If 'force-dynamic' is not used, stale data can be returned from Prisma Client.
+// Learn more here: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/help-articles/nextjs-prisma-client-dynamic.
+export const dynamic = 'force-dynamic'
+
+export default async function Home() {
+ return (
+
+
+ Accelerated Quotes
+
+
+
+ Retrieves the most recently added quote with and without caching enabled
+
+
+
+
+ }>
+
+
+
+ )
+}
diff --git a/accelerate/nextjs-starter/components/Quote/AddQuote.tsx b/accelerate/nextjs-starter/components/Quote/AddQuote.tsx
new file mode 100644
index 000000000000..557641364059
--- /dev/null
+++ b/accelerate/nextjs-starter/components/Quote/AddQuote.tsx
@@ -0,0 +1,46 @@
+"use client";
+
+import { HOST, delay } from "@/lib/utils/helpers";
+import { useRouter } from "next/navigation";
+
+import toast, { Toaster } from "react-hot-toast";
+
+export const AddQuote = () => {
+ const router = useRouter();
+
+ const addQuote = async () => {
+ try {
+ const response = await fetch(`${HOST}/api`, {
+ method: "POST",
+ });
+ const data = await response.json();
+ const toastId = toast.success(`New quote added - "${data.quote}"`);
+ await delay(2000);
+ toast.remove(toastId);
+ router.refresh();
+ } catch (error) {
+ toast.error("Something went wrong");
+ }
+ };
+
+ return (
+ <>
+
+
+ Add new quote and refresh page
+
+
+ router.refresh()}
+ className="focus:outline-none text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"
+ >
+ Refresh
+
+ >
+ );
+};
diff --git a/accelerate/nextjs-starter/components/Quote/Quote.tsx b/accelerate/nextjs-starter/components/Quote/Quote.tsx
new file mode 100644
index 000000000000..fa040d5ee3c5
--- /dev/null
+++ b/accelerate/nextjs-starter/components/Quote/Quote.tsx
@@ -0,0 +1,78 @@
+import { QuoteWrapper } from "./QuoteWrapper";
+import { QuoteCacheType, QuoteResult } from "@/lib/types";
+import { findIATA } from "openflights-cached";
+
+export const Quote: React.FC<{
+ title: string;
+ type: QuoteCacheType;
+ result: QuoteResult;
+}> = ({ title, type, result }) => {
+ const [{ id, quote, createdAt }, { cacheStatus, region, lastModified }] = [
+ result.data,
+ result.info,
+ ];
+
+ return (
+
+
+
+ {" "}
+ ID {id} ⸺ {'"'}
+ {quote}
+ {'"'}
+
+
+
+ Created At ⸺
+ {new Date(createdAt).toLocaleString("en-US")}
+
+
+
+
+
+
+
+ Cache Node Region ⸺
+
+ {" "}
+ {findIATA(region)?.city ?? region}
+
+
+
+
+ Cached Modified at ⸺{" "}
+
+ {" "}
+ {new Date(lastModified).toLocaleString("en-US")}
+
+
+
+
+ Cache status ⸺{" "}
+
+ {" "}
+ {cacheStatus
+ .toUpperCase()
+ .concat(
+ cacheStatus === "swr" || cacheStatus === "ttl"
+ ? " CACHE HIT"
+ : ""
+ )}
+
+
+
+
+ Time taken: {result.time}ms
+
+
+
+
+
+ );
+};
diff --git a/accelerate/nextjs-starter/components/Quote/QuoteWrapper.tsx b/accelerate/nextjs-starter/components/Quote/QuoteWrapper.tsx
new file mode 100644
index 000000000000..f53050aa5fac
--- /dev/null
+++ b/accelerate/nextjs-starter/components/Quote/QuoteWrapper.tsx
@@ -0,0 +1,23 @@
+import { QuoteCacheType } from "@/lib/types";
+import { ReactNode } from "react";
+
+export const QuoteWrapper: React.FC<{
+ title: string;
+ type: QuoteCacheType;
+ children: ReactNode;
+}> = ({ title, type, children }) => {
+ return (
+
+
+
+ {title}
+
+
+
+ {type}
+
+
+
{children}
+
+ );
+};
diff --git a/accelerate/nextjs-starter/components/Quote/Quotes.tsx b/accelerate/nextjs-starter/components/Quote/Quotes.tsx
new file mode 100644
index 000000000000..443db76f2e41
--- /dev/null
+++ b/accelerate/nextjs-starter/components/Quote/Quotes.tsx
@@ -0,0 +1,37 @@
+import { Quote } from "@/components/Quote/Quote";
+import { QuoteResult } from "@/lib/types";
+import { HOST } from "@/lib/utils/helpers";
+
+const loadData = async (url: string): Promise => {
+ const { signal } = new AbortController();
+ const result = await fetch(url, {
+ cache: "no-cache",
+ signal: signal,
+ });
+ const data = await result.json();
+ return data;
+};
+
+const getQuotes = async () => {
+ const data = await Promise.all([
+ loadData(`${HOST}/api?cache=TTL`),
+ loadData(`${HOST}/api?cache=SWR`),
+ loadData(`${HOST}/api?cache=BOTH`),
+ loadData(`${HOST}/api?cache=NONE`),
+ ]);
+
+ return data;
+};
+
+export async function Quotes() {
+ const [ttl, swr, both, none] = await getQuotes();
+
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/accelerate/nextjs-starter/components/Quote/QuotesLoading.tsx b/accelerate/nextjs-starter/components/Quote/QuotesLoading.tsx
new file mode 100644
index 000000000000..46528e32ccd0
--- /dev/null
+++ b/accelerate/nextjs-starter/components/Quote/QuotesLoading.tsx
@@ -0,0 +1,57 @@
+import { title } from "process";
+import { QuoteWrapper } from "./QuoteWrapper";
+import type { QuoteCacheType } from "@/lib/types";
+
+const loaders: { title: string; type: QuoteCacheType }[] = [
+ {
+ title: "Cached Quote",
+ type: "TTL",
+ },
+ {
+ title: "Cached Quote",
+ type: "SWR",
+ },
+ {
+ title: "Cached Quote",
+ type: "TTL + SWR",
+ },
+ {
+ title: "Quote",
+ type: "No caching",
+ },
+];
+
+export const QuotesLoading: React.FC = () => {
+ return (
+
+ {loaders.map((value) => {
+ return (
+
+
+
+ );
+ })}
+
+ );
+};
diff --git a/accelerate/nextjs-starter/demo.gif b/accelerate/nextjs-starter/demo.gif
new file mode 100644
index 000000000000..23c69248f5b5
Binary files /dev/null and b/accelerate/nextjs-starter/demo.gif differ
diff --git a/accelerate/nextjs-starter/lib/db.ts b/accelerate/nextjs-starter/lib/db.ts
new file mode 100644
index 000000000000..8e783383ce35
--- /dev/null
+++ b/accelerate/nextjs-starter/lib/db.ts
@@ -0,0 +1,18 @@
+import { PrismaClient } from "@prisma/client/edge";
+import { withAccelerate } from "@prisma/extension-accelerate";
+
+// Learn more about instantiating PrismaClient in Next.js here: https://www.prisma.io/docs/data-platform/accelerate/getting-started
+
+const prismaClientSingleton = () => {
+ return new PrismaClient().$extends(withAccelerate());
+};
+
+declare const globalThis: {
+ prismaGlobal: ReturnType;
+} & typeof global;
+
+const prisma = globalThis.prismaGlobal ?? prismaClientSingleton();
+
+export default prisma;
+
+if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma;
diff --git a/accelerate/nextjs-starter/lib/types/index.ts b/accelerate/nextjs-starter/lib/types/index.ts
new file mode 100644
index 000000000000..b7cf3178147f
--- /dev/null
+++ b/accelerate/nextjs-starter/lib/types/index.ts
@@ -0,0 +1,33 @@
+export type CacheStrategy =
+ | {
+ ttl: number;
+ swr: number;
+ }
+ | {
+ ttl: number;
+ }
+ | {
+ swr: number;
+ };
+
+export type AccelerateInfo = {
+ cacheStatus: "ttl" | "swr" | "miss" | "none";
+ lastModified: Date;
+ region: string;
+ requestId: string;
+ signature: string;
+};
+
+export type Quote = {
+ id: number;
+ quote: string;
+ createdAt: string;
+};
+
+export type QuoteResult = {
+ data: Quote;
+ info: AccelerateInfo;
+ time: number;
+};
+
+export type QuoteCacheType = "SWR" | "TTL" | "No caching" | "TTL + SWR";
diff --git a/accelerate/nextjs-starter/lib/utils/helpers.ts b/accelerate/nextjs-starter/lib/utils/helpers.ts
new file mode 100644
index 000000000000..fe153bf4c2ed
--- /dev/null
+++ b/accelerate/nextjs-starter/lib/utils/helpers.ts
@@ -0,0 +1,9 @@
+export async function delay(ms: number): Promise {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, ms);
+ });
+}
+
+export const HOST = process.env.NEXT_PUBLIC_URL ?? "http://localhost:3000/";
diff --git a/accelerate/nextjs-starter/lib/utils/query.ts b/accelerate/nextjs-starter/lib/utils/query.ts
new file mode 100644
index 000000000000..7b9ddbaa7cfc
--- /dev/null
+++ b/accelerate/nextjs-starter/lib/utils/query.ts
@@ -0,0 +1,31 @@
+import prisma from "@/lib/db";
+import { CacheStrategy } from "@/lib/types";
+
+export const getQuotes = async (strategy?: CacheStrategy) => {
+ const start = Date.now();
+
+ const result = await prisma.quotes
+ .findMany({
+ // You can find the `cacheStrategy` options [here](https://www.prisma.io/docs/accelerate/caching#cache-strategies). The `cacheStrategy` can also be undefined, which would mean only connection pooling is being used.
+ cacheStrategy: strategy,
+ orderBy: {
+ id: "desc",
+ },
+ take: 1,
+ })
+ .withAccelerateInfo();
+
+ return {
+ data: result?.data?.[0],
+ info: result.info,
+ time: Date.now() - start,
+ };
+};
+
+export const addQuote = async (quote: string) => {
+ return await prisma.quotes.create({
+ data: {
+ quote,
+ },
+ });
+};
diff --git a/accelerate/nextjs-starter/next.config.js b/accelerate/nextjs-starter/next.config.js
new file mode 100644
index 000000000000..767719fc4fba
--- /dev/null
+++ b/accelerate/nextjs-starter/next.config.js
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {}
+
+module.exports = nextConfig
diff --git a/accelerate/nextjs-starter/package.json b/accelerate/nextjs-starter/package.json
new file mode 100644
index 000000000000..f96da9f725a1
--- /dev/null
+++ b/accelerate/nextjs-starter/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "accelerate-starter",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "npx prisma generate --no-engine && next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "@prisma/extension-accelerate": "2.0.2",
+ "@types/node": "22.15.32",
+ "@types/react": "19.1.8",
+ "@types/react-dom": "19.1.6",
+ "autoprefixer": "10.4.21",
+ "eslint": "8.57.1",
+ "eslint-config-next": "15.3.5",
+ "next": "15.3.5",
+ "node-fetch": "3.3.2",
+ "openflights-cached": "1.3.15",
+ "postcss": "8.5.6",
+ "react": "19.1.0",
+ "react-dom": "19.1.0",
+ "react-hot-toast": "2.5.2",
+ "tailwindcss": "3.4.17",
+ "typescript": "5.8.2",
+ "zod": "3.25.76"
+ },
+ "devDependencies": {
+ "prisma": "6.9.0",
+ "ts-node": "10.9.2"
+ },
+ "prisma": {
+ "seed": "ts-node prisma/seed.ts"
+ },
+ "license": "MIT"
+}
\ No newline at end of file
diff --git a/accelerate/nextjs-starter/postcss.config.js b/accelerate/nextjs-starter/postcss.config.js
new file mode 100644
index 000000000000..33ad091d26d8
--- /dev/null
+++ b/accelerate/nextjs-starter/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/accelerate/nextjs-starter/prisma/migrations/20240515102404_init_project/migration.sql b/accelerate/nextjs-starter/prisma/migrations/20240515102404_init_project/migration.sql
new file mode 100644
index 000000000000..48f0302a680a
--- /dev/null
+++ b/accelerate/nextjs-starter/prisma/migrations/20240515102404_init_project/migration.sql
@@ -0,0 +1,8 @@
+-- CreateTable
+CREATE TABLE "Quotes" (
+ "id" SERIAL NOT NULL,
+ "quote" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+ CONSTRAINT "Quotes_pkey" PRIMARY KEY ("id")
+);
diff --git a/accelerate/nextjs-starter/prisma/migrations/migration_lock.toml b/accelerate/nextjs-starter/prisma/migrations/migration_lock.toml
new file mode 100644
index 000000000000..fbffa92c2bb7
--- /dev/null
+++ b/accelerate/nextjs-starter/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "postgresql"
\ No newline at end of file
diff --git a/accelerate/nextjs-starter/prisma/schema.prisma b/accelerate/nextjs-starter/prisma/schema.prisma
new file mode 100644
index 000000000000..5d94e01214ed
--- /dev/null
+++ b/accelerate/nextjs-starter/prisma/schema.prisma
@@ -0,0 +1,18 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
+}
+
+model Quotes {
+ id Int @id @default(autoincrement())
+ quote String
+ createdAt DateTime @default(now())
+}
diff --git a/accelerate/nextjs-starter/prisma/seed.ts b/accelerate/nextjs-starter/prisma/seed.ts
new file mode 100644
index 000000000000..84e5cb002cf2
--- /dev/null
+++ b/accelerate/nextjs-starter/prisma/seed.ts
@@ -0,0 +1,62 @@
+import { PrismaClient } from "@prisma/client";
+
+const prisma = new PrismaClient();
+
+const main = async () => {
+ console.time("Seeding complete 🌱");
+
+ await prisma.quotes.createMany({
+ skipDuplicates: true,
+ data: [
+ { quote: "The only way to do great work is to love what you do." },
+ {
+ quote:
+ "Success is not final, failure is not fatal: It is the courage to continue that counts.",
+ },
+ { quote: "In the middle of every difficulty lies opportunity." },
+ { quote: "Believe you can and you're halfway there." },
+ { quote: "The best way to predict the future is to create it." },
+ { quote: "Don't watch the clock; do what it does. Keep going." },
+ { quote: "The only thing we have to fear is fear itself." },
+ { quote: "The journey of a thousand miles begins with a single step." },
+ { quote: "If you can dream it, you can achieve it." },
+ { quote: "Innovation distinguishes between a leader and a follower." },
+ {
+ quote:
+ "The greatest glory in living lies not in never falling, but in rising every time we fall.",
+ },
+ { quote: "You miss 100% of the shots you don't take." },
+ {
+ quote:
+ "The only limit to our realization of tomorrow will be our doubts of today.",
+ },
+ { quote: "Change your thoughts and you change your world." },
+ {
+ quote:
+ "To be yourself in a world that is constantly trying to make you something else is the greatest accomplishment.",
+ },
+ {
+ quote:
+ "The only thing standing between you and your goal is the story you keep telling yourself as to why you can't achieve it.",
+ },
+ { quote: "Life is 10% what happens to us and 90% how we react to it." },
+ {
+ quote:
+ "The future belongs to those who believe in the beauty of their dreams.",
+ },
+ {
+ quote:
+ "Do not wait for the perfect moment, take the moment and make it perfect.",
+ },
+ { quote: "The only source of knowledge is experience." },
+ ],
+ });
+
+ console.timeEnd("Seeding complete 🌱");
+};
+
+main()
+ .then(() => {
+ console.log("Process completed");
+ })
+ .catch((e) => console.log(e));
diff --git a/accelerate/nextjs-starter/public/next.svg b/accelerate/nextjs-starter/public/next.svg
new file mode 100644
index 000000000000..5174b28c565c
--- /dev/null
+++ b/accelerate/nextjs-starter/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/accelerate/nextjs-starter/public/vercel.svg b/accelerate/nextjs-starter/public/vercel.svg
new file mode 100644
index 000000000000..d2f84222734f
--- /dev/null
+++ b/accelerate/nextjs-starter/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/accelerate/nextjs-starter/tailwind.config.ts b/accelerate/nextjs-starter/tailwind.config.ts
new file mode 100644
index 000000000000..c48eb6d5b57e
--- /dev/null
+++ b/accelerate/nextjs-starter/tailwind.config.ts
@@ -0,0 +1,12 @@
+import type { Config } from 'tailwindcss'
+
+const config: Config = {
+ content: [
+ './pages/**/*.{js,ts,jsx,tsx,mdx}',
+ './components/**/*.{js,ts,jsx,tsx,mdx}',
+ './app/**/*.{js,ts,jsx,tsx,mdx}',
+ ],
+ theme: {},
+ plugins: [],
+}
+export default config
diff --git a/accelerate/nextjs-starter/tsconfig.json b/accelerate/nextjs-starter/tsconfig.json
new file mode 100644
index 000000000000..23f7338a48f6
--- /dev/null
+++ b/accelerate/nextjs-starter/tsconfig.json
@@ -0,0 +1,32 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./*"]
+ }
+ },
+ "ts-node": {
+ "compilerOptions": {
+ "module": "commonjs"
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/accelerate/nuxtjs-starter/.gitignore b/accelerate/nuxtjs-starter/.gitignore
new file mode 100644
index 000000000000..4a7f73a2ed0d
--- /dev/null
+++ b/accelerate/nuxtjs-starter/.gitignore
@@ -0,0 +1,24 @@
+# Nuxt dev/build outputs
+.output
+.data
+.nuxt
+.nitro
+.cache
+dist
+
+# Node dependencies
+node_modules
+
+# Logs
+logs
+*.log
+
+# Misc
+.DS_Store
+.fleet
+.idea
+
+# Local env files
+.env
+.env.*
+!.env.example
diff --git a/accelerate/nuxtjs-starter/README.md b/accelerate/nuxtjs-starter/README.md
new file mode 100644
index 000000000000..44518633e532
--- /dev/null
+++ b/accelerate/nuxtjs-starter/README.md
@@ -0,0 +1,109 @@
+# Prisma Accelerate Example: Nuxt.js Starter
+
+## Introduction
+The quote generator retrieves the most recently added quote with and without caching enabled from a predefined set of quotes. In the context of your Nuxtjs application, the quote generator is a service that provides quotes, with some caching strategies applied to optimize performance and reduce the load on the database.
+
+## General Steps of the Quote Generator:
+- Fetch a quote: Retrieves the most recently added quote with and without caching enabled.
+- Apply caching strategy: Depending on the request, it may apply different caching strategies (e.g., TTL, SWR, TTL+SWR or no caching).
+- Return the quote: The selected quote is returned, along with metadata about the caching status and other relevant information.
+
+This project showcases how to use Prisma ORM with Prisma Accelerate in a Nuxt.js application. It [demonstrates](./server/api/quotes.ts#L11-27) every available [caching strategy in Accelerate](https://www.prisma.io/docs/accelerate/caching#cache-strategies).
+
+## Prerequisites
+
+To successfully run the project, you will need the following:
+
+- The **connection string** of a publicly accessible database
+- Your **Accelerate connection string** (containing your **Accelerate API key**) which you can get by enabling Accelerate in a project in your [Prisma Data Platform](https://pris.ly/pdp) account (learn more in the [docs](https://www.prisma.io/docs/platform/concepts/environments#api-keys))
+
+## Getting started
+
+### 1. Clone the repository
+
+Clone the repository, navigate into it and install dependencies:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+cd prisma-examples/accelerate/nuxtjs-starter
+npm install
+```
+
+### 2. Configure environment variables
+
+Create a `.env` in the root of the project directory:
+
+```bash
+touch .env
+```
+
+Now, open the `.env` file and set the `DATABASE_URL` and `DIRECT_URL` environment variables with the values of your Postgres connection string and your Accelerate connection string:
+
+```bash
+# .env
+
+# Accelerate connection string (used for queries by Prisma Client)
+DATABASE_URL="__YOUR_ACCELERATE_CONNECTION_STRING__"
+
+# Database connection string (used for migrations by Prisma Migrate)
+DIRECT_URL="__YOUR_DATABASE_CONNECTION_STRING__"
+
+NUXT_PUBLIC_URL="http://localhost:3000/"
+```
+
+Note that `__YOUR_DATABASE_CONNECTION_STRING__` and `__YOUR_ACCELERATE_CONNECTION_STRING__` are placeholder values that you need to replace with the values of your database and Accelerate connection strings. Notice that the Accelerate connection string has the following structure: `prisma://accelerate.prisma-data.net/?api_key=__YOUR_ACCELERATE_API_KEY__`.
+
+### 3. Run a migration to create the `Quotes` table and seed the database
+
+The Prisma schema file contains a single `Quotes` model. You can map this model to the database and create the corresponding `Quotes` table using the following command:
+
+```
+npx prisma migrate dev --name init
+```
+
+You now have an empty `Quotes` table in your database. Next, run the [seed script](./prisma/seed.js) to create some sample records in the table:
+
+```
+npx prisma db seed
+```
+
+### 4. Generate Prisma Client for Accelerate
+
+When using Accelerate, Prisma Client doesn't need a query engine. That's why you should generate it as follows:
+
+```
+npx prisma generate --no-engine
+```
+
+### 5. Start the app
+
+You can run the app with the following command:
+
+```
+npm run dev
+```
+
+Starting the development server will skip the prompt to install the Prisma CLI and create a
+Prisma Schema as they already exist. It will also skip the prompt to migrate the schema changes to the database, as the migrations folder already exists from step 3. You would then need to agree to the prompt to install and access Prisma Studio from the Nuxt Devtools:
+
+```
+Do you want to view and edit your data by installing Prisma Studio in Nuxt DevTools? › (Y/n)
+ Select Y (yes) to install and use Prisma Studio in Nuxt Devtools.
+```
+
+### 6. Launch the app in the browser
+Open the browser and navigate to http://localhost:3000
+
+
+
+You can see the performance and other stats (e.g. cache/hit) for the different Accelerate cache strategies at the bottom of the UI:
+
+## Resources
+
+- [Accelerate Speed Test](https://accelerate-speed-test.vercel.app/)
+- [Accelerate documentation](https://www.prisma.io/docs/accelerate)
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/accelerate/nuxtjs-starter/app.vue b/accelerate/nuxtjs-starter/app.vue
new file mode 100644
index 000000000000..8c415a8a0af2
--- /dev/null
+++ b/accelerate/nuxtjs-starter/app.vue
@@ -0,0 +1,35 @@
+
+
+
+
+ Accelerated Quotes
+
+
+
+ Retrieves the most recently added quote with and without caching enabled
+
+
+
+ Refresh
+
+
+
+
+
+
+
+
+
diff --git a/accelerate/nuxtjs-starter/components/Quote.vue b/accelerate/nuxtjs-starter/components/Quote.vue
new file mode 100644
index 000000000000..b33547b7be3a
--- /dev/null
+++ b/accelerate/nuxtjs-starter/components/Quote.vue
@@ -0,0 +1,86 @@
+
+
+
+
Loading...
+
+ ID {{ id }} ⸺ '"
+
+ "'
+
+
+
+ Created At ⸺
+ {{ formatDate(createdAt) }}
+
+
+
+
+
+ Cache Node Region ⸺
+
+ {{ findIATA(region)?.city || region }}
+
+
+
+
+ Cached Modified at ⸺
+
+ {{ formatDate(lastModified) }}
+
+
+
+
+ Cache status ⸺
+
+ {{ cacheStatus?.toUpperCase() }}
+ {{ cacheStatus === 'swr' || cacheStatus === 'ttl'
+ ? ' CACHE HIT'
+ : '' }}
+
+
+
+
+ Time taken: {{ result.time }}ms
+
+
+
+
No data available
+
+
+
+
+
+
\ No newline at end of file
diff --git a/accelerate/nuxtjs-starter/components/QuoteWrapper.vue b/accelerate/nuxtjs-starter/components/QuoteWrapper.vue
new file mode 100644
index 000000000000..9c5bfd67b1a2
--- /dev/null
+++ b/accelerate/nuxtjs-starter/components/QuoteWrapper.vue
@@ -0,0 +1,27 @@
+
+
+
+
+ {{ title }}
+
+
+
+ {{ type }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/accelerate/nuxtjs-starter/demo.gif b/accelerate/nuxtjs-starter/demo.gif
new file mode 100644
index 000000000000..b62fb1a322ac
Binary files /dev/null and b/accelerate/nuxtjs-starter/demo.gif differ
diff --git a/accelerate/nuxtjs-starter/lib/prisma.ts b/accelerate/nuxtjs-starter/lib/prisma.ts
new file mode 100644
index 000000000000..86fe6919142c
--- /dev/null
+++ b/accelerate/nuxtjs-starter/lib/prisma.ts
@@ -0,0 +1,16 @@
+import { PrismaClient } from '@prisma/client'
+import { withAccelerate } from '@prisma/extension-accelerate'
+
+const prismaClientSingleton = () => {
+ return new PrismaClient().$extends(withAccelerate())
+}
+
+declare const globalThis: {
+ prismaGlobal: ReturnType;
+} & typeof global;
+
+const prisma = globalThis.prismaGlobal ?? prismaClientSingleton()
+
+export default prisma
+
+if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma
diff --git a/accelerate/nuxtjs-starter/lib/types/index.ts b/accelerate/nuxtjs-starter/lib/types/index.ts
new file mode 100644
index 000000000000..b7cf3178147f
--- /dev/null
+++ b/accelerate/nuxtjs-starter/lib/types/index.ts
@@ -0,0 +1,33 @@
+export type CacheStrategy =
+ | {
+ ttl: number;
+ swr: number;
+ }
+ | {
+ ttl: number;
+ }
+ | {
+ swr: number;
+ };
+
+export type AccelerateInfo = {
+ cacheStatus: "ttl" | "swr" | "miss" | "none";
+ lastModified: Date;
+ region: string;
+ requestId: string;
+ signature: string;
+};
+
+export type Quote = {
+ id: number;
+ quote: string;
+ createdAt: string;
+};
+
+export type QuoteResult = {
+ data: Quote;
+ info: AccelerateInfo;
+ time: number;
+};
+
+export type QuoteCacheType = "SWR" | "TTL" | "No caching" | "TTL + SWR";
diff --git a/accelerate/nuxtjs-starter/lib/utils/helper.ts b/accelerate/nuxtjs-starter/lib/utils/helper.ts
new file mode 100644
index 000000000000..bce77b061404
--- /dev/null
+++ b/accelerate/nuxtjs-starter/lib/utils/helper.ts
@@ -0,0 +1,10 @@
+export async function delay(ms: number): Promise {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, ms);
+ });
+ }
+
+ export const HOST = process.env.NUXT_PUBLIC_URL ?? "http://localhost:3000/";
+
\ No newline at end of file
diff --git a/accelerate/nuxtjs-starter/lib/utils/query.ts b/accelerate/nuxtjs-starter/lib/utils/query.ts
new file mode 100644
index 000000000000..072e2c476539
--- /dev/null
+++ b/accelerate/nuxtjs-starter/lib/utils/query.ts
@@ -0,0 +1,25 @@
+import prisma from "../prisma";
+import type { CacheStrategy } from "../types";
+
+export const getQuotes = async (strategy?: CacheStrategy) => {
+ const start = Date.now();
+
+ const result = await prisma.quotes
+ .findMany({
+ // You can find the `cacheStrategy` options [here](https://www.prisma.io/docs/accelerate/caching#cache-strategies). The `cacheStrategy` can also be undefined, which would mean only connection pooling is being used.
+ cacheStrategy: strategy,
+ orderBy: {
+ id: "desc",
+ },
+ take: 1,
+ })
+ .withAccelerateInfo();
+
+
+ return {
+ data: result?.data?.[0],
+ info: result.info,
+ time: Date.now() - start,
+ };
+};
+
diff --git a/accelerate/nuxtjs-starter/nuxt.config.ts b/accelerate/nuxtjs-starter/nuxt.config.ts
new file mode 100644
index 000000000000..b69895292f04
--- /dev/null
+++ b/accelerate/nuxtjs-starter/nuxt.config.ts
@@ -0,0 +1,8 @@
+// https://nuxt.com/docs/api/configuration/nuxt-config
+export default defineNuxtConfig({
+ modules: ["@prisma/nuxt", "tailwindcss", "@nuxtjs/tailwindcss"],
+ prisma:{
+ autoSetupPrisma: false,
+ },
+ devtools: { enabled: true }
+})
\ No newline at end of file
diff --git a/accelerate/nuxtjs-starter/package.json b/accelerate/nuxtjs-starter/package.json
new file mode 100644
index 000000000000..5356e8e5d9ed
--- /dev/null
+++ b/accelerate/nuxtjs-starter/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "nuxt-app",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "nuxt build",
+ "dev": "nuxt dev",
+ "generate": "nuxt generate",
+ "preview": "nuxt preview",
+ "postinstall": "nuxt prepare"
+ },
+ "dependencies": {
+ "@nuxtjs/tailwindcss": "6.14.0",
+ "@prisma/extension-accelerate": "2.0.2",
+ "@prisma/nuxt": "0.3.0",
+ "nuxt": "3.17.6",
+ "openflights-cached": "1.3.15",
+ "tsx": "4.20.6",
+ "zod": "3.25.76"
+ },
+ "devDependencies": {
+ "@prisma/client": "6.9.0",
+ "prisma": "6.9.0"
+ },
+ "prisma": {
+ "seed": "tsx prisma/seed.ts"
+ }
+}
diff --git a/accelerate/nuxtjs-starter/pages/index.vue b/accelerate/nuxtjs-starter/pages/index.vue
new file mode 100644
index 000000000000..a358a13584c5
--- /dev/null
+++ b/accelerate/nuxtjs-starter/pages/index.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/accelerate/nuxtjs-starter/prisma/schema.prisma b/accelerate/nuxtjs-starter/prisma/schema.prisma
new file mode 100644
index 000000000000..5d94e01214ed
--- /dev/null
+++ b/accelerate/nuxtjs-starter/prisma/schema.prisma
@@ -0,0 +1,18 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
+}
+
+model Quotes {
+ id Int @id @default(autoincrement())
+ quote String
+ createdAt DateTime @default(now())
+}
diff --git a/accelerate/nuxtjs-starter/prisma/seed.ts b/accelerate/nuxtjs-starter/prisma/seed.ts
new file mode 100644
index 000000000000..84e5cb002cf2
--- /dev/null
+++ b/accelerate/nuxtjs-starter/prisma/seed.ts
@@ -0,0 +1,62 @@
+import { PrismaClient } from "@prisma/client";
+
+const prisma = new PrismaClient();
+
+const main = async () => {
+ console.time("Seeding complete 🌱");
+
+ await prisma.quotes.createMany({
+ skipDuplicates: true,
+ data: [
+ { quote: "The only way to do great work is to love what you do." },
+ {
+ quote:
+ "Success is not final, failure is not fatal: It is the courage to continue that counts.",
+ },
+ { quote: "In the middle of every difficulty lies opportunity." },
+ { quote: "Believe you can and you're halfway there." },
+ { quote: "The best way to predict the future is to create it." },
+ { quote: "Don't watch the clock; do what it does. Keep going." },
+ { quote: "The only thing we have to fear is fear itself." },
+ { quote: "The journey of a thousand miles begins with a single step." },
+ { quote: "If you can dream it, you can achieve it." },
+ { quote: "Innovation distinguishes between a leader and a follower." },
+ {
+ quote:
+ "The greatest glory in living lies not in never falling, but in rising every time we fall.",
+ },
+ { quote: "You miss 100% of the shots you don't take." },
+ {
+ quote:
+ "The only limit to our realization of tomorrow will be our doubts of today.",
+ },
+ { quote: "Change your thoughts and you change your world." },
+ {
+ quote:
+ "To be yourself in a world that is constantly trying to make you something else is the greatest accomplishment.",
+ },
+ {
+ quote:
+ "The only thing standing between you and your goal is the story you keep telling yourself as to why you can't achieve it.",
+ },
+ { quote: "Life is 10% what happens to us and 90% how we react to it." },
+ {
+ quote:
+ "The future belongs to those who believe in the beauty of their dreams.",
+ },
+ {
+ quote:
+ "Do not wait for the perfect moment, take the moment and make it perfect.",
+ },
+ { quote: "The only source of knowledge is experience." },
+ ],
+ });
+
+ console.timeEnd("Seeding complete 🌱");
+};
+
+main()
+ .then(() => {
+ console.log("Process completed");
+ })
+ .catch((e) => console.log(e));
diff --git a/accelerate/nuxtjs-starter/public/favicon.ico b/accelerate/nuxtjs-starter/public/favicon.ico
new file mode 100644
index 000000000000..18993ad91cfd
Binary files /dev/null and b/accelerate/nuxtjs-starter/public/favicon.ico differ
diff --git a/accelerate/nuxtjs-starter/server/api/quotes.ts b/accelerate/nuxtjs-starter/server/api/quotes.ts
new file mode 100644
index 000000000000..d34667aa4ddd
--- /dev/null
+++ b/accelerate/nuxtjs-starter/server/api/quotes.ts
@@ -0,0 +1,32 @@
+import { defineEventHandler, getQuery, createError } from 'h3';
+import { z } from 'zod';
+import { getQuotes } from '@/lib/utils/query';
+
+
+export default defineEventHandler(async (event) => {
+
+ const { cache } = getQuery(event);
+
+ const parser = z.enum(["TTL", "SWR", "BOTH", "NONE"]);
+ const parsedOutput = await parser.safeParseAsync(cache);
+
+ if (!parsedOutput.success) {
+ throw createError({
+ statusCode: 400,
+ statusMessage: "Invalid search parameter."
+ });
+ }
+
+ let map = new Map();
+
+ map.set("TTL", { ttl: 30 });
+ map.set("SWR", { swr: 30 });
+ map.set("BOTH", { ttl: 30, swr: 60 });
+ map.set("NONE", undefined);
+
+ const data = await getQuotes(map.get(parsedOutput.data));
+
+ return data;
+});
+
+
diff --git a/accelerate/nuxtjs-starter/server/tsconfig.json b/accelerate/nuxtjs-starter/server/tsconfig.json
new file mode 100644
index 000000000000..fdbd5f2c2525
--- /dev/null
+++ b/accelerate/nuxtjs-starter/server/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "../.nuxt/tsconfig.server.json",
+ "exclude": ["../prisma/seed.js"]
+}
diff --git a/accelerate/nuxtjs-starter/tsconfig.json b/accelerate/nuxtjs-starter/tsconfig.json
new file mode 100644
index 000000000000..a746f2a70c28
--- /dev/null
+++ b/accelerate/nuxtjs-starter/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ // https://nuxt.com/docs/guide/concepts/typescript
+ "extends": "./.nuxt/tsconfig.json"
+}
diff --git a/accelerate/remix-starter/.env.example b/accelerate/remix-starter/.env.example
new file mode 100644
index 000000000000..5c8813b77c04
--- /dev/null
+++ b/accelerate/remix-starter/.env.example
@@ -0,0 +1,3 @@
+DIRECT_DATABASE_URL="__YOUR_DATABASE_CONNECTION_STRING__"
+DATABASE_URL="__YOUR_ACCELERATE_CONNECTION_STRING__"
+NODE_ENV="development"
\ No newline at end of file
diff --git a/accelerate/remix-starter/.eslintignore b/accelerate/remix-starter/.eslintignore
new file mode 100644
index 000000000000..67191efbb0b9
--- /dev/null
+++ b/accelerate/remix-starter/.eslintignore
@@ -0,0 +1,7 @@
+.cache
+build
+public/build
+app/styles
+dist/
+node_modules
+api/
diff --git a/accelerate/remix-starter/.eslintrc b/accelerate/remix-starter/.eslintrc
new file mode 100644
index 000000000000..c22f538460f1
--- /dev/null
+++ b/accelerate/remix-starter/.eslintrc
@@ -0,0 +1,68 @@
+{
+ "parser": "@typescript-eslint/parser",
+ "globals": {
+ "module": true,
+ "require": true,
+ "process": true,
+ "exports": true
+ },
+ "settings": {
+ "react": {
+ "version": "detect"
+ },
+ "formComponents": ["Form"],
+ "linkComponents": [
+ { "name": "Link", "linkAttribute": "to" },
+ { "name": "NavLink", "linkAttribute": "to" }
+ ]
+ },
+ "plugins": [
+ "prettier",
+ "@typescript-eslint",
+ "jsx-a11y",
+ "import",
+ "react",
+ "react-hooks",
+ "lodash"
+ ],
+ "extends": [
+ "eslint:recommended",
+ "prettier",
+ "plugin:prettier/recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:jsx-a11y/recommended",
+ "plugin:import/recommended",
+ "plugin:import/typescript",
+ "plugin:react/jsx-runtime",
+ "plugin:react/recommended",
+ "plugin:react-hooks/recommended",
+ "@remix-run/eslint-config/node"
+ ],
+ "rules": {
+ "lodash/import-scope": [2, "method"],
+ "prettier/prettier": "error",
+ "import/no-unresolved": "off",
+ "@typescript-eslint/no-unused-vars": [
+ "error",
+ { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }
+ ],
+ "jsx-a11y/anchor-is-valid": [
+ "error",
+ {
+ "components": ["Link", "NavLink"],
+ "specialLink": ["to"]
+ }
+ ],
+ "react/boolean-prop-naming": "error",
+ "react/react-in-jsx-scope": "off",
+ "react/button-has-type": "error",
+ "react/jsx-no-target-blank": [
+ "error",
+ {
+ "warnOnSpreadAttributes": true,
+ "links": true,
+ "forms": true
+ }
+ ]
+ }
+}
diff --git a/accelerate/remix-starter/.gitignore b/accelerate/remix-starter/.gitignore
new file mode 100644
index 000000000000..1e76147d5ced
--- /dev/null
+++ b/accelerate/remix-starter/.gitignore
@@ -0,0 +1,12 @@
+node_modules
+.cache
+.output
+build
+public/build
+api/*
+.env
+test-results/
+playwright-report/
+.eslintcache
+
+!.env.example
\ No newline at end of file
diff --git a/accelerate/remix-starter/.npmrc b/accelerate/remix-starter/.npmrc
new file mode 100644
index 000000000000..dc48c97ba2c6
--- /dev/null
+++ b/accelerate/remix-starter/.npmrc
@@ -0,0 +1,2 @@
+auto-install-peers=false
+shamefully-hoist=true
diff --git a/accelerate/remix-starter/.prettierrc b/accelerate/remix-starter/.prettierrc
new file mode 100644
index 000000000000..bf357fbbc081
--- /dev/null
+++ b/accelerate/remix-starter/.prettierrc
@@ -0,0 +1,3 @@
+{
+ "trailingComma": "all"
+}
diff --git a/accelerate/remix-starter/.tool-versions b/accelerate/remix-starter/.tool-versions
new file mode 100644
index 000000000000..7d41de14071b
--- /dev/null
+++ b/accelerate/remix-starter/.tool-versions
@@ -0,0 +1 @@
+nodejs 22.16.0
diff --git a/accelerate/remix-starter/Prisma-Studio-Image.png b/accelerate/remix-starter/Prisma-Studio-Image.png
new file mode 100644
index 000000000000..9180399bd1c7
Binary files /dev/null and b/accelerate/remix-starter/Prisma-Studio-Image.png differ
diff --git a/accelerate/remix-starter/README.md b/accelerate/remix-starter/README.md
new file mode 100644
index 000000000000..4e31fdc08920
--- /dev/null
+++ b/accelerate/remix-starter/README.md
@@ -0,0 +1,103 @@
+# Prisma Accelerate Example: Remix Starter
+
+This project showcases how to use Prisma ORM with Prisma Accelerate in a Remix application. It [demonstrates](./app/routes/_index.tsx#L10-13) every available [caching strategy in Accelerate](https://www.prisma.io/docs/data-platform/accelerate/concepts#cache-strategies).
+
+## Prerequisites
+
+To successfully run the project, you will need the following:
+
+- The **connection string** of a publicly accessible database.
+- Your **Accelerate connection string** (containing your **Accelerate API key**) which you can get by enabling Accelerate in a project in your [Prisma Data Platform](https://pris.ly/pdp) account (learn more in the [docs](https://www.prisma.io/docs/platform/concepts/environments#api-keys)).
+
+## Getting started
+
+### 1. Clone the repository
+
+Clone the repository, navigate into it and install dependencies:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+cd prisma-examples/accelerate/remix-starter
+npm install
+```
+
+### 2. Configure environment variables
+
+Copy the `.env.example` env file in the root of the project directory:
+
+```bash
+cp .env.example .env
+```
+
+Now, open the `.env` file and set the `DIRECT_DATABASE_URL` and `DATABASE_URL` environment variables with the values of your connection string and your Accelerate connection string respectively:
+
+```bash
+# .env
+
+# Accelerate connection string (used for queries by Prisma Client)
+DATABASE_URL="__YOUR_ACCELERATE_CONNECTION_STRING__"
+
+# Database connection string (used for migrations by Prisma Migrate)
+DIRECT_DATABASE_URL="__YOUR_DATABASE_CONNECTION_STRING__"
+
+```
+
+Note that `__YOUR_DATABASE_CONNECTION_STRING__` and `__YOUR_ACCELERATE_CONNECTION_STRING__` are placeholder values that you need to replace with the values of your database and Accelerate connection strings. Notice that the Accelerate connection string has the following structure: `prisma://accelerate.prisma-data.net/?api_key=__YOUR_ACCELERATE_API_KEY__`.
+
+### 3. Run a migration to create the `Quotes` table and seed the database
+
+The Prisma schema file contains a single `Quotes` model. You can map this model to the database and create the corresponding `Quotes` table using the following command:
+
+```
+npx prisma migrate dev --name init
+```
+
+You now have an empty `Quotes` table in your database. Next, run the [seed script](./prisma/seed.ts) to create some sample records in the table:
+
+```
+npx prisma db seed
+```
+
+### 4. Generate Prisma Client for Accelerate
+
+When using Accelerate, Prisma Client doesn't need a query engine. That's why you should generate it as follows:
+
+```
+npx prisma generate --no-engine
+```
+
+### 5. Start the app
+
+You can run the app with the following command:
+
+```
+npm run dev
+```
+
+The application will start on PORT 5173 and you should be able to see the performance and other stats (e.g. cache/hit) for the different Accelerate cache strategies at the bottom of the UI:
+
+
+
+This application queries the most recent Quote with all the different cache strategies available in Accelerate.
+
+Optionally, to add your own quote and see the caching strategies in action, you can add a new quote through Prisma Studio by running the following command:
+
+```
+npx prisma studio
+```
+
+Once the Prisma Studio is running, you can add a new quote by clicking on the `Quotes` table and then the `Add Record` button as shown in the screenshot below.
+
+
+
+After adding a new record, you can refresh the Remix application to see the new quote and the caching strategies in action.
+
+## Resources
+
+- [Accelerate Speed Test](https://accelerate-speed-test.vercel.app/)
+- [Accelerate documentation](https://www.prisma.io/docs/accelerate)
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/accelerate/remix-starter/Remix-accelerate.gif b/accelerate/remix-starter/Remix-accelerate.gif
new file mode 100644
index 000000000000..e5095d57df55
Binary files /dev/null and b/accelerate/remix-starter/Remix-accelerate.gif differ
diff --git a/accelerate/remix-starter/app/components/Quote/Quote.tsx b/accelerate/remix-starter/app/components/Quote/Quote.tsx
new file mode 100644
index 000000000000..b71c1cee2b77
--- /dev/null
+++ b/accelerate/remix-starter/app/components/Quote/Quote.tsx
@@ -0,0 +1,77 @@
+/* eslint-disable react/prop-types */
+import { QuoteWrapper } from "./QuoteWrapper";
+import { QuoteCacheType, QuoteResult } from "./../../lib/types";
+import pkg from "openflights-cached";
+const { findIATA } = pkg;
+
+export const Quote: React.FC<{
+ title: string;
+ type: QuoteCacheType;
+ result: QuoteResult;
+}> = ({ title, type, result }) => {
+ const [{ id, quote, createdAt }, { cacheStatus, region, lastModified }] = [
+ result.data,
+ result.info,
+ ];
+
+ return (
+
+
+
+ ID {id} ⸺ {'"'}
+ {quote}
+ {'"'}
+
+
+
+ Created At ⸺
+ {new Date(createdAt).toLocaleString("en-US")}
+
+
+
+
+
+
+
+ Cache Node Region ⸺
+
+ {findIATA(region)?.city ?? region}
+
+
+
+
+ Cached Modified at ⸺
+
+ {new Date(lastModified).toLocaleString("en-US")}
+
+
+
+
+ Cache status ⸺
+
+ {cacheStatus
+ .toUpperCase()
+ .concat(
+ cacheStatus === "swr" || cacheStatus === "ttl"
+ ? " CACHE HIT"
+ : "",
+ )}
+
+
+
+
+ Time taken: {result.time}ms
+
+
+
+
+
+ );
+};
diff --git a/accelerate/remix-starter/app/components/Quote/QuoteWrapper.tsx b/accelerate/remix-starter/app/components/Quote/QuoteWrapper.tsx
new file mode 100644
index 000000000000..97e731d18e03
--- /dev/null
+++ b/accelerate/remix-starter/app/components/Quote/QuoteWrapper.tsx
@@ -0,0 +1,24 @@
+/* eslint-disable react/prop-types */
+import { QuoteCacheType } from "../../lib/types";
+import { ReactNode } from "react";
+
+export const QuoteWrapper: React.FC<{
+ title: string;
+ type: QuoteCacheType;
+ children: ReactNode;
+}> = ({ title, type, children }) => {
+ return (
+
+
+
+ {title}
+
+
+
+ {type}
+
+
+
{children}
+
+ );
+};
diff --git a/accelerate/remix-starter/app/components/Quote/Quotes.tsx b/accelerate/remix-starter/app/components/Quote/Quotes.tsx
new file mode 100644
index 000000000000..83e8e3ef94ce
--- /dev/null
+++ b/accelerate/remix-starter/app/components/Quote/Quotes.tsx
@@ -0,0 +1,21 @@
+// app/components/Quotes.tsx
+import { Quote } from "./Quote";
+import { QuoteResult } from "~/lib/types";
+
+interface QuotesProps {
+ ttl: QuoteResult;
+ swr: QuoteResult;
+ both: QuoteResult;
+ none: QuoteResult;
+}
+
+export default function Quotes({ ttl, swr, both, none }: QuotesProps) {
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/accelerate/remix-starter/app/components/Quote/RefreshQuote.tsx b/accelerate/remix-starter/app/components/Quote/RefreshQuote.tsx
new file mode 100644
index 000000000000..8a9ffd66e3d5
--- /dev/null
+++ b/accelerate/remix-starter/app/components/Quote/RefreshQuote.tsx
@@ -0,0 +1,17 @@
+import { Toaster } from "react-hot-toast";
+
+export const RefreshQuote = () => {
+ return (
+ <>
+
+
+ window.location.reload()}
+ className="focus:outline-none text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"
+ >
+ Refresh
+
+ >
+ );
+};
diff --git a/accelerate/remix-starter/app/data/query.server.ts b/accelerate/remix-starter/app/data/query.server.ts
new file mode 100644
index 000000000000..51b58f7914ae
--- /dev/null
+++ b/accelerate/remix-starter/app/data/query.server.ts
@@ -0,0 +1,23 @@
+import prisma from "./utils/prisma.server";
+import { CacheStrategy } from "../lib/types";
+
+export const getQuotes = async (strategy?: CacheStrategy) => {
+ const start = Date.now();
+
+ const result = await prisma.quotes
+ .findMany({
+ // You can find the `cacheStrategy` options [here](https://www.prisma.io/docs/accelerate/caching#cache-strategies). The `cacheStrategy` can also be undefined, which would mean only connection pooling is being used.
+ cacheStrategy: strategy,
+ orderBy: {
+ id: "desc",
+ },
+ take: 1,
+ })
+ .withAccelerateInfo();
+
+ return {
+ data: result?.data?.[0],
+ info: result.info,
+ time: Date.now() - start,
+ };
+};
diff --git a/accelerate/remix-starter/app/data/quotes.server.ts b/accelerate/remix-starter/app/data/quotes.server.ts
new file mode 100644
index 000000000000..2d6d019173a2
--- /dev/null
+++ b/accelerate/remix-starter/app/data/quotes.server.ts
@@ -0,0 +1,28 @@
+import { getQuotes } from "./query.server";
+
+export async function getQuotesFromDB(cacheStrategy: string) {
+ const map = new Map();
+
+ // When TTL is selected
+ map.set("TTL", {
+ ttl: 30,
+ });
+
+ // When SWR is selected
+ map.set("SWR", {
+ swr: 30,
+ });
+
+ // When TTL + SWR is selected
+ map.set("BOTH", {
+ ttl: 30,
+ swr: 60,
+ });
+
+ // This ensures no caching is performed and only the Accelerate connection pool is used
+ map.set("NONE", undefined);
+
+ const data = await getQuotes(map.get(cacheStrategy));
+
+ return data;
+}
diff --git a/accelerate/remix-starter/app/data/utils/formatZodErrors.server.ts b/accelerate/remix-starter/app/data/utils/formatZodErrors.server.ts
new file mode 100644
index 000000000000..bb6c785a64d7
--- /dev/null
+++ b/accelerate/remix-starter/app/data/utils/formatZodErrors.server.ts
@@ -0,0 +1,11 @@
+import capitalize from "lodash/capitalize.js";
+import type { ZodError } from "zod";
+
+export function formatZodErrors(zodError: ZodError) {
+ return Object.fromEntries(
+ zodError.issues.map((errorObj) => [
+ errorObj.path,
+ capitalize(errorObj.message),
+ ]),
+ );
+}
diff --git a/accelerate/remix-starter/app/data/utils/prisma.server.ts b/accelerate/remix-starter/app/data/utils/prisma.server.ts
new file mode 100644
index 000000000000..293f661397bd
--- /dev/null
+++ b/accelerate/remix-starter/app/data/utils/prisma.server.ts
@@ -0,0 +1,38 @@
+/* eslint-disable no-var */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { PrismaClient } from "@prisma/client";
+import { withAccelerate } from "@prisma/extension-accelerate";
+import { SERVER_ENV } from "~/env/envFlags.server";
+
+function buildClient() {
+ const client = new PrismaClient().$extends(withAccelerate());
+
+ return client;
+}
+
+/**
+ * The type of the PrismaClient with extensions
+ */
+export type PrismaClientType = ReturnType;
+
+let prisma: PrismaClientType;
+
+declare global {
+ var __prisma: PrismaClientType | undefined;
+}
+
+// This is needed because in development we don't want to restart
+// the server with every change, but we want to make sure we don't
+// create a new connection to the DB with every change either.
+if (SERVER_ENV.NODE_ENV === "production") {
+ prisma = buildClient();
+ prisma.$connect();
+} else {
+ if (!global.__prisma) {
+ global.__prisma = buildClient();
+ global.__prisma.$connect();
+ }
+ prisma = global.__prisma;
+}
+
+export default prisma;
diff --git a/accelerate/remix-starter/app/data/utils/types.ts b/accelerate/remix-starter/app/data/utils/types.ts
new file mode 100644
index 000000000000..66818d7a67de
--- /dev/null
+++ b/accelerate/remix-starter/app/data/utils/types.ts
@@ -0,0 +1,5 @@
+export type GenericDataError = Record;
+
+export type DataResult =
+ | { data: DataType; errors: null }
+ | { data: null; errors: GenericDataError };
diff --git a/accelerate/remix-starter/app/entry.client.tsx b/accelerate/remix-starter/app/entry.client.tsx
new file mode 100644
index 000000000000..442da4f8a80d
--- /dev/null
+++ b/accelerate/remix-starter/app/entry.client.tsx
@@ -0,0 +1,12 @@
+import { RemixBrowser } from "@remix-run/react";
+import { startTransition, StrictMode } from "react";
+import { hydrateRoot } from "react-dom/client";
+
+startTransition(() => {
+ hydrateRoot(
+ document,
+
+
+ ,
+ );
+});
diff --git a/accelerate/remix-starter/app/entry.server.tsx b/accelerate/remix-starter/app/entry.server.tsx
new file mode 100644
index 000000000000..38476546d30e
--- /dev/null
+++ b/accelerate/remix-starter/app/entry.server.tsx
@@ -0,0 +1,147 @@
+import { PassThrough } from "node:stream";
+
+import type {
+ AppLoadContext,
+ EntryContext,
+ HandleErrorFunction,
+} from "@remix-run/node";
+import { createReadableStreamFromReadable } from "@remix-run/node";
+import { RemixServer } from "@remix-run/react";
+import { isbot } from "isbot";
+import { renderToPipeableStream } from "react-dom/server";
+
+const ABORT_DELAY = 5_000;
+
+export const handleError: HandleErrorFunction = (
+ error,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ { request, params, context },
+) => {
+ if (!request.signal.aborted) {
+ // Here you can log the error to your preferred error handling service
+ // handleError(error)
+ }
+};
+
+export default function handleRequest(
+ request: Request,
+ responseStatusCode: number,
+ responseHeaders: Headers,
+ remixContext: EntryContext,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ loadContext: AppLoadContext,
+) {
+ return isbot(request.headers.get("user-agent"))
+ ? handleBotRequest(
+ request,
+ responseStatusCode,
+ responseHeaders,
+ remixContext,
+ )
+ : handleBrowserRequest(
+ request,
+ responseStatusCode,
+ responseHeaders,
+ remixContext,
+ );
+}
+
+function handleBotRequest(
+ request: Request,
+ responseStatusCode: number,
+ responseHeaders: Headers,
+ remixContext: EntryContext,
+) {
+ return new Promise((resolve, reject) => {
+ let shellRendered = false;
+ const { pipe, abort } = renderToPipeableStream(
+ ,
+ {
+ onAllReady() {
+ shellRendered = true;
+ const body = new PassThrough();
+ const stream = createReadableStreamFromReadable(body);
+
+ responseHeaders.set("Content-Type", "text/html");
+
+ resolve(
+ new Response(stream, {
+ headers: responseHeaders,
+ status: responseStatusCode,
+ }),
+ );
+
+ pipe(body);
+ },
+ onShellError(error: unknown) {
+ reject(error);
+ },
+ onError(error: unknown) {
+ responseStatusCode = 500;
+ // Log streaming rendering errors from inside the shell. Don't log
+ // errors encountered during initial shell rendering since they'll
+ // reject and get logged in handleDocumentRequest.
+ if (shellRendered) {
+ console.error(error);
+ }
+ },
+ },
+ );
+
+ setTimeout(abort, ABORT_DELAY);
+ });
+}
+
+function handleBrowserRequest(
+ request: Request,
+ responseStatusCode: number,
+ responseHeaders: Headers,
+ remixContext: EntryContext,
+) {
+ return new Promise((resolve, reject) => {
+ let shellRendered = false;
+ const { pipe, abort } = renderToPipeableStream(
+ ,
+ {
+ onShellReady() {
+ shellRendered = true;
+ const body = new PassThrough();
+ const stream = createReadableStreamFromReadable(body);
+
+ responseHeaders.set("Content-Type", "text/html");
+
+ resolve(
+ new Response(stream, {
+ headers: responseHeaders,
+ status: responseStatusCode,
+ }),
+ );
+
+ pipe(body);
+ },
+ onShellError(error: unknown) {
+ reject(error);
+ },
+ onError(error: unknown) {
+ responseStatusCode = 500;
+ // Log streaming rendering errors from inside the shell. Don't log
+ // errors encountered during initial shell rendering since they'll
+ // reject and get logged in handleDocumentRequest.
+ if (shellRendered) {
+ console.error(error);
+ }
+ },
+ },
+ );
+
+ setTimeout(abort, ABORT_DELAY);
+ });
+}
diff --git a/accelerate/remix-starter/app/env/envFlags.server.ts b/accelerate/remix-starter/app/env/envFlags.server.ts
new file mode 100644
index 000000000000..dac50a0581ca
--- /dev/null
+++ b/accelerate/remix-starter/app/env/envFlags.server.ts
@@ -0,0 +1,28 @@
+import z from "zod";
+import { generateErrorMessage } from "zod-error";
+
+export const serverEnvSchema = z.object({
+ DIRECT_DATABASE_URL: z.string(),
+ DATABASE_URL: z.string(),
+ NODE_ENV: z.string(),
+});
+
+export type ServerEnv = z.infer;
+
+/** Zod will filter all the keys not specified on the schema */
+function buildEnv(): ServerEnv {
+ try {
+ return serverEnvSchema.parse(process.env);
+ } catch (error: unknown) {
+ console.error("Warning: invalid server env vars!");
+ console.error(
+ generateErrorMessage((error as z.ZodError).issues, {
+ delimiter: { error: "\n" },
+ }),
+ );
+
+ return {} as ServerEnv;
+ }
+}
+
+export const SERVER_ENV = buildEnv();
diff --git a/accelerate/remix-starter/app/env/globalEnv.ts b/accelerate/remix-starter/app/env/globalEnv.ts
new file mode 100644
index 000000000000..341ff02ea751
--- /dev/null
+++ b/accelerate/remix-starter/app/env/globalEnv.ts
@@ -0,0 +1,41 @@
+import z from "zod";
+import { generateErrorMessage } from "zod-error";
+
+export const globalEnvSchema = z.object({
+ PUBLIC_EXAMPLE: z.string().optional(),
+ EXAMPLE_GLOBAL_FEATURE_FLAG: z
+ .enum(["true", "false"])
+ .optional()
+ .transform((v) => v === "true"),
+});
+
+export type GlobalEnv = z.infer;
+
+/** Zod will filter all the keys not specified on the schema */
+function buildEnv(): GlobalEnv {
+ try {
+ return globalEnvSchema.parse(process.env);
+ } catch (error: unknown) {
+ console.error("Warning: invalid client env vars!");
+ console.error(
+ generateErrorMessage((error as z.ZodError).issues, {
+ delimiter: { error: "\n" },
+ }),
+ );
+
+ return {} as GlobalEnv;
+ }
+}
+
+/**
+ * If we are on a browser environment, we get the vars from the `window` object.
+ * We set this on the root.tsx file on around line 58.
+ *
+ * If we are on a server environment, we just read it from process.env.
+ *
+ * Remember that CLIENT_ENV vars can be accessed from any context.
+ */
+export const GLOBAL_ENV =
+ typeof window === "undefined"
+ ? buildEnv()
+ : (window as unknown as { ENV: GlobalEnv }).ENV;
diff --git a/accelerate/remix-starter/app/env/useFeatureFlags.tsx b/accelerate/remix-starter/app/env/useFeatureFlags.tsx
new file mode 100644
index 000000000000..67c9a46ca3f5
--- /dev/null
+++ b/accelerate/remix-starter/app/env/useFeatureFlags.tsx
@@ -0,0 +1,29 @@
+import { useContext, useMemo } from "react";
+
+import { UserContext } from "../hooks/useUser";
+import { UserFeatureFlags } from "./userFeatureFlags.server";
+import { GLOBAL_ENV, GlobalEnv } from "./globalEnv";
+
+export default function useFeatureFlags() {
+ const userContext = useContext(UserContext);
+
+ return useMemo(
+ () => ({
+ // Check the CLIENT_ENV object for feature flags
+ hasGlobalFeatureFlag: (flag: keyof GlobalEnv): boolean =>
+ !!GLOBAL_ENV[flag],
+ // Get a value from CLIENT_ENV object
+ getGlobalFeatureFlag: (
+ flag: T,
+ ): GlobalEnv[T] => GLOBAL_ENV[flag],
+ // Check the current user feature flags. If there's no user, this returns false, always
+ hasUserFeatureFlag: (flag: keyof UserFeatureFlags): boolean =>
+ !!userContext?.featureFlags?.[flag],
+ // Get the current user feature flag value. If there's no user, this returns undefined, always
+ getUserFeatureFlag: (
+ flag: T,
+ ): UserFeatureFlags[T] | undefined => userContext?.featureFlags?.[flag],
+ }),
+ [userContext?.featureFlags],
+ );
+}
diff --git a/accelerate/remix-starter/app/env/userFeatureFlags.server.ts b/accelerate/remix-starter/app/env/userFeatureFlags.server.ts
new file mode 100644
index 000000000000..bfa1f2d4b5bc
--- /dev/null
+++ b/accelerate/remix-starter/app/env/userFeatureFlags.server.ts
@@ -0,0 +1,10 @@
+import { z } from "zod";
+
+export const UserFeatureFlagsSchema = z
+ .object({
+ EXAMPLE_FEATURE_FLAG: z.boolean().optional(),
+ EXAMPLE_FEATURE_FLAG_STRING: z.string().optional(),
+ })
+ .default({});
+
+export type UserFeatureFlags = z.infer;
diff --git a/accelerate/remix-starter/app/hooks/useRootLoaderData.tsx b/accelerate/remix-starter/app/hooks/useRootLoaderData.tsx
new file mode 100644
index 000000000000..8afaec415576
--- /dev/null
+++ b/accelerate/remix-starter/app/hooks/useRootLoaderData.tsx
@@ -0,0 +1,9 @@
+import { SerializeFrom } from "@remix-run/node";
+import { useRouteLoaderData } from "@remix-run/react";
+import { loader } from "~/root";
+
+export type RootLoaderType = SerializeFrom>>;
+
+export function useRootLoaderData() {
+ return useRouteLoaderData("root")!;
+}
diff --git a/accelerate/remix-starter/app/lib/types/index.tsx b/accelerate/remix-starter/app/lib/types/index.tsx
new file mode 100644
index 000000000000..1fda962ee16b
--- /dev/null
+++ b/accelerate/remix-starter/app/lib/types/index.tsx
@@ -0,0 +1,33 @@
+export type CacheStrategy =
+ | {
+ ttl: number;
+ swr: number;
+ }
+ | {
+ ttl: number;
+ }
+ | {
+ swr: number;
+ };
+
+export type AccelerateInfo = {
+ cacheStatus: "ttl" | "swr" | "miss" | "none";
+ lastModified: string;
+ region: string;
+ requestId: string;
+ signature: string;
+};
+
+export type Quote = {
+ id: number;
+ quote: string;
+ createdAt: string;
+};
+
+export type QuoteResult = {
+ data: Quote;
+ info: AccelerateInfo;
+ time: number;
+};
+
+export type QuoteCacheType = "SWR" | "TTL" | "No caching" | "TTL + SWR";
diff --git a/accelerate/remix-starter/app/root.css b/accelerate/remix-starter/app/root.css
new file mode 100644
index 000000000000..8abdb15c9458
--- /dev/null
+++ b/accelerate/remix-starter/app/root.css
@@ -0,0 +1,76 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 222.2 84% 4.9%;
+
+ --card: 0 0% 100%;
+ --card-foreground: 222.2 84% 4.9%;
+
+ --popover: 0 0% 100%;
+ --popover-foreground: 222.2 84% 4.9%;
+
+ --primary: 222.2 47.4% 11.2%;
+ --primary-foreground: 210 40% 98%;
+
+ --secondary: 210 40% 96.1%;
+ --secondary-foreground: 222.2 47.4% 11.2%;
+
+ --muted: 210 40% 96.1%;
+ --muted-foreground: 215.4 16.3% 46.9%;
+
+ --accent: 210 40% 96.1%;
+ --accent-foreground: 222.2 47.4% 11.2%;
+
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 214.3 31.8% 91.4%;
+ --input: 214.3 31.8% 91.4%;
+ --ring: 222.2 84% 4.9%;
+
+ --radius: 0.5rem;
+ }
+
+ .dark {
+ --background: 222.2 84% 4.9%;
+ --foreground: 210 40% 98%;
+
+ --card: 222.2 84% 4.9%;
+ --card-foreground: 210 40% 98%;
+
+ --popover: 222.2 84% 4.9%;
+ --popover-foreground: 210 40% 98%;
+
+ --primary: 210 40% 98%;
+ --primary-foreground: 222.2 47.4% 11.2%;
+
+ --secondary: 217.2 32.6% 17.5%;
+ --secondary-foreground: 210 40% 98%;
+
+ --muted: 217.2 32.6% 17.5%;
+ --muted-foreground: 215 20.2% 65.1%;
+
+ --accent: 217.2 32.6% 17.5%;
+ --accent-foreground: 210 40% 98%;
+
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 217.2 32.6% 17.5%;
+ --input: 217.2 32.6% 17.5%;
+ --ring: 212.7 26.8% 83.9%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
diff --git a/accelerate/remix-starter/app/root.tsx b/accelerate/remix-starter/app/root.tsx
new file mode 100644
index 000000000000..d5ffc151b210
--- /dev/null
+++ b/accelerate/remix-starter/app/root.tsx
@@ -0,0 +1,127 @@
+import "./root.css";
+
+import { unstable_defineLoader } from "@remix-run/node";
+import {
+ Links,
+ Meta,
+ Outlet,
+ Scripts,
+ ScrollRestoration,
+} from "@remix-run/react";
+import acceptLanguage from "accept-language-parser";
+import React, { useEffect } from "react";
+import { GLOBAL_ENV } from "./env/globalEnv";
+import { useRootLoaderData } from "./hooks/useRootLoaderData";
+import { cn } from "./utils";
+import { getCurrentTheme } from "./web/theme.server";
+
+// Load the locale from the Accept-Language header to later
+// inject it on the app's context
+function localeFromRequest(request: Request): string {
+ const languages = acceptLanguage.parse(
+ request.headers.get("Accept-Language") as string,
+ );
+
+ // If somehow the header is empty, return a default locale
+ if (languages?.length < 1) return "en-us";
+
+ // If there is no region for this locale, just return the country code
+ if (!languages[0].region) return languages[0].code;
+
+ return `${languages[0].code}-${languages[0].region.toLowerCase()}`;
+}
+
+export const loader = unstable_defineLoader(async ({ request }) => {
+ return {
+ locale: localeFromRequest(request),
+ ENV: GLOBAL_ENV,
+ rootTime: new Date().toISOString(),
+ currentTheme: await getCurrentTheme(request),
+ };
+});
+
+function applySystemTheme() {
+ const theme = window.matchMedia("(prefers-color-scheme: dark)").matches
+ ? "dark"
+ : "light";
+ const cl = document.documentElement.classList;
+
+ cl.add(theme);
+}
+
+const applySystemThemeString = `
+ const theme = window.matchMedia("(prefers-color-scheme: dark)").matches
+ ? "dark"
+ : "light";
+ const cl = document.documentElement.classList;
+
+ cl.add(theme);
+`;
+
+export default function App() {
+ const { ENV, currentTheme } = useRootLoaderData();
+
+ useEffect(() => {
+ if (currentTheme === "system") applySystemTheme();
+ }, [currentTheme]);
+
+ return (
+
+
+
+
+
+ );
+}
+
+/**
+ * This will render errors without env vars or any locale
+ * info unfortunately as errors can happen on the root loader.
+ */
+export function ErrorBoundary() {
+ return (
+
+
+
+ );
+}
+
+function Document({
+ children,
+ title,
+ className,
+}: {
+ children: React.ReactNode;
+ title?: string;
+ className?: string;
+}) {
+ return (
+
+
+
+
+
+ {title ? {title} : null}
+
+
+
+
+ {children}
+
+
+
+
+
+ );
+}
diff --git a/accelerate/remix-starter/app/routes/_index.tsx b/accelerate/remix-starter/app/routes/_index.tsx
new file mode 100644
index 000000000000..8a3fc582950d
--- /dev/null
+++ b/accelerate/remix-starter/app/routes/_index.tsx
@@ -0,0 +1,47 @@
+// app/routes/index.tsx
+import { LoaderFunction, json } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import Quotes from "../components/Quote/Quotes";
+import { RefreshQuote } from "../components/Quote/RefreshQuote";
+import { QuoteResult } from "~/lib/types";
+import { getQuotesFromDB } from "../data/quotes.server";
+
+const getQuotes = async () => {
+ const ttl = await getQuotesFromDB("TTL");
+ const swr = await getQuotesFromDB("SWR");
+ const both = await getQuotesFromDB("BOTH");
+ const none = await getQuotesFromDB("NONE");
+
+ return [ttl, swr, both, none];
+};
+
+export const loader: LoaderFunction = async () => {
+ const [ttl, swr, both, none] = await getQuotes();
+ return json({ ttl, swr, both, none });
+};
+
+export default function Index() {
+ const { ttl, swr, both, none } = useLoaderData<{
+ ttl: QuoteResult;
+ swr: QuoteResult;
+ both: QuoteResult;
+ none: QuoteResult;
+ }>();
+
+ return (
+
+
+ Accelerated Quotes
+
+
+
+ Retrieves the most recently added quote with and without caching enabled
+
+
+
+
+
+
+
+ );
+}
diff --git a/accelerate/remix-starter/app/utils.ts b/accelerate/remix-starter/app/utils.ts
new file mode 100644
index 000000000000..365058cebd7d
--- /dev/null
+++ b/accelerate/remix-starter/app/utils.ts
@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/accelerate/remix-starter/app/web/theme.server.ts b/accelerate/remix-starter/app/web/theme.server.ts
new file mode 100644
index 000000000000..8b4a163db0fb
--- /dev/null
+++ b/accelerate/remix-starter/app/web/theme.server.ts
@@ -0,0 +1,36 @@
+import { createCookie, redirect } from "@remix-run/node";
+
+export type ThemeType = "dark" | "light" | "system";
+
+const themeCookie = createCookie("theme", {
+ sameSite: "lax",
+ maxAge: 604_800, // one week,
+});
+
+export async function getCurrentTheme(request: Request): Promise {
+ const cookieHeader = request.headers.get("Cookie");
+ const currentValue = await themeCookie.parse(cookieHeader);
+
+ if (currentValue === "dark" || currentValue === "light") return currentValue;
+
+ return "system";
+}
+
+export async function setTheme(request: Request): Promise {
+ const desiredTheme = (await request.formData()).get("theme");
+ const redirectUrl = request.headers.get("Referer") || "/";
+
+ if (
+ typeof desiredTheme === "string" &&
+ !["dark", "light", "system"].includes(desiredTheme)
+ ) {
+ // Let's not do anything if the theme is invalid
+ return redirect(redirectUrl);
+ }
+
+ return redirect(redirectUrl, {
+ headers: {
+ "Set-Cookie": await themeCookie.serialize(desiredTheme),
+ },
+ });
+}
diff --git a/accelerate/remix-starter/components.json b/accelerate/remix-starter/components.json
new file mode 100644
index 000000000000..806ecf954c13
--- /dev/null
+++ b/accelerate/remix-starter/components.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.js",
+ "css": "app/root.css",
+ "baseColor": "slate",
+ "cssVariables": true
+ },
+ "aliases": {
+ "components": "~/components",
+ "utils": "~/utils"
+ }
+}
\ No newline at end of file
diff --git a/accelerate/remix-starter/package.json b/accelerate/remix-starter/package.json
new file mode 100644
index 000000000000..987294ab28a3
--- /dev/null
+++ b/accelerate/remix-starter/package.json
@@ -0,0 +1,92 @@
+{
+ "name": "remix-accelerate-starter",
+ "private": false,
+ "description": "A Remix Example App with Prisma Accelerate",
+ "license": "MIT",
+ "type": "module",
+ "scripts": {
+ "build": "remix vite:build",
+ "deploy": "npm run ts-run tasks/validateConfig.ts && prisma generate && prisma db push && npm run build",
+ "dev": "remix vite:dev",
+ "lint": "eslint \"**/*.{js,jsx,ts,tsx}\" --cache",
+ "prepare": "[ \"$NODE_ENV\" != \"production\" ] && husky || :",
+ "start": "remix-serve ./build/server/index.js",
+ "test:vitest": "vitest --run",
+ "test:vitest:watch": "vitest",
+ "ts-check": "tsc --project tsconfig.json --noEmit --skipLibCheck",
+ "ts-run": "dotenv ts-node",
+ "validate-env": "npm run ts-run tasks/validateConfig.ts"
+ },
+ "prisma": {
+ "seed": "tsx prisma/seed.ts"
+ },
+ "lint-staged": {
+ "*.{js,ts,jsx,tsx}": "eslint --cache --fix"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "@prisma/extension-accelerate": "2.0.2",
+ "@remix-run/node": "2.16.8",
+ "@remix-run/react": "2.16.8",
+ "@remix-run/serve": "2.16.8",
+ "accept-language-parser": "1.5.0",
+ "clsx": "2.1.1",
+ "date-fns": "4.1.0",
+ "isbot": "5.1.30",
+ "lodash": "4.17.21",
+ "lodash-es": "4.17.21",
+ "openflights-cached": "1.3.15",
+ "postcss": "8.5.6",
+ "react": "19.1.0",
+ "react-dom": "19.1.0",
+ "react-hot-toast": "2.5.2",
+ "remix": "2.16.8",
+ "tailwind-merge": "3.3.1",
+ "tailwindcss-animate": "1.0.7",
+ "zod": "3.25.76",
+ "zod-error": "1.5.0",
+ "zod-form-data": "2.0.7"
+ },
+ "devDependencies": {
+ "@faker-js/faker": "9.9.0",
+ "@remix-run/dev": "2.16.8",
+ "@remix-run/eslint-config": "2.16.8",
+ "@remix-run/testing": "2.16.8",
+ "@testing-library/jest-dom": "6.6.4",
+ "@testing-library/react": "16.3.0",
+ "@types/accept-language-parser": "1.5.8",
+ "@types/lodash": "4.17.20",
+ "@types/node": "22.15.32",
+ "@types/react": "19.1.8",
+ "@types/react-dom": "19.1.6",
+ "@typescript-eslint/eslint-plugin": "8.41.0",
+ "@typescript-eslint/parser": "8.41.0",
+ "@vitest/ui": "3.2.4",
+ "autoprefixer": "10.4.21",
+ "dotenv": "16.6.1",
+ "dotenv-cli": "8.0.0",
+ "eslint": "8.57.1",
+ "eslint-config-prettier": "10.1.8",
+ "eslint-plugin-import": "2.32.0",
+ "eslint-plugin-jsx-a11y": "6.10.2",
+ "eslint-plugin-lodash": "8.0.0",
+ "eslint-plugin-prettier": "5.5.4",
+ "eslint-plugin-react": "7.37.5",
+ "eslint-plugin-react-hooks": "5.2.0",
+ "eslint-plugin-testing-library": "7.6.8",
+ "jsdom": "26.1.0",
+ "lint-staged": "16.2.3",
+ "prettier": "3.6.2",
+ "prisma": "6.9.0",
+ "tailwindcss": "3.4.17",
+ "ts-node": "10.9.2",
+ "tsx": "4.20.6",
+ "typescript": "5.8.2",
+ "vite": "6.3.6",
+ "vite-tsconfig-paths": "5.1.4",
+ "vitest": "3.2.4"
+ },
+ "engines": {
+ "node": "22.16.0"
+ }
+}
diff --git a/accelerate/remix-starter/postcss.config.cjs b/accelerate/remix-starter/postcss.config.cjs
new file mode 100644
index 000000000000..12a703d900da
--- /dev/null
+++ b/accelerate/remix-starter/postcss.config.cjs
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/accelerate/remix-starter/prisma/schema.prisma b/accelerate/remix-starter/prisma/schema.prisma
new file mode 100644
index 000000000000..cda0ee7afb1e
--- /dev/null
+++ b/accelerate/remix-starter/prisma/schema.prisma
@@ -0,0 +1,15 @@
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgres"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_DATABASE_URL")
+}
+
+model Quotes {
+ id Int @id @default(autoincrement())
+ quote String
+ createdAt DateTime @default(now())
+}
diff --git a/accelerate/remix-starter/prisma/seed.ts b/accelerate/remix-starter/prisma/seed.ts
new file mode 100644
index 000000000000..00382053bb84
--- /dev/null
+++ b/accelerate/remix-starter/prisma/seed.ts
@@ -0,0 +1,22 @@
+import { PrismaClient } from "@prisma/client";
+const prisma = new PrismaClient();
+
+async function main() {
+ console.log("Seeding started...");
+ await prisma.quotes.create({
+ data: {
+ quote:
+ "Prisma Accelerate and Remix together make a powerhouse combo, boosting performance and simplifying full-stack development with ease and efficiency.",
+ },
+ });
+ console.log("Seeding completed");
+}
+main()
+ .then(async () => {
+ await prisma.$disconnect();
+ })
+ .catch(async (e) => {
+ console.error(e);
+ await prisma.$disconnect();
+ process.exit(1);
+ });
diff --git a/accelerate/remix-starter/public/favicon.ico b/accelerate/remix-starter/public/favicon.ico
new file mode 100644
index 000000000000..8830cf6821b3
Binary files /dev/null and b/accelerate/remix-starter/public/favicon.ico differ
diff --git a/accelerate/remix-starter/tailwind.config.js b/accelerate/remix-starter/tailwind.config.js
new file mode 100644
index 000000000000..6f2c9c2c2bae
--- /dev/null
+++ b/accelerate/remix-starter/tailwind.config.js
@@ -0,0 +1,71 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ darkMode: ["class"],
+ content: ["./app/**/*.{html,js,jsx,ts,tsx}"],
+ theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
+ extend: {
+ colors: {
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ keyframes: {
+ "accordion-down": {
+ from: { height: 0 },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: 0 },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ },
+ },
+ },
+ plugins: [require("tailwindcss-animate")],
+};
diff --git a/accelerate/remix-starter/tasks/validateConfig.ts b/accelerate/remix-starter/tasks/validateConfig.ts
new file mode 100644
index 000000000000..c924848b4a12
--- /dev/null
+++ b/accelerate/remix-starter/tasks/validateConfig.ts
@@ -0,0 +1,11 @@
+import { globalEnvSchema } from "../app/env/globalEnv";
+import { serverEnvSchema } from "../app/env/envFlags.server";
+
+const serverEnvResult = serverEnvSchema.safeParse(process.env);
+const clientEnvResult = globalEnvSchema.safeParse(process.env);
+
+if (!serverEnvResult.success || !clientEnvResult.success) {
+ process.exit(-1);
+}
+
+console.log("Client and server env vars are valid!");
diff --git a/accelerate/remix-starter/tsconfig.json b/accelerate/remix-starter/tsconfig.json
new file mode 100644
index 000000000000..aa8718e06d3d
--- /dev/null
+++ b/accelerate/remix-starter/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "include": ["env.d.ts", "**/*.ts", "**/*.tsx", "app/**/*"],
+ "compilerOptions": {
+ "lib": ["DOM", "DOM.Iterable", "ES2019"],
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "jsx": "react-jsx",
+ "resolveJsonModule": true,
+ "target": "ES2019",
+ "strict": true,
+ "baseUrl": ".",
+ "paths": {
+ "~/*": ["./app/*"]
+ },
+ "noEmit": true,
+ "allowJs": true,
+ "forceConsistentCasingInFileNames": true,
+ "types": [
+ "@remix-run/node",
+ "vite/client",
+ "@remix-run/react/future/single-fetch.d.ts"
+ ],
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "Bundler"
+ }
+}
diff --git a/accelerate/remix-starter/vercel.json b/accelerate/remix-starter/vercel.json
new file mode 100644
index 000000000000..2798cba5710c
--- /dev/null
+++ b/accelerate/remix-starter/vercel.json
@@ -0,0 +1,27 @@
+{
+ "build": {
+ "env": {
+ "ENABLE_FILE_SYSTEM_API": "1"
+ }
+ },
+ "headers": [
+ {
+ "source": "(.*)",
+ "headers": [
+ {
+ "key": "X-Content-Type-Options",
+ "value": "nosniff"
+ },
+ {
+ "key": "X-Frame-Options",
+ "value": "DENY"
+ },
+ {
+ "key": "Content-Security-Policy",
+ "value": "default-src 'self' 'unsafe-inline' gc.zgo.at; img-src 'self' data:;"
+ },
+ { "key": "X-XSS-Protection", "value": "1" }
+ ]
+ }
+ ]
+}
diff --git a/accelerate/remix-starter/vite.config.ts b/accelerate/remix-starter/vite.config.ts
new file mode 100644
index 000000000000..6b976e2a776d
--- /dev/null
+++ b/accelerate/remix-starter/vite.config.ts
@@ -0,0 +1,21 @@
+import { vitePlugin as remix } from "@remix-run/dev";
+import { installGlobals } from "@remix-run/node";
+import { defineConfig } from "vite";
+import tsconfigPaths from "vite-tsconfig-paths";
+
+installGlobals({ nativeFetch: true });
+
+export default defineConfig({
+ plugins: [
+ remix({
+ ignoredRouteFiles: ["**/*.css"],
+ future: {
+ v3_fetcherPersist: true,
+ v3_relativeSplatPath: true,
+ v3_throwAbortReason: true,
+ unstable_singleFetch: true,
+ },
+ }),
+ tsconfigPaths(),
+ ],
+});
diff --git a/accelerate/remix-starter/vitest.config.ts b/accelerate/remix-starter/vitest.config.ts
new file mode 100644
index 000000000000..01b2f4d1a572
--- /dev/null
+++ b/accelerate/remix-starter/vitest.config.ts
@@ -0,0 +1,19 @@
+import { defineConfig } from "vite";
+import tsconfigPaths from "vite-tsconfig-paths";
+
+export default defineConfig({
+ plugins: [tsconfigPaths()],
+ test: {
+ globals: true,
+ environment: "jsdom",
+ setupFiles: "./tests/vitest-setup.ts",
+ exclude: [
+ "./tests/e2e",
+ "**/node_modules/**",
+ "**/dist/**",
+ "**/cypress/**",
+ "**/.{idea,git,cache,output,temp}/**",
+ "**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*",
+ ],
+ },
+});
diff --git a/accelerate/solidstart-starter/.gitignore b/accelerate/solidstart-starter/.gitignore
new file mode 100644
index 000000000000..ff04496935f1
--- /dev/null
+++ b/accelerate/solidstart-starter/.gitignore
@@ -0,0 +1,28 @@
+
+dist
+.solid
+.output
+.vercel
+.netlify
+.vinxi
+
+# Environment
+.env
+.env*.local
+
+# dependencies
+/node_modules
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+*.launch
+.settings/
+
+# Temp
+gitignore
+
+# System Files
+.DS_Store
+Thumbs.db
diff --git a/accelerate/solidstart-starter/README.md b/accelerate/solidstart-starter/README.md
new file mode 100644
index 000000000000..727efe5267c8
--- /dev/null
+++ b/accelerate/solidstart-starter/README.md
@@ -0,0 +1,102 @@
+# Prisma Accelerate Example: SolidStart Starter
+
+## Introduction
+The quote generator retrieves the most recently added quote with and without caching enabled from a predefined set of quotes. In the context of your Solidstart application, the quote generator is a service that provides quotes, with some caching strategies applied to optimize performance and reduce the load on the database.
+
+## General Steps of the Quote Generator:
+- Fetch a quote: Retrieves the most recently added quote with and without caching enabled.
+- Apply caching strategy: Depending on the request, it may apply different caching strategies (e.g., TTL, SWR, TTL+SWR or no caching).
+- Return the quote: The selected quote is returned, along with metadata about the caching status and other relevant information.
+
+This project showcases how to use Prisma ORM with Prisma Accelerate in a SolidStart application. It [demonstrates](./src/routes/api/quotes.ts#L18-32) every available [caching strategy in Accelerate](https://www.prisma.io/docs/accelerate/caching#cache-strategies).
+
+## Prerequisites
+
+To successfully run the project, you will need the following:
+
+- The **connection string** of a publicly accessible database
+- Your **Accelerate connection string** (containing your **Accelerate API key**) which you can get by enabling Accelerate in a project in your [Prisma Data Platform](https://pris.ly/pdp) account (learn more in the [docs](https://www.prisma.io/docs/platform/about#api-keys))
+
+
+## Getting started
+
+### 1. Clone the repository
+
+Clone the repository, navigate into it and install dependencies:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+cd prisma-examples/accelerate/solidstart-starter
+npm install
+```
+
+### 2. Configure environment variables
+
+Create a `.env` in the root of the project directory:
+
+```bash
+touch .env
+```
+
+Now, open the `.env` file and set the `DATABASE_URL` and `DIRECT_URL` environment variables with the values of your connection string and your Accelerate connection string:
+
+```bash
+# .env
+
+# Accelerate connection string (used for queries by Prisma Client)
+DATABASE_URL="__YOUR_ACCELERATE_CONNECTION_STRING__"
+
+# Database connection string (used for migrations by Prisma Migrate)
+DIRECT_URL="__YOUR_DATABASE_CONNECTION_STRING__"
+
+SOLID_START_PUBLIC_URL="http://localhost:3000/"
+```
+
+Note that `__YOUR_DATABASE_CONNECTION_STRING__` and `__YOUR_ACCELERATE_CONNECTION_STRING__` are placeholder values that you need to replace with the values of your database and Accelerate connection strings. Notice that the Accelerate connection string has the following structure: `prisma://accelerate.prisma-data.net/?api_key=__YOUR_ACCELERATE_API_KEY__`.
+
+### 3. Run a migration to create the `Quotes` table and seed the database
+
+The Prisma schema file contains a single `Quotes` model. You can map this model to the database and create the corresponding `Quotes` table using the following command:
+
+```
+npx prisma migrate dev --name init
+```
+
+You now have an empty `Quotes` table in your database. Next, run the [seed script](./prisma/seed.ts) to create some sample records in the table:
+
+```
+ npx prisma db seed
+```
+
+### 4. Generate Prisma Client for Accelerate
+
+When using Accelerate, Prisma Client doesn't need a query engine. That's why you should generate it as follows:
+
+```
+npx prisma generate --no-engine
+```
+
+### 5. Start the app
+
+You can run the app with the following command:
+
+```
+npm run dev
+```
+
+You will now be able to retrieve the most recently added quote with and without caching enabled along with some stats.
+
+
+
+You can see the performance and other stats (e.g. cache/hit) for the different Accelerate cache strategies at the bottom of the UI:
+
+
+## Resources
+
+- [Accelerate Speed Test](https://accelerate-speed-test.vercel.app/)
+- [Accelerate documentation](https://www.prisma.io/docs/accelerate)
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/accelerate/solidstart-starter/app.config.ts b/accelerate/solidstart-starter/app.config.ts
new file mode 100644
index 000000000000..de7f83103a18
--- /dev/null
+++ b/accelerate/solidstart-starter/app.config.ts
@@ -0,0 +1,3 @@
+import { defineConfig } from "@solidjs/start/config";
+
+export default defineConfig({});
diff --git a/accelerate/solidstart-starter/demo-solid.gif b/accelerate/solidstart-starter/demo-solid.gif
new file mode 100644
index 000000000000..da4c0a917621
Binary files /dev/null and b/accelerate/solidstart-starter/demo-solid.gif differ
diff --git a/accelerate/solidstart-starter/package.json b/accelerate/solidstart-starter/package.json
new file mode 100644
index 000000000000..ae023f51ef6d
--- /dev/null
+++ b/accelerate/solidstart-starter/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "example-hackernews",
+ "type": "module",
+ "scripts": {
+ "dev": "vinxi dev",
+ "build": "vinxi build",
+ "start": "vinxi start"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "@prisma/extension-accelerate": "2.0.2",
+ "@solidjs/router": "0.15.3",
+ "@solidjs/start": "1.1.7",
+ "solid-js": "1.9.9",
+ "tsx": "4.20.6",
+ "vinxi": "0.5.8",
+ "zod": "3.25.76"
+ },
+ "engines": {
+ "node": "22.16.0"
+ },
+ "devDependencies": {
+ "autoprefixer": "10.4.21",
+ "postcss": "8.5.6",
+ "prisma": "6.9.0",
+ "tailwindcss": "3.4.17"
+ },
+ "prisma": {
+ "seed": "tsx prisma/seed.ts"
+ }
+}
diff --git a/accelerate/solidstart-starter/postcss.config.js b/accelerate/solidstart-starter/postcss.config.js
new file mode 100644
index 000000000000..2e7af2b7f1a6
--- /dev/null
+++ b/accelerate/solidstart-starter/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/accelerate/solidstart-starter/prisma/schema.prisma b/accelerate/solidstart-starter/prisma/schema.prisma
new file mode 100644
index 000000000000..9b6c9431a4ef
--- /dev/null
+++ b/accelerate/solidstart-starter/prisma/schema.prisma
@@ -0,0 +1,20 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
+// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+model Quotes {
+ id Int @id @default(autoincrement())
+ quote String
+ createdAt DateTime @default(now())
+}
diff --git a/accelerate/solidstart-starter/prisma/seed.ts b/accelerate/solidstart-starter/prisma/seed.ts
new file mode 100644
index 000000000000..433935f38c89
--- /dev/null
+++ b/accelerate/solidstart-starter/prisma/seed.ts
@@ -0,0 +1,62 @@
+import { PrismaClient } from "@prisma/client";
+
+const prisma = new PrismaClient();
+
+const main = async () => {
+ console.time("Seeding complete 🌱");
+
+ await prisma.quotes.createMany({
+ skipDuplicates: true,
+ data: [
+ { quote: "The only way to do great work is to love what you do." },
+ {
+ quote:
+ "Success is not final, failure is not fatal: It is the courage to continue that counts.",
+ },
+ { quote: "In the middle of every difficulty lies opportunity." },
+ { quote: "Believe you can and you're halfway there." },
+ { quote: "The best way to predict the future is to create it." },
+ { quote: "Don't watch the clock; do what it does. Keep going." },
+ { quote: "The only thing we have to fear is fear itself." },
+ { quote: "The journey of a thousand miles begins with a single step." },
+ { quote: "If you can dream it, you can achieve it." },
+ { quote: "Innovation distinguishes between a leader and a follower." },
+ {
+ quote:
+ "The greatest glory in living lies not in never falling, but in rising every time we fall.",
+ },
+ { quote: "You miss 100% of the shots you don't take." },
+ {
+ quote:
+ "The only limit to our realization of tomorrow will be our doubts of today.",
+ },
+ { quote: "Change your thoughts and you change your world." },
+ {
+ quote:
+ "To be yourself in a world that is constantly trying to make you something else is the greatest accomplishment.",
+ },
+ {
+ quote:
+ "The only thing standing between you and your goal is the story you keep telling yourself as to why you can't achieve it.",
+ },
+ { quote: "Life is 10% what happens to us and 90% how we react to it." },
+ {
+ quote:
+ "The future belongs to those who believe in the beauty of their dreams.",
+ },
+ {
+ quote:
+ "Do not wait for the perfect moment, take the moment and make it perfect.",
+ },
+ { quote: "The only source of knowledge is experience." },
+ ],
+ });
+
+ console.timeEnd("Seeding complete 🌱");
+};
+
+main()
+ .then(() => {
+ console.log("Process completed");
+ })
+ .catch((e) => console.log(e));
\ No newline at end of file
diff --git a/accelerate/solidstart-starter/public/favicon.ico b/accelerate/solidstart-starter/public/favicon.ico
new file mode 100644
index 000000000000..fb282da0719e
Binary files /dev/null and b/accelerate/solidstart-starter/public/favicon.ico differ
diff --git a/accelerate/solidstart-starter/public/img/android-chrome-192x192.png b/accelerate/solidstart-starter/public/img/android-chrome-192x192.png
new file mode 100644
index 000000000000..378bc3867522
Binary files /dev/null and b/accelerate/solidstart-starter/public/img/android-chrome-192x192.png differ
diff --git a/accelerate/solidstart-starter/public/img/android-chrome-512x512.png b/accelerate/solidstart-starter/public/img/android-chrome-512x512.png
new file mode 100644
index 000000000000..f85a880f0833
Binary files /dev/null and b/accelerate/solidstart-starter/public/img/android-chrome-512x512.png differ
diff --git a/accelerate/solidstart-starter/public/img/apple-touch-icon.png b/accelerate/solidstart-starter/public/img/apple-touch-icon.png
new file mode 100644
index 000000000000..8b82e33bc162
Binary files /dev/null and b/accelerate/solidstart-starter/public/img/apple-touch-icon.png differ
diff --git a/accelerate/solidstart-starter/public/img/favicon-16x16.png b/accelerate/solidstart-starter/public/img/favicon-16x16.png
new file mode 100644
index 000000000000..fb282da0719e
Binary files /dev/null and b/accelerate/solidstart-starter/public/img/favicon-16x16.png differ
diff --git a/accelerate/solidstart-starter/public/img/favicon-32x32.png b/accelerate/solidstart-starter/public/img/favicon-32x32.png
new file mode 100644
index 000000000000..2c45aa58daea
Binary files /dev/null and b/accelerate/solidstart-starter/public/img/favicon-32x32.png differ
diff --git a/accelerate/solidstart-starter/public/img/mstile-150x150.png b/accelerate/solidstart-starter/public/img/mstile-150x150.png
new file mode 100644
index 000000000000..0f6d02f5e1f3
Binary files /dev/null and b/accelerate/solidstart-starter/public/img/mstile-150x150.png differ
diff --git a/accelerate/solidstart-starter/public/manifest.webmanifest b/accelerate/solidstart-starter/public/manifest.webmanifest
new file mode 100644
index 000000000000..1e7f4529cabe
--- /dev/null
+++ b/accelerate/solidstart-starter/public/manifest.webmanifest
@@ -0,0 +1,20 @@
+{
+ "name": "Solid Hackernews",
+ "short_name": "Solid HN",
+ "icons": [
+ {
+ "src": "/img/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/img/android-chrome-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "/",
+ "background_color": "#f2f3f5",
+ "display": "standalone",
+ "theme_color": "#f60"
+}
diff --git a/accelerate/solidstart-starter/public/robots.txt b/accelerate/solidstart-starter/public/robots.txt
new file mode 100644
index 000000000000..6f27bb66a346
--- /dev/null
+++ b/accelerate/solidstart-starter/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:
\ No newline at end of file
diff --git a/accelerate/solidstart-starter/public/sw.js b/accelerate/solidstart-starter/public/sw.js
new file mode 100644
index 000000000000..b2ecb50562f4
--- /dev/null
+++ b/accelerate/solidstart-starter/public/sw.js
@@ -0,0 +1,14 @@
+self.addEventListener("fetch", (e) => {
+ (e.request.url.includes("localhost") || e.request.url.includes("workers")) &&
+ e.respondWith(
+ caches
+ .open("solid-hn")
+ .then((t) =>
+ t
+ .match(e.request)
+ .then((n) => n || fetch(e.request).then((n) => (t.put(e.request, n.clone()), n)))
+ )
+ );
+});
+
+self.addEventListener("activate", (e) => e.waitUntil(caches.delete("solid-hn")));
diff --git a/accelerate/solidstart-starter/src/app.css b/accelerate/solidstart-starter/src/app.css
new file mode 100644
index 000000000000..dd320bb79154
--- /dev/null
+++ b/accelerate/solidstart-starter/src/app.css
@@ -0,0 +1,71 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+body {
+ font-family: 'Arial, sans-serif';
+}
+
+.quote-wrapper {
+ border: 1px solid #ccc;
+ padding: 16px;
+ border-radius: 8px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+.quote-content p {
+ margin-bottom: 8px;
+}
+
+.text-green-300 {
+ color: #81e6d9;
+}
+
+.text-gray-500 {
+ color: #a0aec0;
+}
+
+.text-slate-200 {
+ color: #e2e8f0;
+}
+
+.text-black {
+ color: #000;
+}
+
+.font-bold {
+ font-weight: bold;
+}
+
+.mt-3.5 {
+ margin-top: 0.875rem;
+}
+
+.my-2 {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+
+.h-0.5 {
+ height: 0.125rem;
+}
+
+.border-t-0 {
+ border-top-width: 0;
+}
+
+.bg-neutral-100 {
+ background-color: #f5f5f5;
+}
+
+.opacity-100 {
+ opacity: 1;
+}
+
+.dark\\:opacity-50 {
+ opacity: 0.5;
+}
+
+.text-red-400 {
+ color: #fc8181;
+}
diff --git a/accelerate/solidstart-starter/src/app.tsx b/accelerate/solidstart-starter/src/app.tsx
new file mode 100644
index 000000000000..4d36f45ba44d
--- /dev/null
+++ b/accelerate/solidstart-starter/src/app.tsx
@@ -0,0 +1,59 @@
+import { createResource, Suspense, Show } from 'solid-js';
+import Quote from './components/quote';
+import { HOST } from './lib/utils/helper';
+import type { QuoteResult } from './types';
+
+const fetchQuotes = async (type: string): Promise => {
+
+ const res = await fetch(`${HOST}/api/quotes?cache=${encodeURIComponent(type)}`);
+
+ if (!res.ok) {
+ throw new Error('Network response was not ok');
+ }
+
+ return res.json();
+};
+
+const App = () => {
+ const [ttl, { loading: ttlLoading, error: ttlError }] = createResource(() => 'TTL', fetchQuotes);
+ const [swr, { loading: swrLoading, error: swrError }] = createResource(() => 'SWR', fetchQuotes);
+ const [both, { loading: bothLoading, error: bothError }] = createResource(() => 'TTL + SWR', fetchQuotes);
+ const [none, { loading: noneLoading, error: noneError }] = createResource(() => 'NO CACHING', fetchQuotes);
+
+ const renderQuote = (title: string, type: string, result: () => QuoteResult | undefined, loading: boolean, error: any) => (
+ Loading...}>
+ {error ? (
+ Error: {error.message}
+ ) : (
+
+ )}
+
+ );
+ const refreshPage = () => {
+ window.location.reload();
+ };
+ return (
+
+ Accelerated Quotes
+
+ Retrieves the most recently added quote with and without caching enabled
+
+ Refresh Page
+
+ Loading...
}>
+ {renderQuote("Cached Quote", "TTL", ttl, ttlLoading, ttlError)}
+ {renderQuote("Cached Quote", "SWR", swr, swrLoading, swrError)}
+ { renderQuote("Cached Quote", "TTL + SWR", both, bothLoading, bothError)}
+ {renderQuote("Quote", "NO CACHING", none, noneLoading, noneError)}
+
+
+
+ );
+};
+
+export default App;
+
+
+
+
+
diff --git a/accelerate/solidstart-starter/src/components/quote.tsx b/accelerate/solidstart-starter/src/components/quote.tsx
new file mode 100644
index 000000000000..953e7bcf8916
--- /dev/null
+++ b/accelerate/solidstart-starter/src/components/quote.tsx
@@ -0,0 +1,56 @@
+import { Component, createEffect } from 'solid-js';
+import QuoteWrapper from './quoteWrapper';
+import { formatDate } from '../lib/utils/helper';
+import type { QuoteResult, QuoteCacheType } from '../types';
+
+type QuoteProps = {
+ title: string;
+ type: QuoteCacheType;
+ result: QuoteResult | undefined;
+};
+
+const Quote: Component = (props) => {
+ let quoteData: QuoteResult | undefined = props.result;
+
+ createEffect(() => {
+ if (props.result) {
+ quoteData = props.result;
+ }
+ });
+
+ return (
+
+
+ {quoteData ? (
+ <>
+
+ ID {quoteData.data.id} ⸺ '"
+ {quoteData.data.quote} "
+
+
+ Created At ⸺ {formatDate(quoteData.data.createdAt)}
+
+
+
+ Cache Node Region ⸺ {quoteData.info?.region}
+
+
+ Cached Modified at ⸺ {formatDate(quoteData.info?.lastModified.toString())}
+
+
+ Cache status ⸺
+
+ {quoteData.info?.cacheStatus?.toUpperCase()} {quoteData.info?.cacheStatus === 'swr' || quoteData.info?.cacheStatus === 'ttl' ? ' CACHE HIT' : ''}
+
+
+
Time taken: {quoteData.time}ms
+ >
+ ) : (
+
No data available
+ )}
+
+
+ );
+};
+
+export default Quote;
diff --git a/accelerate/solidstart-starter/src/components/quoteWrapper.tsx b/accelerate/solidstart-starter/src/components/quoteWrapper.tsx
new file mode 100644
index 000000000000..68781a75141a
--- /dev/null
+++ b/accelerate/solidstart-starter/src/components/quoteWrapper.tsx
@@ -0,0 +1,19 @@
+import { Component, JSX } from 'solid-js';
+
+type QuoteWrapperProps = {
+ title: string;
+ type: string;
+ children: JSX.Element;
+};
+
+const QuoteWrapper: Component = ({ title, type, children }) => {
+ return (
+
+
{title}
+
Type: {type}
+ {children}
+
+ );
+};
+
+export default QuoteWrapper;
diff --git a/accelerate/solidstart-starter/src/entry-client.tsx b/accelerate/solidstart-starter/src/entry-client.tsx
new file mode 100644
index 000000000000..8154f8697597
--- /dev/null
+++ b/accelerate/solidstart-starter/src/entry-client.tsx
@@ -0,0 +1,12 @@
+// @refresh reload
+import { mount, StartClient } from "@solidjs/start/client";
+import "./app.css";
+
+mount(() => , document.getElementById("app")!);
+
+// if (import.meta.env.PROD && "serviceWorker" in navigator) {
+// // Use the window load event to keep the page load performant
+// window.addEventListener("load", () => {
+// navigator.serviceWorker.register(`/sw.js`);
+// });
+// }
diff --git a/accelerate/solidstart-starter/src/entry-server.tsx b/accelerate/solidstart-starter/src/entry-server.tsx
new file mode 100644
index 000000000000..401eff83fdf7
--- /dev/null
+++ b/accelerate/solidstart-starter/src/entry-server.tsx
@@ -0,0 +1,21 @@
+// @refresh reload
+import { createHandler, StartServer } from "@solidjs/start/server";
+
+export default createHandler(() => (
+ (
+
+
+
+
+
+ {assets}
+
+
+ {children}
+ {scripts}
+
+
+ )}
+ />
+));
diff --git a/accelerate/solidstart-starter/src/global.d.ts b/accelerate/solidstart-starter/src/global.d.ts
new file mode 100644
index 000000000000..dc6f10c226c0
--- /dev/null
+++ b/accelerate/solidstart-starter/src/global.d.ts
@@ -0,0 +1 @@
+///
diff --git a/accelerate/solidstart-starter/src/lib/prisma.ts b/accelerate/solidstart-starter/src/lib/prisma.ts
new file mode 100644
index 000000000000..fcc6ce659d7e
--- /dev/null
+++ b/accelerate/solidstart-starter/src/lib/prisma.ts
@@ -0,0 +1,7 @@
+import { PrismaClient } from '@prisma/client'
+import { withAccelerate } from '@prisma/extension-accelerate'
+
+
+const prisma = new PrismaClient().$extends(withAccelerate())
+
+export default prisma
\ No newline at end of file
diff --git a/accelerate/solidstart-starter/src/lib/utils/helper.ts b/accelerate/solidstart-starter/src/lib/utils/helper.ts
new file mode 100644
index 000000000000..adb2e3ac21fc
--- /dev/null
+++ b/accelerate/solidstart-starter/src/lib/utils/helper.ts
@@ -0,0 +1,13 @@
+export const formatDate = (date: string | undefined): string => {
+ return date ? new Date(date).toLocaleString() : 'N/A';
+};
+
+export async function delay(ms: number): Promise {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, ms);
+ });
+ }
+
+export const HOST = process.env.SOLID_START_PUBLIC_URL ?? "http://localhost:3000/";
\ No newline at end of file
diff --git a/accelerate/solidstart-starter/src/lib/utils/query.ts b/accelerate/solidstart-starter/src/lib/utils/query.ts
new file mode 100644
index 000000000000..51b31eda2a8d
--- /dev/null
+++ b/accelerate/solidstart-starter/src/lib/utils/query.ts
@@ -0,0 +1,23 @@
+import prisma from "../prisma";
+import type { CacheStrategy } from "../../types";
+
+export const getQuotes = async (strategy?: CacheStrategy) => {
+ const start = Date.now();
+
+ const result = await prisma.quotes
+ .findMany({
+ // You can find the `cacheStrategy` options [here](https://www.prisma.io/docs/accelerate/caching#cache-strategies). The `cacheStrategy` can also be undefined, which would mean only connection pooling is being used.
+ cacheStrategy: strategy,
+ orderBy: {
+ id: "desc",
+ },
+ take: 1,
+ }).withAccelerateInfo();
+
+
+ return {
+ data: result?.data?.[0],
+ info: result.info,
+ time: Date.now() - start,
+ };
+};
diff --git a/accelerate/solidstart-starter/src/routes/api/quotes.ts b/accelerate/solidstart-starter/src/routes/api/quotes.ts
new file mode 100644
index 000000000000..e6de6277c549
--- /dev/null
+++ b/accelerate/solidstart-starter/src/routes/api/quotes.ts
@@ -0,0 +1,35 @@
+import { json } from "@solidjs/router";
+import { z } from 'zod';
+import { getQuotes } from '../../lib/utils/query';
+import type { APIEvent } from "@solidjs/start/server";
+import type { QuoteResult, CacheStrategy, QuoteCacheType } from '../../types';
+
+const cacheStrategies: Record = {
+ 'SWR': { swr: 30 },
+ 'TTL': { ttl: 30 },
+ 'NO CACHING': undefined,
+ 'TTL + SWR': { ttl: 30, swr: 60 },
+};
+
+export async function GET({ request }: APIEvent) {
+ const url = new URL(request.url);
+ const cache = decodeURIComponent(url.searchParams.get('cache') || '') as QuoteCacheType;
+
+ const parser = z.enum(["TTL", "SWR", "TTL + SWR", "NO CACHING"]);
+ const parsedOutput = parser.safeParse(cache);
+
+ if (!parsedOutput.success) {
+ return json({ error: 'Invalid search parameter.' }, { status: 400 });
+ }
+
+ const cacheType: QuoteCacheType = parsedOutput.data;
+ const cacheStrategy = cacheStrategies[cacheType];
+
+ if (cacheStrategy === undefined && cacheType !== 'NO CACHING') {
+ return json({ error: 'Invalid cache strategy.' }, { status: 400 });
+ }
+
+ const data = await getQuotes(cacheStrategy);
+
+ return json(data);
+}
diff --git a/accelerate/solidstart-starter/src/types.ts b/accelerate/solidstart-starter/src/types.ts
new file mode 100644
index 000000000000..576ec480adc4
--- /dev/null
+++ b/accelerate/solidstart-starter/src/types.ts
@@ -0,0 +1,33 @@
+export type CacheStrategy =
+ | {
+ ttl: number;
+ swr: number;
+ }
+ | {
+ ttl: number;
+ }
+ | {
+ swr: number;
+ };
+
+export type AccelerateInfo = {
+ cacheStatus: "ttl" | "swr" | "miss" | "none";
+ lastModified: Date;
+ region: string;
+ requestId: string;
+ signature: string;
+};
+
+export type Quote = {
+ id: number;
+ quote: string;
+ createdAt: string;
+};
+
+export type QuoteResult = {
+ data: Quote;
+ info: AccelerateInfo;
+ time: number;
+};
+
+export type QuoteCacheType = "SWR" | "TTL" | "NO CACHING" | "TTL + SWR";
\ No newline at end of file
diff --git a/accelerate/solidstart-starter/tailwind.config.js b/accelerate/solidstart-starter/tailwind.config.js
new file mode 100644
index 000000000000..df321fea6af0
--- /dev/null
+++ b/accelerate/solidstart-starter/tailwind.config.js
@@ -0,0 +1,9 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+}
+
diff --git a/accelerate/solidstart-starter/tsconfig.json b/accelerate/solidstart-starter/tsconfig.json
new file mode 100644
index 000000000000..7d5871a07ad8
--- /dev/null
+++ b/accelerate/solidstart-starter/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "jsx": "preserve",
+ "jsxImportSource": "solid-js",
+ "allowJs": true,
+ "strict": true,
+ "noEmit": true,
+ "types": ["vinxi/types/client"],
+ "isolatedModules": true,
+ "paths": {
+ "~/*": ["./src/*"]
+ }
+ }
+}
diff --git a/accelerate/starter/.gitignore b/accelerate/starter/.gitignore
new file mode 100644
index 000000000000..8f00ef230720
--- /dev/null
+++ b/accelerate/starter/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+.env
+dist
\ No newline at end of file
diff --git a/accelerate/starter/README.md b/accelerate/starter/README.md
new file mode 100644
index 000000000000..7fb6404cf268
--- /dev/null
+++ b/accelerate/starter/README.md
@@ -0,0 +1,91 @@
+# Prisma Accelerate Example: TypeScript Starter
+
+This repository has been created to help you get started with [Prisma Accelerate](https://prisma.io/accelerate). This project comes with a basic [`schema.prisma`](./prisma/schema.prisma) configured with PostgreSQL and an example operation found in the [`index.ts`](./index.ts) file.
+
+## Prerequisites
+
+To successfully run the project, you will need the following:
+
+- An Accelerate **connection string**. If you don't have one yet, you can get one in 2 minutes by signing up on console.prisma.io or following our [Getting Started guide](https://www.prisma.io/docs/accelerate/getting-started#1-enable-accelerate).
+
+## Getting started
+
+### 1. Download example and install dependencies
+
+Download this example:
+
+```
+npx try-prisma@latest --template typescript/starter
+```
+
+Install npm dependencies:
+
+```
+cd starter
+npm install
+```
+
+Alternative: Clone the entire repo
+
+Clone this repository:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+```
+
+Install npm dependencies:
+
+```
+cd prisma-examples/typescript/starter
+npm install
+```
+
+
+
+### 2. Configure environment variables
+
+Create a `.env` in the root of the project directory:
+
+```bash
+touch .env
+```
+
+Now, open the `.env` file and update the `DATABASE_URL` environment variables with the values of your connection string:
+
+```bash
+# .env
+DATABASE_URL="__ACCELERATE_CONNECTION_STRING_PLACEHOLDER__"
+DIRECT_URL="__DIRECT_DATABASE_CONNECTION_STRING_PLACEHOLDER__"
+```
+
+Note that you need to replace the placeholder values with the actual values.
+
+### 3. Run a database migration to create the `User` table
+
+The Prisma schema file contains a single `User` model. You can map this model to the database and create the corresponding `User` table using the following command:
+
+```bash
+npx prisma migrate dev --name init
+```
+
+You now have an empty `User` table in your database.
+
+### 4. Run a Prisma operation
+
+Run the [main script](./src/index.ts)
+
+```bash
+npm run start
+```
+
+This will add a new user to the `User` table, and then run a simple query to fetch all users.
+
+## Resources
+
+- [Accelerate Speed Test](https://accelerate-speed-test.vercel.app/)
+- [Accelerate documentation](https://www.prisma.io/docs/accelerate)
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/accelerate/starter/package.json b/accelerate/starter/package.json
new file mode 100644
index 000000000000..4faf718273d2
--- /dev/null
+++ b/accelerate/starter/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "prisma-typescript-starter",
+ "version": "1.0.0",
+ "main": "index.js",
+ "license": "MIT",
+ "scripts": {
+ "build": "tsc",
+ "start": "tsx src/index.ts",
+ "dev": "tsc --watch"
+ },
+ "devDependencies": {
+ "@types/node": "22.15.32",
+ "nodemon": "3.1.10",
+ "prisma": "6.9.0",
+ "tsx": "4.20.6",
+ "typescript": "5.8.2"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "@prisma/extension-accelerate": "2.0.2"
+ },
+ "prettier": {
+ "trailingComma": "all",
+ "tabWidth": 2,
+ "printWidth": 80,
+ "semi": true,
+ "singleQuote": true,
+ "jsxSingleQuote": false,
+ "jsxBracketSameLine": false,
+ "bracketSpacing": true,
+ "arrowParens": "always"
+ }
+}
diff --git a/accelerate/starter/prisma/schema.prisma b/accelerate/starter/prisma/schema.prisma
new file mode 100644
index 000000000000..0ae298de7e2b
--- /dev/null
+++ b/accelerate/starter/prisma/schema.prisma
@@ -0,0 +1,18 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ name String
+ email String
+}
diff --git a/accelerate/starter/src/index.ts b/accelerate/starter/src/index.ts
new file mode 100644
index 000000000000..3ce291f1fead
--- /dev/null
+++ b/accelerate/starter/src/index.ts
@@ -0,0 +1,28 @@
+import { PrismaClient } from '@prisma/client';
+import { withAccelerate } from '@prisma/extension-accelerate'
+
+const prisma = new PrismaClient().$extends(withAccelerate())
+
+async function main() {
+ const newUser = await prisma.user.create({
+ data: {
+ name: 'Percy Prisma',
+ email: 'percy@prisma.io',
+ },
+ });
+ console.log('The new user:', newUser);
+
+ const users = await prisma.user.findMany({
+ cacheStrategy: { ttl: 60 },
+ });
+ console.log('All users:', users);
+
+ const cachedUsers = await prisma.user.findMany({
+ cacheStrategy: { ttl: 60 },
+ }).withAccelerateInfo();
+ console.log('Cached users:', cachedUsers);
+
+ // See more examples of how to use Prisma Accelerate: https://www.prisma.io/docs/accelerate/examples
+}
+
+main();
diff --git a/accelerate/starter/tsconfig.json b/accelerate/starter/tsconfig.json
new file mode 100644
index 000000000000..a2b8c6f0b7c9
--- /dev/null
+++ b/accelerate/starter/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "compilerOptions": {
+ "target": "es6",
+ "module": "commonjs",
+ "rootDir": "./src",
+ "outDir": "./dist",
+ "strict": true,
+ "esModuleInterop": true,
+ "typeRoots": [
+ "./node_modules/@types"
+ ],
+ "forceConsistentCasingInFileNames": true,
+ "skipLibCheck": true
+ },
+}
diff --git a/accelerate/svelte-starter/.gitignore b/accelerate/svelte-starter/.gitignore
new file mode 100644
index 000000000000..79518f716450
--- /dev/null
+++ b/accelerate/svelte-starter/.gitignore
@@ -0,0 +1,21 @@
+node_modules
+
+# Output
+.output
+.vercel
+/.svelte-kit
+/build
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Env
+.env
+.env.*
+!.env.example
+!.env.test
+
+# Vite
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/accelerate/svelte-starter/.npmrc b/accelerate/svelte-starter/.npmrc
new file mode 100644
index 000000000000..b6f27f135954
--- /dev/null
+++ b/accelerate/svelte-starter/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/accelerate/svelte-starter/README.md b/accelerate/svelte-starter/README.md
new file mode 100644
index 000000000000..03c2762cbacc
--- /dev/null
+++ b/accelerate/svelte-starter/README.md
@@ -0,0 +1,98 @@
+# Prisma Accelerate Example: Sveltekit Starter
+
+## Introduction
+The quote generator retrieves the most recently added quote with and without caching enabled from a predefined set of quotes. In the context of your Sveltekit application, the quote generator is a service that provides quotes, with some caching strategies applied to optimize performance and reduce the load on the database.
+
+## General Steps of the Quote Generator:
+- Fetch a quote: Retrieves the most recently added quote with and without caching enabled.
+- Apply caching strategy: Depending on the request, it may apply different caching strategies (e.g., TTL, SWR, TTL+SWR or no caching).
+- Return the quote: The selected quote is returned, along with metadata about the caching status and other relevant information.
+
+This project showcases how to use Prisma ORM with Prisma Accelerate in a Sveltekit application. It [demonstrates](./src/routes/api/quotes/+server.ts#L18-33) every available [caching strategy in Accelerate](https://www.prisma.io/docs/accelerate/caching#cache-strategies).
+
+## Prerequisites
+
+To successfully run the project, you will need the following:
+
+- The **connection string** of a publicly accessible database
+- Your **Accelerate connection string** (containing your **Accelerate API key**) which you can get by enabling Accelerate in a project in your [Prisma Data Platform](https://pris.ly/pdp) account (learn more in the [docs](https://www.prisma.io/docs/platform/about#api-keys))
+
+## Getting started
+
+### 1. Clone the repository
+
+Clone the repository, navigate into it and install dependencies:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+cd prisma-examples/accelerate/svelte-starter
+npm install
+```
+
+### 2. Configure environment variables
+
+Create a `.env` in the root of the project directory:
+
+```bash
+touch .env
+```
+
+Now, open the `.env` file and set the `DATABASE_URL` and `DIRECT_URL` environment variables with the values of your connection string and your Accelerate connection string:
+
+```bash
+# .env
+
+# Accelerate connection string (used for queries by Prisma Client)
+DATABASE_URL="__YOUR_ACCELERATE_CONNECTION_STRING__"
+
+# Database connection string (used for migrations by Prisma Migrate)
+DIRECT_URL="__YOUR_DATABASE_CONNECTION_STRING__"
+
+VITE_PUBLIC_URL="http://localhost:5173/"
+```
+
+Note that `__YOUR_DATABASE_CONNECTION_STRING__` and `__YOUR_ACCELERATE_CONNECTION_STRING__` are placeholder values that you need to replace with the values of your database and Accelerate connection strings. Notice that the Accelerate connection string has the following structure: `prisma://accelerate.prisma-data.net/?api_key=__YOUR_ACCELERATE_API_KEY__`.
+
+### 3. Run a migration to create the `Quotes` table and seed the database
+
+The Prisma schema file contains a single `Quotes` model. You can map this model to the database and create the corresponding `Quotes` table using the following command:
+
+```
+npx prisma migrate dev --name init
+```
+
+You now have an empty `Quotes` table in your database. Next, run the [seed script](./prisma/seed.ts) to create some sample records in the table:
+
+```
+ npx prisma db seed
+```
+
+### 4. Generate Prisma Client for Accelerate
+
+When using Accelerate, Prisma Client doesn't need a query engine. That's why you should generate it as follows:
+
+```
+npx prisma generate --no-engine
+```
+
+### 5. Start the app
+
+You can run the app with the following command:
+
+```
+npm run dev
+```
+
+You will now be able to retrieve the most recently added quote with and without caching enabled along with some stats.
+
+
+
+## Resources
+
+- [Accelerate Speed Test](https://accelerate-speed-test.vercel.app/)
+- [Accelerate documentation](https://www.prisma.io/docs/accelerate)
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/accelerate/svelte-starter/demo.gif b/accelerate/svelte-starter/demo.gif
new file mode 100644
index 000000000000..4c52be8c22aa
Binary files /dev/null and b/accelerate/svelte-starter/demo.gif differ
diff --git a/accelerate/svelte-starter/package.json b/accelerate/svelte-starter/package.json
new file mode 100644
index 000000000000..14a6e100b94c
--- /dev/null
+++ b/accelerate/svelte-starter/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "svelte-starter",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "vite preview",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-auto": "6.0.1",
+ "@sveltejs/kit": "2.27.1",
+ "@sveltejs/vite-plugin-svelte": "5.1.1",
+ "@tailwindcss/typography": "0.5.16",
+ "autoprefixer": "10.4.21",
+ "postcss": "8.5.6",
+ "prisma": "6.9.0",
+ "svelte": "5.35.4",
+ "svelte-check": "4.2.2",
+ "tailwindcss": "3.4.17",
+ "tslib": "2.8.1",
+ "tsx": "4.20.6",
+ "typescript": "5.8.2",
+ "vite": "6.3.6"
+ },
+ "type": "module",
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "@prisma/extension-accelerate": "2.0.2",
+ "date-fns": "4.1.0",
+ "openflights-cached": "1.3.15",
+ "zod": "3.25.76"
+ },
+ "prisma": {
+ "seed": "tsx prisma/seed.ts"
+ }
+}
diff --git a/accelerate/svelte-starter/postcss.config.js b/accelerate/svelte-starter/postcss.config.js
new file mode 100644
index 000000000000..988ba6ba7e39
--- /dev/null
+++ b/accelerate/svelte-starter/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {}
+ }
+};
\ No newline at end of file
diff --git a/accelerate/svelte-starter/prisma/schema.prisma b/accelerate/svelte-starter/prisma/schema.prisma
new file mode 100644
index 000000000000..4f46ea877f1c
--- /dev/null
+++ b/accelerate/svelte-starter/prisma/schema.prisma
@@ -0,0 +1,22 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
+// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
+}
+
+
+model Quotes {
+ id Int @id @default(autoincrement())
+ quote String
+ createdAt DateTime @default(now())
+}
diff --git a/accelerate/svelte-starter/prisma/seed.ts b/accelerate/svelte-starter/prisma/seed.ts
new file mode 100644
index 000000000000..fa4f6cec9075
--- /dev/null
+++ b/accelerate/svelte-starter/prisma/seed.ts
@@ -0,0 +1,62 @@
+import { PrismaClient } from "@prisma/client";
+
+const prisma = new PrismaClient();
+
+const main = async () => {
+ console.time("Seeding complete 🌱");
+
+ await prisma.quotes.createMany({
+ skipDuplicates: true,
+ data: [
+ { quote: "The only way to do great work is to love what you do." },
+ {
+ quote:
+ "Success is not final, failure is not fatal: It is the courage to continue that counts.",
+ },
+ { quote: "In the middle of every difficulty lies opportunity." },
+ { quote: "Believe you can and you're halfway there." },
+ { quote: "The best way to predict the future is to create it." },
+ { quote: "Don't watch the clock; do what it does. Keep going." },
+ { quote: "The only thing we have to fear is fear itself." },
+ { quote: "The journey of a thousand miles begins with a single step." },
+ { quote: "If you can dream it, you can achieve it." },
+ { quote: "Innovation distinguishes between a leader and a follower." },
+ {
+ quote:
+ "The greatest glory in living lies not in never falling, but in rising every time we fall.",
+ },
+ { quote: "You miss 100% of the shots you don't take." },
+ {
+ quote:
+ "The only limit to our realization of tomorrow will be our doubts of today.",
+ },
+ { quote: "Change your thoughts and you change your world." },
+ {
+ quote:
+ "To be yourself in a world that is constantly trying to make you something else is the greatest accomplishment.",
+ },
+ {
+ quote:
+ "The only thing standing between you and your goal is the story you keep telling yourself as to why you can't achieve it.",
+ },
+ { quote: "Life is 10% what happens to us and 90% how we react to it." },
+ {
+ quote:
+ "The future belongs to those who believe in the beauty of their dreams.",
+ },
+ {
+ quote:
+ "Do not wait for the perfect moment, take the moment and make it perfect.",
+ },
+ { quote: "The only source of knowledge is experience." },
+ ],
+ });
+
+ console.timeEnd("Seeding complete 🌱");
+};
+
+main()
+ .then(() => {
+ console.log("Process completed");
+ })
+ .catch((e) => console.log(e));
\ No newline at end of file
diff --git a/accelerate/svelte-starter/src/app.css b/accelerate/svelte-starter/src/app.css
new file mode 100644
index 000000000000..bd6213e1dfe6
--- /dev/null
+++ b/accelerate/svelte-starter/src/app.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
\ No newline at end of file
diff --git a/accelerate/svelte-starter/src/app.d.ts b/accelerate/svelte-starter/src/app.d.ts
new file mode 100644
index 000000000000..743f07b2e50a
--- /dev/null
+++ b/accelerate/svelte-starter/src/app.d.ts
@@ -0,0 +1,13 @@
+// See https://kit.svelte.dev/docs/types#app
+// for information about these interfaces
+declare global {
+ namespace App {
+ // interface Error {}
+ // interface Locals {}
+ // interface PageData {}
+ // interface PageState {}
+ // interface Platform {}
+ }
+}
+
+export {};
diff --git a/accelerate/svelte-starter/src/app.html b/accelerate/svelte-starter/src/app.html
new file mode 100644
index 000000000000..58afe8159135
--- /dev/null
+++ b/accelerate/svelte-starter/src/app.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+ %sveltekit.body%
+
+
diff --git a/accelerate/svelte-starter/src/components/Quote.svelte b/accelerate/svelte-starter/src/components/Quote.svelte
new file mode 100644
index 000000000000..0aa64335e8d4
--- /dev/null
+++ b/accelerate/svelte-starter/src/components/Quote.svelte
@@ -0,0 +1,94 @@
+
+
+
+
+ {#if result?.data}
+
+ ID {id} ⸺ '"
+ {quote}
+ "'
+
+
+
+ Created At ⸺ {formatDate(createdAt)}
+
+
+
+
+
+ Cache Node Region ⸺ {findIATA(region ?? '')?.city || region}
+
+
+
+ Cached Modified at ⸺ {formatDate(lastModified)}
+
+
+
+ Cache status ⸺
+
+ {cacheStatus?.toUpperCase()}
+ {cacheStatus === 'swr' || cacheStatus === 'ttl' ? ' CACHE HIT' : ''}
+
+
+
+
Time taken: {time}ms
+
+
+ {:else}
+
No data available
+ {/if}
+
+
diff --git a/accelerate/svelte-starter/src/components/QuoteWrapper.svelte b/accelerate/svelte-starter/src/components/QuoteWrapper.svelte
new file mode 100644
index 000000000000..be3242c864f3
--- /dev/null
+++ b/accelerate/svelte-starter/src/components/QuoteWrapper.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+
+ {title}
+
+
+
{type}
+
+
+
diff --git a/accelerate/svelte-starter/src/lib/prisma.ts b/accelerate/svelte-starter/src/lib/prisma.ts
new file mode 100644
index 000000000000..d9c6f99200ca
--- /dev/null
+++ b/accelerate/svelte-starter/src/lib/prisma.ts
@@ -0,0 +1,8 @@
+// place files you want to import through the `$lib` alias in this folder.
+import { PrismaClient } from '@prisma/client'
+import { withAccelerate } from '@prisma/extension-accelerate'
+
+
+const prisma = new PrismaClient().$extends(withAccelerate());
+
+export default prisma
\ No newline at end of file
diff --git a/accelerate/svelte-starter/src/lib/types/index.ts b/accelerate/svelte-starter/src/lib/types/index.ts
new file mode 100644
index 000000000000..b7cf3178147f
--- /dev/null
+++ b/accelerate/svelte-starter/src/lib/types/index.ts
@@ -0,0 +1,33 @@
+export type CacheStrategy =
+ | {
+ ttl: number;
+ swr: number;
+ }
+ | {
+ ttl: number;
+ }
+ | {
+ swr: number;
+ };
+
+export type AccelerateInfo = {
+ cacheStatus: "ttl" | "swr" | "miss" | "none";
+ lastModified: Date;
+ region: string;
+ requestId: string;
+ signature: string;
+};
+
+export type Quote = {
+ id: number;
+ quote: string;
+ createdAt: string;
+};
+
+export type QuoteResult = {
+ data: Quote;
+ info: AccelerateInfo;
+ time: number;
+};
+
+export type QuoteCacheType = "SWR" | "TTL" | "No caching" | "TTL + SWR";
diff --git a/accelerate/svelte-starter/src/lib/utils/helper.ts b/accelerate/svelte-starter/src/lib/utils/helper.ts
new file mode 100644
index 000000000000..516e74b64344
--- /dev/null
+++ b/accelerate/svelte-starter/src/lib/utils/helper.ts
@@ -0,0 +1,12 @@
+import { browser } from '$app/environment';
+
+export async function delay(ms: number): Promise {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, ms);
+ });
+}
+
+// Use the appropriate environment variable based on the environment (server or browser)
+export const HOST = browser ? import.meta.env.VITE_PUBLIC_URL : process.env.VITE_PUBLIC_URL;
diff --git a/accelerate/svelte-starter/src/lib/utils/query.ts b/accelerate/svelte-starter/src/lib/utils/query.ts
new file mode 100644
index 000000000000..3c0047a5a911
--- /dev/null
+++ b/accelerate/svelte-starter/src/lib/utils/query.ts
@@ -0,0 +1,24 @@
+import prisma from "$lib/prisma";
+import type { CacheStrategy } from "../types";
+
+export const getQuotes = async (strategy?: CacheStrategy) => {
+ const start = Date.now();
+
+ const result = await prisma.quotes
+ .findMany({
+ // You can find the `cacheStrategy` options [here](https://www.prisma.io/docs/accelerate/caching#cache-strategies). The `cacheStrategy` can also be undefined, which would mean only connection pooling is being used.
+ cacheStrategy: strategy,
+ orderBy: {
+ id: "desc",
+ },
+ take: 1,
+ })
+ .withAccelerateInfo();
+
+ return {
+ data: result?.data?.[0],
+ info: result.info,
+ time: Date.now() - start,
+ };
+};
+
diff --git a/accelerate/svelte-starter/src/routes/+layout.svelte b/accelerate/svelte-starter/src/routes/+layout.svelte
new file mode 100644
index 000000000000..18aae606bbdd
--- /dev/null
+++ b/accelerate/svelte-starter/src/routes/+layout.svelte
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/accelerate/svelte-starter/src/routes/+page.svelte b/accelerate/svelte-starter/src/routes/+page.svelte
new file mode 100644
index 000000000000..47d5d907ce42
--- /dev/null
+++ b/accelerate/svelte-starter/src/routes/+page.svelte
@@ -0,0 +1,53 @@
+
+
+
+ Accelerated Quotes
+
+ Retrieves the most recently added quote with and without caching enabled
+
+ Refresh Page
+
+
+
+
+
+
+
+
diff --git a/accelerate/svelte-starter/src/routes/api/quotes/+server.ts b/accelerate/svelte-starter/src/routes/api/quotes/+server.ts
new file mode 100644
index 000000000000..e76f9661387b
--- /dev/null
+++ b/accelerate/svelte-starter/src/routes/api/quotes/+server.ts
@@ -0,0 +1,36 @@
+import { json } from '@sveltejs/kit';
+import { z } from 'zod';
+import { getQuotes } from '$lib/utils/query';
+
+// Import types from your custom types file
+import type { QuoteResult, CacheStrategy, QuoteCacheType } from '$lib/types';
+
+const cacheStrategies: Record = {
+ 'SWR': { swr: 30 },
+ 'TTL': { ttl: 30 },
+ 'No caching': undefined,
+ 'TTL + SWR': { ttl: 30, swr: 60 },
+};
+
+export async function GET({ url }: { url: URL }) {
+ const cache = decodeURIComponent(url.searchParams.get('cache') || '') as QuoteCacheType;
+
+ const parser = z.enum(["TTL", "SWR", "TTL + SWR", "No caching"]);
+ const parsedOutput = await parser.safeParseAsync(cache);
+
+ if (!parsedOutput.success) {
+ return json({ error: 'Invalid search parameter.' }, { status: 400 });
+ }
+
+ const cacheType: QuoteCacheType = parsedOutput.data;
+
+ const cacheStrategy = cacheStrategies[cacheType];
+
+ if (cacheStrategy === undefined && cacheType !== 'No caching') {
+ return json({ error: 'Invalid cache strategy.' }, { status: 400 });
+ }
+
+ const data = await getQuotes(cacheStrategy);
+
+ return json(data);
+}
diff --git a/accelerate/svelte-starter/static/favicon.png b/accelerate/svelte-starter/static/favicon.png
new file mode 100644
index 000000000000..825b9e65af7c
Binary files /dev/null and b/accelerate/svelte-starter/static/favicon.png differ
diff --git a/accelerate/svelte-starter/svelte.config.js b/accelerate/svelte-starter/svelte.config.js
new file mode 100644
index 000000000000..4a82086e244a
--- /dev/null
+++ b/accelerate/svelte-starter/svelte.config.js
@@ -0,0 +1,18 @@
+import adapter from '@sveltejs/adapter-auto';
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ // Consult https://kit.svelte.dev/docs/integrations#preprocessors
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+
+ kit: {
+ // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
+ // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
+ // See https://kit.svelte.dev/docs/adapters for more information about adapters.
+ adapter: adapter()
+ }
+};
+
+export default config;
diff --git a/accelerate/svelte-starter/tailwind.config.ts b/accelerate/svelte-starter/tailwind.config.ts
new file mode 100644
index 000000000000..41fc028aa662
--- /dev/null
+++ b/accelerate/svelte-starter/tailwind.config.ts
@@ -0,0 +1,11 @@
+import type { Config } from "tailwindcss";
+
+export default {
+ content: ["./src/**/*.{html,js,svelte,ts}"],
+
+ theme: {
+ extend: {}
+ },
+
+ plugins: [require("@tailwindcss/typography")]
+} as Config;
\ No newline at end of file
diff --git a/accelerate/svelte-starter/tsconfig.json b/accelerate/svelte-starter/tsconfig.json
new file mode 100644
index 000000000000..6298cda53d8c
--- /dev/null
+++ b/accelerate/svelte-starter/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
+ // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
+ //
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
+ // from the referenced tsconfig.json - TypeScript does not merge them in
+}
diff --git a/accelerate/svelte-starter/vite.config.ts b/accelerate/svelte-starter/vite.config.ts
new file mode 100644
index 000000000000..bbf8c7da43f0
--- /dev/null
+++ b/accelerate/svelte-starter/vite.config.ts
@@ -0,0 +1,6 @@
+import { sveltekit } from '@sveltejs/kit/vite';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [sveltekit()]
+});
diff --git a/databases/cockroachdb/.env.example b/databases/cockroachdb/.env.example
new file mode 100644
index 000000000000..a73022c1a7a6
--- /dev/null
+++ b/databases/cockroachdb/.env.example
@@ -0,0 +1 @@
+DATABASE_URL="postgresql://:@:/?&sslrootcert="
\ No newline at end of file
diff --git a/databases/cockroachdb/.gitignore b/databases/cockroachdb/.gitignore
new file mode 100644
index 000000000000..e547ace72bb1
--- /dev/null
+++ b/databases/cockroachdb/.gitignore
@@ -0,0 +1,5 @@
+node_modules/
+cockroach-data/
+dist/
+*.env*
+!.env.example
diff --git a/databases/cockroachdb/README.md b/databases/cockroachdb/README.md
new file mode 100644
index 000000000000..28f80a9b239d
--- /dev/null
+++ b/databases/cockroachdb/README.md
@@ -0,0 +1,161 @@
+# CockroachDB example
+
+This example shows how to:
+
+- Connect Prisma to a CockroachDB database
+- Create the database schema with raw SQL
+- Populate the Prisma schema using [`prisma db pull`](https://www.prisma.io/docs/reference/api-reference/command-reference#db-pull)
+- Read and write data to the database using [Prisma Client](https://www.prisma.io/client)
+
+> **Note:** CockroachDB support in Prisma is currently in [**Preview**](https://www.prisma.io/docs/about/prisma/releases#preview), and **Prisma Migrate isn't supported for now**. For this reason, you will create the database schema with raw SQL.
+
+The example consists of two parts:
+
+- `tests/prisma.test.ts`: Jest test (in TypeScript) with a variety of Prisma Client queries and assertions to showcase access patterns
+- `src/script.ts`: Node.js script with queries similar to the ones in the test.
+
+## Prerequisites
+
+- Node.js installed.
+- [Docker](https://www.docker.com/products/docker-desktop) installed
+
+> **Note:** You can also connect to a [free CockroachDB Serverless Cluster](https://www.cockroachlabs.com/docs/cockroachcloud/create-a-serverless-cluster.html).
+
+## 1. Download example & install dependencies
+
+Download this example:
+
+```
+curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/databases/cockroachdb
+```
+
+Install npm dependencies:
+
+```
+cd cockroachdb
+npm install
+```
+
+
+Alternative: Clone this repository
+
+Clone this repository:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+```
+
+Install npm dependencies:
+
+```
+cd prisma-examples/databases/cockroachdb
+npm install
+```
+
+
+
+## 2. Start a CockroachDB database server
+
+There are two approaches to setting up a CockroachDB database:
+
+1. Locally with Docker using the included [`docker-compose.yml`](./docker-compose.yml) file.
+1. Using a free hosted [CockroachDB Serverless](https://www.cockroachlabs.com/get-started-cockroachdb-v2/).
+
+### (Option 1) Start CockroachDB with Docker
+
+Run the following command from the `cockroachdb` folder to start a CockroachDB Docker container:
+
+```sh
+docker compose up -d
+```
+
+### (Option 2) Using CockroachDB Serverless
+
+Follow the following [guide](https://www.cockroachlabs.com/docs/cockroachcloud/create-a-serverless-cluster.html) to create a free CockroachDB Serverless cluster.
+
+
+
+## 3. Configure the database connection URL
+
+Prisma uses the `DATABASE_URL` environment variable in `.env` in the `cockroachdb` folder to connect to the database.
+
+Create the file:
+
+```sh
+touch .env
+```
+
+Then add the following line:
+
+```
+DATABASE_URL="postgresql://root@localhost:26257/prisma?sslmode=disable"
+```
+
+> **Note:** If you're using CockroachDB Serverless, see [`.env.example`](./.env.example) for more information on how `DATABASE_URL` should look like with the cluster configruation.
+
+## 4. Create the database schema in CockroachDB with Prisma Migrate
+
+Now that you have defined the `DATABASE_URL` in `.env`, you will use Prisma Migrate to create a migration file with the SQL necessary to create the database schema.
+
+Run the following command from the `cockroachdb` folder:
+
+```
+npx prisma migrate dev --name init
+```
+
+You should see the following output:
+
+```
+Your database is now in sync with your schema.
+```
+
+> **Note:** The `prisma migrate dev` command will automatically generate Prisma Client for use in `script.ts`.
+
+## 5. Run the tests and script
+
+To run the test in `tests/prisma.test.ts`, run the following command:
+
+```
+npm run test
+```
+
+To run the script `src/script.ts`, run the following command:
+
+```
+npm run start
+```
+
+As a next step, explore the `script.ts` file to see how to use Prisma Client to read and write data in the database.
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/databases/cockroachdb/docker-compose.yml b/databases/cockroachdb/docker-compose.yml
new file mode 100644
index 000000000000..c0d1e079c910
--- /dev/null
+++ b/databases/cockroachdb/docker-compose.yml
@@ -0,0 +1,17 @@
+# https://hub.docker.com/r/cockroachdb/cockroach
+
+version: '3'
+services:
+ cockroachdb:
+ image: cockroachdb/cockroach:latest-v21.2
+ restart: always
+ ports:
+ - '26257:26257'
+ volumes:
+ - cockroach:/cockroach/cockroach-data
+ - ./:/app
+ command: start-single-node --insecure --advertise-host localhost
+volumes:
+ cockroach:
+
+
diff --git a/typescript/circleci/jest.config.js b/databases/cockroachdb/jest.config.js
similarity index 100%
rename from typescript/circleci/jest.config.js
rename to databases/cockroachdb/jest.config.js
diff --git a/databases/cockroachdb/package.json b/databases/cockroachdb/package.json
new file mode 100644
index 000000000000..8523ea101456
--- /dev/null
+++ b/databases/cockroachdb/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "prisma-cockroachdb-example",
+ "version": "1.0.0",
+ "keywords": [],
+ "license": "ISC",
+ "author": "",
+ "main": "index.js",
+ "scripts": {
+ "start": "ts-node ./src/script.ts",
+ "test": "jest",
+ "test:watch": "jest --watch"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "jest": "29.7.0"
+ },
+ "devDependencies": {
+ "@types/jest": "29.5.14",
+ "@types/node": "22.15.32",
+ "@types/prettyjson": "0.0.33",
+ "prettyjson": "1.2.5",
+ "prisma": "6.9.0",
+ "ts-jest": "29.4.5",
+ "ts-node": "10.9.2",
+ "ts-node-dev": "2.0.0",
+ "typescript": "5.8.2"
+ }
+}
diff --git a/databases/cockroachdb/prisma/schema.prisma b/databases/cockroachdb/prisma/schema.prisma
new file mode 100644
index 000000000000..d8dfad4deb63
--- /dev/null
+++ b/databases/cockroachdb/prisma/schema.prisma
@@ -0,0 +1,45 @@
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "cockroachdb"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ id String @id @default(uuid())
+ createdAt DateTime @default(now())
+ email String @unique
+ name String?
+ comments Comment[]
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(uuid())
+ createdAt DateTime @default(now())
+ title String
+ content String?
+ published Boolean @default(false)
+ authorId String
+ author User @relation(fields: [authorId], references: [id])
+ comments Comment[]
+ tags Tag[]
+}
+
+model Comment {
+ id String @id @default(uuid())
+ createdAt DateTime @default(now())
+ comment String
+ writtenById String
+ postId String
+ writtenBy User @relation(fields: [writtenById], references: [id])
+ post Post @relation(fields: [postId], references: [id], onUpdate: NoAction)
+}
+
+model Tag {
+ id String @id @default(uuid())
+ tag String @unique
+ posts Post[]
+}
diff --git a/databases/cockroachdb/src/script.ts b/databases/cockroachdb/src/script.ts
new file mode 100644
index 000000000000..c4445cb0c187
--- /dev/null
+++ b/databases/cockroachdb/src/script.ts
@@ -0,0 +1,262 @@
+import { PrismaClient } from '@prisma/client'
+import prettyjson from 'prettyjson'
+
+const prisma = new PrismaClient()
+
+// A `main` function so that we can use async/await
+async function main() {
+ const tags = await Promise.all([
+ prisma.tag.create({
+ data: {
+ tag: 'Node.js',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'TypeScript',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Prisma',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Databases',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Cockroach Labs',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Serverless',
+ },
+ }),
+ ])
+
+ console.log('Created tags: \n', prettyjson.render(tags))
+
+ // Seed the database with users and posts
+ const user1 = await prisma.user.create({
+ data: {
+ email: 'alice@prisma.io',
+ name: 'Alice',
+ posts: {
+ create: {
+ title: 'Productive development with Prisma and CockroachDB',
+ published: true,
+ tags: {
+ connect: [
+ {
+ tag: 'Prisma',
+ },
+ {
+ tag: 'Cockroach Labs',
+ },
+ ],
+ },
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+ })
+
+ console.log('Created first user: \n', prettyjson.render(user1))
+
+ const user2 = await prisma.user.create({
+ data: {
+ email: 'shakuntala@prisma.io',
+ name: 'Shakuntala',
+ comments: {
+ create: {
+ comment:
+ 'Thanks for sharing. CockroachDB has helped us rapidly scale our architecture with very little effort.',
+ post: {
+ connect: {
+ id: user1.posts[0].id,
+ },
+ },
+ },
+ },
+ posts: {
+ create: [
+ {
+ title: 'Introducing to Prisma with CockroachDB',
+ published: true,
+ content:
+ 'Check out the Prisma blog at https://www.prisma.io/blog for more information',
+ tags: {
+ connect: [
+ {
+ tag: 'Node.js',
+ },
+ {
+ tag: 'Cockroach Labs',
+ },
+ {
+ tag: 'Databases',
+ },
+ ],
+ },
+ },
+ {
+ title: 'Zero cost type safety with Prisma',
+ published: true,
+ tags: {
+ connect: [
+ {
+ tag: 'Node.js',
+ },
+ {
+ tag: 'Databases',
+ },
+ ],
+ },
+ },
+ {
+ title: 'Horizontal scaling made easy',
+ published: false,
+ },
+ ],
+ },
+ },
+ include: {
+ posts: {
+ include: {
+ tags: true,
+ },
+ },
+ comments: {
+ include: {
+ post: true,
+ },
+ },
+ },
+ })
+
+ console.log('Created second user: \n', prettyjson.render(user2))
+
+ const taggedPosts = await prisma.tag.findUnique({
+ where: {
+ tag: 'Node.js',
+ },
+ include: {
+ posts: true,
+ },
+ })
+
+ console.log(
+ 'Retrieved all posts with the Node.js tag: ',
+ prettyjson.render(taggedPosts),
+ )
+
+ // Retrieve all published posts with a tag
+ const allPosts = await prisma.post.findMany({
+ where: {
+ AND: [
+ { published: true },
+ {
+ tags: {
+ some: {
+ tag: 'Cockroach Labs',
+ },
+ },
+ },
+ ],
+ },
+ })
+ console.log(
+ `Retrieved all published posts with the Cockroach Labs tag: `,
+ prettyjson.render(allPosts),
+ )
+
+ // Create a new post (written by an already existing user with email alice@prisma.io)
+ const newPost = await prisma.post.create({
+ data: {
+ title: 'Join the Prisma Discord community',
+ content: 'https://pris.ly/discord',
+ published: false,
+ author: {
+ connect: {
+ email: 'alice@prisma.io', // Should have been created during initial seeding
+ },
+ },
+ tags: {
+ connectOrCreate: {
+ create: {
+ tag: 'Community',
+ },
+ where: {
+ tag: 'Community',
+ },
+ },
+ connect: {
+ tag: 'Prisma',
+ },
+ },
+ comments: {
+ create: {
+ comment: 'Looking forward to joining to Prisma community.',
+ writtenBy: {
+ connect: {
+ email: 'shakuntala@prisma.io',
+ },
+ },
+ },
+ },
+ },
+ include: {
+ comments: {
+ include: {
+ writtenBy: true,
+ },
+ },
+ tags: true,
+ },
+ })
+ console.log(`Created a new post: \n`, prettyjson.render(newPost))
+
+ // Publish the new post
+ const updatedPost = await prisma.post.update({
+ where: {
+ id: newPost.id,
+ },
+ data: {
+ published: true,
+ },
+ })
+ console.log(`Published the newly created post: `, updatedPost)
+
+ // Retrieve all posts by user with email alice@prisma.io
+ const postsByUser = await prisma.user
+ .findUnique({
+ where: {
+ email: 'alice@prisma.io',
+ },
+ })
+ .posts()
+ console.log(`Retrieved all posts from a specific user: `, postsByUser)
+}
+
+async function clearDB() {
+ await prisma.tag.deleteMany({})
+ await prisma.comment.deleteMany({})
+ await prisma.post.deleteMany({})
+ await prisma.user.deleteMany({})
+}
+
+clearDB()
+ .then(main)
+ .catch((e) => {
+ console.error(e)
+ process.exit(1)
+ })
+ .finally(async () => {
+ await prisma.$disconnect()
+ })
diff --git a/databases/cockroachdb/tests/prisma.test.ts b/databases/cockroachdb/tests/prisma.test.ts
new file mode 100644
index 000000000000..9a8c8331cf6e
--- /dev/null
+++ b/databases/cockroachdb/tests/prisma.test.ts
@@ -0,0 +1,295 @@
+import { PrismaClient } from '@prisma/client'
+
+export const prisma = new PrismaClient()
+
+describe('example test with Prisma Client', () => {
+ beforeAll(async () => {
+ await prisma.tag.deleteMany({})
+ await prisma.comment.deleteMany({})
+ await prisma.post.deleteMany({})
+ await prisma.user.deleteMany({})
+ })
+ afterAll(async () => {
+ await prisma.$disconnect()
+ })
+ test('test query', async () => {
+ const data = await prisma.user.findMany({ take: 1, select: { id: true } })
+ expect(data).toBeTruthy()
+ })
+
+ test('create tags', async () => {
+ const tags = await Promise.all([
+ prisma.tag.create({
+ data: {
+ tag: 'Node.js',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'TypeScript',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Prisma',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Databases',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Cockroach Labs',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Serverless',
+ },
+ }),
+ ])
+
+ expect(tags.length).toEqual(6)
+ expect(typeof tags[0].id).toEqual('string')
+ expect(tags[0].tag).toBeTruthy()
+ })
+
+ test('create two user with posts comments and tags', async () => {
+ let email = 'alice@prisma.io'
+ let name = 'Alice'
+
+ const user1 = await prisma.user.create({
+ data: {
+ email,
+ name,
+ posts: {
+ create: {
+ title: 'Bringing value to users with rapid deployment',
+ published: true,
+ tags: {
+ connect: {
+ tag: 'Prisma',
+ },
+ },
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+ })
+
+ expect(user1.id).toBeTruthy()
+ expect(user1.name).toEqual(name)
+ expect(user1.email).toEqual(email)
+ expect(
+ user1.createdAt.getMonth() === new Date().getMonth() &&
+ user1.createdAt.getFullYear() === new Date().getFullYear(),
+ ).toBeTruthy()
+ expect(user1.posts.length).toEqual(1)
+ expect(user1.posts[0].published).toEqual(true)
+
+ email = 'shakuntala@prisma.io'
+ name = 'Shakuntala'
+
+ const user2 = await prisma.user.create({
+ data: {
+ name,
+ email,
+ comments: {
+ create: {
+ comment:
+ 'Thanks for sharing. Reducing the size of our releases and deployment more frequently has allowed us to bring more value to our customers.',
+ post: {
+ connect: {
+ id: user1.posts[0].id,
+ },
+ },
+ },
+ },
+ posts: {
+ create: [
+ {
+ title: 'GraphQL Authentication simplified',
+ published: false,
+ },
+ {
+ title: 'Introducing to Prisma with CockroachDB',
+ published: true,
+ content:
+ 'Check out the Prisma blog at https://www.prisma.io/blog for more information',
+ tags: {
+ // Creates the rows in the m-n relation table
+ connect: [
+ {
+ tag: 'Node.js',
+ },
+ {
+ tag: 'Cockroach Labs',
+ },
+ {
+ tag: 'Databases',
+ },
+ ],
+ },
+ },
+ {
+ title: 'Zero cost type safety with Prisma',
+ published: true,
+ tags: {
+ // Creates the rows in the m-n relation table
+ connect: [
+ {
+ tag: 'Node.js',
+ },
+ {
+ tag: 'Databases',
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ include: {
+ posts: {
+ include: {
+ tags: true,
+ },
+ orderBy: { title: 'asc' },
+ },
+ comments: {
+ include: {
+ post: true,
+ },
+ },
+ },
+ })
+
+ expect(user2.id).toBeTruthy()
+ expect(user2.name).toEqual(name)
+ expect(user2.email).toEqual(email)
+ expect(user2.posts.length).toEqual(3)
+ expect(user2.posts[1].authorId).toEqual(user2.id)
+ expect(user2.posts[1].tags[1].id).toBeTruthy()
+ expect(
+ user2.comments[0].comment.toLowerCase().includes('thanks'),
+ ).toBeTruthy()
+ expect(user2.comments[0].postId).toEqual(user1.posts[0].id)
+
+ expect(
+ user2.createdAt.getMonth() === new Date().getMonth() &&
+ user2.createdAt.getFullYear() === new Date().getFullYear(),
+ ).toBeTruthy()
+
+ const updatedName = 'Shakuntala Devi'
+ const updatedUser2 = await prisma.user.update({
+ data: {
+ name: updatedName,
+ },
+ where: {
+ id: user2.id,
+ },
+ })
+
+ expect(updatedUser2.name).toEqual(updatedName)
+ })
+
+ test('Get all published posts with a given tag', async () => {
+ // Retrieve all published posts
+ const taggedPosts = await prisma.tag.findUnique({
+ where: {
+ tag: 'Node.js',
+ },
+ include: {
+ posts: true,
+ },
+ })
+ expect(taggedPosts).toBeTruthy()
+ expect(taggedPosts?.tag).toEqual('Node.js')
+ expect(taggedPosts?.posts.length).toEqual(2)
+ })
+
+ test('Create unpublished post with tags and comments for an existing user and then publish', async () => {
+ const newPost = await prisma.post.create({
+ data: {
+ title: 'Join the Prisma Discord community',
+ content: 'https://pris.ly/discord',
+ published: false,
+ author: {
+ connect: {
+ email: 'alice@prisma.io', // Should have been created during initial seeding
+ },
+ },
+ tags: {
+ connectOrCreate: {
+ create: {
+ tag: 'Community',
+ },
+ where: {
+ tag: 'Community',
+ },
+ },
+ connect: {
+ tag: 'Prisma',
+ },
+ },
+ comments: {
+ create: {
+ comment: 'Looking forward to joining to Prisma community.',
+ writtenBy: {
+ connect: {
+ email: 'shakuntala@prisma.io',
+ },
+ },
+ },
+ },
+ },
+ include: {
+ comments: true,
+ tags: true,
+ },
+ })
+ expect(newPost).toBeTruthy()
+ expect(newPost.tags.length).toEqual(2)
+ expect(newPost.tags[0].tag).toBeTruthy()
+ expect(newPost.comments.length).toEqual(1)
+
+ await prisma.post.update({
+ where: {
+ id: newPost.id,
+ },
+ data: {
+ published: true,
+ },
+ })
+ })
+
+ test('Find comments by a user', async () => {
+ // Retrieve all published posts
+ const userComments = await prisma.user
+ .findUnique({
+ where: {
+ email: 'shakuntala@prisma.io',
+ },
+ })
+ .comments()
+ expect(userComments).toBeTruthy()
+ expect(userComments?.length).toEqual(2)
+ })
+
+ test('Fetch posts by a user', async () => {
+ // Retrieve all published posts
+ const userPosts = await prisma.user
+ .findUnique({
+ where: {
+ email: 'shakuntala@prisma.io',
+ },
+ })
+ .posts()
+ expect(userPosts).toBeTruthy()
+ expect(userPosts?.length).toEqual(3)
+ })
+})
diff --git a/databases/cockroachdb/tsconfig.json b/databases/cockroachdb/tsconfig.json
new file mode 100644
index 000000000000..a8744c799f6d
--- /dev/null
+++ b/databases/cockroachdb/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "outDir": "dist",
+ "target": "ES2018",
+ "module": "commonjs",
+ "strict": true,
+ "lib": ["esnext"],
+ "esModuleInterop": true
+ },
+ "exclude": ["dist"],
+ "include": ["tests"]
+}
diff --git a/databases/mongodb/README.md b/databases/mongodb/README.md
new file mode 100644
index 000000000000..4f3afef62e66
--- /dev/null
+++ b/databases/mongodb/README.md
@@ -0,0 +1,104 @@
+# MongoDB example
+
+This example shows how to use Prisma with MongoDB and use [Prisma Client](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client) in a **Node.js script** to read and write data in a MongoDB database. You can find the database schema in [`./prisma/schema.prisma`](./schema.sql).
+
+The example consists of two parts:
+
+- `tests/prisma.test.ts`: Jest test (in TypeScript) with a variety of Prisma Client queries and assertions to showcase access patterns
+- `src/prisma-examples`: TypesScript files containing different Prisma Client queries
+
+## How to use
+
+### 1. Download example and navigate into the project directory
+
+Download this example:
+
+```
+npx try-prisma@latest --template databases/mongodb
+```
+
+Then, navigate into the project directory:
+
+```
+cd mongodb
+```
+
+Alternative: Clone the entire repo
+
+Clone this repository:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+```
+
+Install npm dependencies:
+
+```
+cd prisma-examples/databases/mongodb
+npm install
+```
+
+
+
+### 2. Start MongoDB with Docker Compose
+
+Run the following command from the `mongodb` folder to start MongoDB:
+
+```
+docker compose up -d
+```
+
+> **Note:** The `docker-compose.yml` is where the root username and password are set with the `MONGO_INITDB_ROOT_USERNAME` `MONGO_INITDB_ROOT_PASSWORD` env vars
+
+### 3. Configure the database connection URL
+
+Prisma uses the `DATABASE_URL` environment variable defined in the `.env` file (in the same folder as `package.json`) to connect to the database.
+
+Create the file:
+
+```bash
+touch .env
+```
+
+Then add the following line:
+
+```
+DATABASE_URL="mongodb://root:prisma@localhost:27017/prisma-mongo?authSource=admin&retryWrites=true&w=majority"
+```
+
+### 4. Generate Prisma Client
+
+Generate Prisma Client using the following command:
+
+```bash
+npx prisma generate
+```
+
+### 5. Run the tests
+
+To run the test in `tests/prisma.test.ts`, run the following command:
+
+```bash
+npm run test
+```
+
+### 6. Run the example scripts
+
+To run the example scripts in `src/prisma-examples`, run the following commands:
+
+```bash
+npm run script:create-user
+npm run script:find-user
+npm run script:update-user
+npm run script:delete-user
+npm run script:create-user-post
+npm run script:find-posts
+```
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/databases/mongodb/docker-compose.yml b/databases/mongodb/docker-compose.yml
new file mode 100644
index 000000000000..9842fc8ee859
--- /dev/null
+++ b/databases/mongodb/docker-compose.yml
@@ -0,0 +1,11 @@
+version: '3.7'
+services:
+ mongodb_container:
+ # This image automatically creates a replica set required for transactions
+ image: prismagraphql/mongo-single-replica:4.4.3-bionic
+ environment:
+ MONGO_INITDB_ROOT_USERNAME: root
+ MONGO_INITDB_ROOT_PASSWORD: prisma
+ INIT_WAIT_SEC: 3
+ ports:
+ - 27017:27017
diff --git a/databases/mongodb/jest.config.js b/databases/mongodb/jest.config.js
new file mode 100644
index 000000000000..87c30aa4a773
--- /dev/null
+++ b/databases/mongodb/jest.config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+}
diff --git a/databases/mongodb/package.json b/databases/mongodb/package.json
new file mode 100644
index 000000000000..d8e3becf4e6b
--- /dev/null
+++ b/databases/mongodb/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "prisma-mongo",
+ "version": "1.0.0",
+ "description": "",
+ "keywords": [],
+ "license": "ISC",
+ "author": "",
+ "main": "index.js",
+ "scripts": {
+ "build": "tsc",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "script:create-user": "ts-node src/prisma-examples/1-create-user.ts",
+ "script:find-user": "ts-node src/prisma-examples/2-find-user.ts",
+ "script:update-user": "ts-node src/prisma-examples/3-update-user.ts",
+ "script:delete-user": "ts-node src/prisma-examples/4-delete-user.ts",
+ "script:create-user-post": "ts-node src/prisma-examples/5-create-user-post.ts",
+ "script:find-posts": "ts-node src/prisma-examples/6-find-posts.ts"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0"
+ },
+ "devDependencies": {
+ "@types/jest": "29.5.14",
+ "@types/node": "22.15.32",
+ "jest": "29.7.0",
+ "prisma": "6.9.0",
+ "ts-jest": "29.4.5",
+ "ts-node": "10.9.2",
+ "typescript": "5.8.2"
+ }
+}
diff --git a/databases/mongodb/prisma/schema.prisma b/databases/mongodb/prisma/schema.prisma
new file mode 100644
index 000000000000..6a7ee01b5a53
--- /dev/null
+++ b/databases/mongodb/prisma/schema.prisma
@@ -0,0 +1,28 @@
+// We want to connect to the MongoDB datasource
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ createdAt DateTime @default(now())
+ firstName String
+ lastName String?
+ email String @unique
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ createdAt DateTime @default(now())
+ title String
+ body String?
+ views Int @default(0)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId String? @db.ObjectId
+}
diff --git a/databases/mongodb/src/prisma-examples/1-create-user.ts b/databases/mongodb/src/prisma-examples/1-create-user.ts
new file mode 100644
index 000000000000..744e56241580
--- /dev/null
+++ b/databases/mongodb/src/prisma-examples/1-create-user.ts
@@ -0,0 +1,19 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ const hana = await prisma.user.create({
+ data: {
+ email: 'hana@hana.io',
+ firstName: 'Hana',
+ lastName: 'Gold',
+ },
+ })
+
+ console.log(hana)
+}
+
+main()
+ .catch(console.error)
+ .finally(() => prisma.$disconnect())
diff --git a/databases/mongodb/src/prisma-examples/2-find-user.ts b/databases/mongodb/src/prisma-examples/2-find-user.ts
new file mode 100644
index 000000000000..c7a5b574783d
--- /dev/null
+++ b/databases/mongodb/src/prisma-examples/2-find-user.ts
@@ -0,0 +1,16 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ const user = await prisma.user.findUnique({
+ where: {
+ email: 'hana@hana.io'
+ }
+ })
+ console.log(user)
+}
+
+main()
+ .catch(console.error)
+ .finally(() => prisma.$disconnect())
diff --git a/databases/mongodb/src/prisma-examples/3-update-user.ts b/databases/mongodb/src/prisma-examples/3-update-user.ts
new file mode 100644
index 000000000000..28fde99fee4d
--- /dev/null
+++ b/databases/mongodb/src/prisma-examples/3-update-user.ts
@@ -0,0 +1,19 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ const user = await prisma.user.update({
+ where: {
+ email: 'hana@hana.io',
+ },
+ data: {
+ lastName: 'Peters',
+ },
+ })
+ console.log(user)
+}
+
+main()
+ .catch(console.error)
+ .finally(() => prisma.$disconnect())
diff --git a/databases/mongodb/src/prisma-examples/4-delete-user.ts b/databases/mongodb/src/prisma-examples/4-delete-user.ts
new file mode 100644
index 000000000000..0d1bb6ff15a7
--- /dev/null
+++ b/databases/mongodb/src/prisma-examples/4-delete-user.ts
@@ -0,0 +1,16 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ const user = await prisma.user.delete({
+ where: {
+ email: 'hana@hana.io',
+ }
+ })
+ console.log(user)
+}
+
+main()
+ .catch(console.error)
+ .finally(() => prisma.$disconnect())
diff --git a/databases/mongodb/src/prisma-examples/5-create-user-post.ts b/databases/mongodb/src/prisma-examples/5-create-user-post.ts
new file mode 100644
index 000000000000..e046687fc3f1
--- /dev/null
+++ b/databases/mongodb/src/prisma-examples/5-create-user-post.ts
@@ -0,0 +1,30 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ await prisma.user.deleteMany()
+ const user = await prisma.user.create({
+ data: {
+ email: 'david@prisma.io',
+ firstName: 'David',
+ lastName: 'Deutsch',
+ posts: {
+ create: [
+ { title: 'Hello world' },
+ { title: 'Introduction to Prisma with Mongo' },
+ { title: 'MongoDB and schemas' },
+ ],
+ },
+ },
+ include: {
+ posts: true,
+ },
+ })
+
+ console.dir(user, { depth: Infinity })
+}
+
+main()
+ .catch(console.error)
+ .finally(() => prisma.$disconnect())
diff --git a/databases/mongodb/src/prisma-examples/6-find-posts.ts b/databases/mongodb/src/prisma-examples/6-find-posts.ts
new file mode 100644
index 000000000000..55b7c772392f
--- /dev/null
+++ b/databases/mongodb/src/prisma-examples/6-find-posts.ts
@@ -0,0 +1,20 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ const posts = await prisma.post.findMany({
+ include: {
+ author: true,
+ },
+ orderBy: {
+ createdAt: 'desc',
+ },
+ })
+
+ console.dir(posts, { depth: Infinity })
+}
+
+main()
+ .catch(console.error)
+ .finally(() => prisma.$disconnect())
diff --git a/databases/mongodb/tests/prisma.test.ts b/databases/mongodb/tests/prisma.test.ts
new file mode 100644
index 000000000000..f1f97022ac7e
--- /dev/null
+++ b/databases/mongodb/tests/prisma.test.ts
@@ -0,0 +1,169 @@
+import { PrismaClient } from '@prisma/client'
+
+export const prisma = new PrismaClient()
+
+describe('example test with Prisma Client', () => {
+ beforeAll(async () => {
+ await prisma.post.deleteMany({})
+ await prisma.user.deleteMany({})
+ })
+ afterAll(async () => {
+ await prisma.$disconnect()
+ })
+
+ test('test query', async () => {
+ const data = await prisma.user.findMany({ take: 1, select: { id: true } })
+ expect(data).toBeTruthy()
+ })
+
+ const email = 'ada@prisma.io'
+ const firstName = 'Ada'
+ const lastName = 'Lovelace'
+ let userId: string
+ let postId: string
+
+ test('create user', async () => {
+ const user = await prisma.user.create({
+ data: {
+ email,
+ firstName,
+ lastName,
+ },
+ })
+
+ expect(user).toBeTruthy()
+ expect(typeof user.id).toEqual('string')
+ expect(user.firstName).toEqual('Ada')
+ expect(user.lastName).toEqual('Lovelace')
+ expect(user.email).toEqual('ada@prisma.io')
+ })
+
+ test('create a user with posts', async () => {
+ const user = await prisma.user.create({
+ data: {
+ email,
+ firstName,
+ lastName,
+ posts: {
+ create: [
+ {
+ title:
+ 'Bringing value to users with rapid deployment using Prisma',
+ },
+ {
+ title: 'Using Prisma Client with MongoDB',
+ },
+ ],
+ },
+ },
+ include: {
+ posts: true,
+ },
+ })
+
+ expect(user.id).toBeTruthy()
+ expect(user.createdAt instanceof Date).toBeTruthy()
+ expect(user.firstName).toEqual(firstName)
+ expect(user.email).toEqual(email)
+
+ expect(user.posts.length).toEqual(2)
+ expect(user.posts[0].authorId).toEqual(user.id)
+ expect(user.posts[0].views).toEqual(0)
+ expect(user.posts[0].id).toBeTruthy()
+ userId = user.id
+ postId = user.posts[0].id
+ })
+
+ test('Find user based on user id', async () => {
+ const user = await prisma.user.findUnique({
+ where: {
+ id: userId,
+ },
+ })
+
+ expect(user).toBeTruthy()
+ expect(user?.email).toEqual(email)
+ })
+
+ test('Find user and related posts based on user id', async () => {
+ const userPosts = await prisma.user
+ .findUnique({
+ where: {
+ id: userId,
+ },
+ })
+ .posts()
+
+ expect(userPosts).toBeTruthy()
+ expect(userPosts?.length).toEqual(2)
+ })
+
+ test('Find posts based on author id', async () => {
+ const postsFromUser = await prisma.post.findMany({
+ where: {
+ authorId: userId,
+ },
+ })
+ expect(postsFromUser).toBeTruthy()
+ expect(postsFromUser.length).toEqual(2)
+ })
+
+ test('Filter posts based on title', async () => {
+ const postsWithPrisma = await prisma.post.findMany({
+ where: {
+ title: {
+ equals: 'Using Prisma Client with MongoDB',
+ },
+ },
+ })
+ expect(postsWithPrisma).toBeTruthy()
+ expect(postsWithPrisma.length).toEqual(1)
+ })
+
+ test('Update posts - increment count', async () => {
+ const postsByUser = await prisma.post.updateMany({
+ where: {
+ authorId: userId,
+ },
+ data: {
+ views: {
+ increment: 1,
+ },
+ },
+ })
+ expect(postsByUser.count).toBeTruthy()
+ expect(postsByUser.count).toEqual(2)
+
+ const posts = await prisma.post.findMany({
+ where: {
+ authorId: userId,
+ },
+ select: {
+ views: true,
+ },
+ })
+
+ expect(posts).toBeTruthy()
+ expect(posts.length).toEqual(2)
+ expect(posts[0].views).toEqual(1)
+ expect(posts[1].views).toEqual(1)
+ })
+
+ test('Delete post', async () => {
+ const deletedPost = await prisma.post.delete({
+ where: {
+ id: postId,
+ },
+ })
+ expect(deletedPost).toBeTruthy()
+
+ const postsByUserCount = await prisma.post.count({
+ where: {
+ authorId: userId,
+ },
+ })
+
+ expect(postsByUserCount).toBeTruthy()
+ expect(postsByUserCount).toEqual(1)
+ })
+})
diff --git a/databases/mongodb/tsconfig.json b/databases/mongodb/tsconfig.json
new file mode 100644
index 000000000000..cd4f277a45c4
--- /dev/null
+++ b/databases/mongodb/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "outDir": "dist",
+ "target": "ES2018",
+ "module": "commonjs",
+ "strict": true,
+ "lib": ["esnext"],
+ "esModuleInterop": true
+ },
+ "exclude": ["dist"],
+ "include": ["src"]
+}
diff --git a/databases/postgresql-supabase/README.md b/databases/postgresql-supabase/README.md
new file mode 100644
index 000000000000..0d1f8ed024a9
--- /dev/null
+++ b/databases/postgresql-supabase/README.md
@@ -0,0 +1,111 @@
+# PostgreSQL example using Supabase
+
+This example shows you how to connect to a PostgreSQL database on [Supabase](https://supabase.com/) using Prisma, and use [Prisma Client](https://www.prisma.io/client) in a TypeScript script to read and write data.
+
+## How to use
+
+Download this example:
+
+```
+curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/databases/postgresql-supabase
+```
+
+Install npm dependencies:
+```
+cd postgresql-supabase
+npm install
+```
+
+Alternative: Clone the entire repo
+
+Clone this repository:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+```
+
+Install npm dependencies:
+
+```
+cd prisma-examples/databases/postgresql-supabase
+npm install
+```
+
+
+### 2. Set up Supabase
+
+
+Create a `.env` file at the root of your folder. Copy and update the following environment variables in the `.env` file:
+
+
+```sh
+touch .env
+```
+
+#### Using a local development environment
+
+If you have the Supabase CLI locally installed and have logged in, run the following command to start up Supabase
+
+```sh
+npx supabase start
+```
+
+```sh
+# .env
+DATABASE_URL="postgresql://postgres:postgres@localhost:54322/postgres"
+```
+
+#### Using a managed environment
+
+If you're using the hosted version, create another database that will serve as the [shadow database](https://www.prisma.io/docs/concepts/components/prisma-migrate/shadow-database#cloud-hosted-shadow-databases-must-be-created-manually).
+
+```
+postgres=> CREATE DATABASE postgres_shadow;
+postgres=> exit
+```
+
+Next, update, your `.env` file with your `DATABASE_URL` and `SHADOW_DATABASE_URL` variables accordingly. Be sure to update the password (`[YOUR-PASSWORD]`) and project reference (`[YOUR-PROJECT-REF]`):
+
+```
+# .env
+DATABASE_URL="postgres://postgres:[YOUR-PASSWORD]@db.[YOUR-PROJECT-REF].supabase.co:5432/postgres"
+SHADOW_DATABASE_URL="postgres://postgres:[YOUR-PASSWORD]@db.[YOUR-PROJECT-REF].supabase.co:5432/postgres_shadow"
+```
+
+### Create the database schema
+
+Run the following command to create a migration file with the SQL necessary to create the database schema:
+
+```
+npx prisma migrate dev --name init
+```
+
+You should see the following output:
+
+```
+Your database is now in sync with your schema.
+```
+
+### 3. Run the script
+
+For the script to work, you first need to execute the [seed](./prisma/seed.ts) script to seed your database. You can do that using the following command:
+
+```
+npx prisma db seed
+```
+
+Then run the script [`script.ts`](./script.ts), using the following command:
+
+```bash
+npm run dev
+```
+
+As a next step, explore the `script.ts` file to see how to use Prisma Client to read and write data in the database.
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/databases/postgresql-supabase/package.json b/databases/postgresql-supabase/package.json
new file mode 100644
index 000000000000..7eea48b6a645
--- /dev/null
+++ b/databases/postgresql-supabase/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "supabase-postgresql",
+ "version": "1.0.0",
+ "license": "MIT",
+ "scripts": {
+ "dev": "ts-node script.ts",
+ "test": "jest",
+ "test:watch": "jest --watch"
+ },
+ "devDependencies": {
+ "@types/node": "22.15.32",
+ "prisma": "6.9.0",
+ "supabase": "2.30.4",
+ "ts-node": "10.9.2",
+ "typescript": "5.8.2"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0"
+ },
+ "prisma": {
+ "seed": "ts-node prisma/seed.ts"
+ }
+}
diff --git a/databases/postgresql-supabase/prisma/schema.prisma b/databases/postgresql-supabase/prisma/schema.prisma
new file mode 100644
index 000000000000..b140f04f2c38
--- /dev/null
+++ b/databases/postgresql-supabase/prisma/schema.prisma
@@ -0,0 +1,30 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ title String
+ content String?
+ published Boolean @default(false)
+ viewCount Int @default(0)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
diff --git a/databases/postgresql-supabase/prisma/seed.ts b/databases/postgresql-supabase/prisma/seed.ts
new file mode 100644
index 000000000000..56b7d849c590
--- /dev/null
+++ b/databases/postgresql-supabase/prisma/seed.ts
@@ -0,0 +1,70 @@
+import { PrismaClient, Prisma } from '@prisma/client'
+
+const prisma = new PrismaClient();
+
+const userData = [
+ {
+ name: 'Alice',
+ email: 'alice@prisma.io',
+ posts: {
+ create: [
+ {
+ title: 'Join the Prisma Discord',
+ content: 'https://pris.ly/discord',
+ published: true,
+ },
+ ],
+ },
+ },
+ {
+ name: 'Nilu',
+ email: 'nilu@prisma.io',
+ posts: {
+ create: [
+ {
+ title: 'Follow Prisma on Twitter',
+ content: 'https://www.twitter.com/prisma',
+ published: true,
+ },
+ ],
+ },
+ },
+ {
+ name: 'Mahmoud',
+ email: 'mahmoud@prisma.io',
+ posts: {
+ create: [
+ {
+ title: 'Ask a question about Prisma on GitHub',
+ content: 'https://www.github.com/prisma/prisma/discussions',
+ published: true,
+ },
+ {
+ title: 'Prisma on YouTube',
+ content: 'https://pris.ly/youtube',
+ },
+ ],
+ },
+ },
+] satisfies Prisma.UserCreateInput[]
+
+async function main() {
+ console.log(`Start seeding ...`)
+ for (const u of userData) {
+ const user = await prisma.user.create({
+ data: u,
+ })
+ console.log(`Created user with id: ${user.id}`)
+ }
+ console.log(`Seeding finished.`)
+}
+
+main()
+ .then(async () => {
+ await prisma.$disconnect()
+ })
+ .catch(async (e) => {
+ console.error(e)
+ await prisma.$disconnect()
+ process.exit(1)
+ })
diff --git a/databases/postgresql-supabase/script.ts b/databases/postgresql-supabase/script.ts
new file mode 100644
index 000000000000..bf173ab5e7ed
--- /dev/null
+++ b/databases/postgresql-supabase/script.ts
@@ -0,0 +1,71 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient();
+
+async function main() {
+
+ try {
+ await prisma.user.findFirstOrThrow({ where: { email: 'alice@prisma.io' } })
+ } catch {
+ const consoleMessage = `
+User alice@prisma.io not found. Please run the seed script before running this script.
+You can run the seed script via the following command:
+
+npx prisma db seed
+`;
+ console.error(consoleMessage);
+ return
+ }
+
+ // Retrieve all published posts
+ const allPosts = await prisma.post.findMany({
+ where: { published: true },
+ })
+ console.log('Retrieved all published posts: ', allPosts)
+
+ // Create a new post (written by an already existing user with email alice@prisma.io)
+ const newPost = await prisma.post.create({
+ data: {
+ title: "Join us for another episode of What's new in Prisma",
+ content: 'https://youtube.com/playlist?list=PLn2e1F9Rfr6l1B9RP0A9NdX7i7QIWfBa7',
+ published: false,
+ author: {
+ connect: {
+ email: 'alice@prisma.io',
+ },
+ },
+ },
+ })
+ console.log('Created a new post:', newPost)
+
+ // Publish the new post
+ const updatedPost = await prisma.post.update({
+ where: {
+ id: newPost.id,
+ },
+ data: {
+ published: true,
+ },
+ })
+ console.log(`Published the newly created post: `, updatedPost)
+
+ // Retrieve all posts by user with email alice@prisma.io
+ const postsByUser = await prisma.user
+ .findUnique({
+ where: {
+ email: 'alice@prisma.io',
+ },
+ })
+ .posts()
+ console.log(`Retrieved all posts from a specific user: `, postsByUser)
+}
+
+main()
+ .then(async () => {
+ await prisma.$disconnect()
+ })
+ .catch(async (e) => {
+ console.error(e)
+ await prisma.$disconnect()
+ process.exit(1)
+ })
diff --git a/databases/postgresql-supabase/supabase/.gitignore b/databases/postgresql-supabase/supabase/.gitignore
new file mode 100644
index 000000000000..773c7c3e0a15
--- /dev/null
+++ b/databases/postgresql-supabase/supabase/.gitignore
@@ -0,0 +1,3 @@
+# Supabase
+.branches
+.temp
diff --git a/databases/postgresql-supabase/supabase/config.toml b/databases/postgresql-supabase/supabase/config.toml
new file mode 100644
index 000000000000..c85afddf4958
--- /dev/null
+++ b/databases/postgresql-supabase/supabase/config.toml
@@ -0,0 +1,72 @@
+# A string used to distinguish different Supabase projects on the same host. Defaults to the working
+# directory name when running `supabase init`.
+project_id = "postgresql-supabase"
+
+[api]
+# Port to use for the API URL.
+port = 54321
+# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
+# endpoints. public and storage are always included.
+schemas = ["public", "storage", "graphql_public"]
+# Extra schemas to add to the search_path of every request. public is always included.
+extra_search_path = ["public", "extensions"]
+# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
+# for accidental or malicious requests.
+max_rows = 1000
+
+[db]
+# Port to use for the local database URL.
+port = 54322
+# The database major version to use. This has to be the same as your remote database's. Run `SHOW
+# server_version;` on the remote database to check.
+major_version = 15
+
+[studio]
+# Port to use for Supabase Studio.
+port = 54323
+
+# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they
+# are monitored, and you can view the emails that would have been sent from the web interface.
+[inbucket]
+# Port to use for the email testing server web interface.
+port = 54324
+smtp_port = 54325
+pop3_port = 54326
+
+[storage]
+# The maximum file size allowed (e.g. "5MB", "500KB").
+file_size_limit = "50MiB"
+
+[auth]
+# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used
+# in emails.
+site_url = "http://localhost:3000/"
+# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
+additional_redirect_urls = ["https://localhost:3000/"]
+# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 seconds (one
+# week).
+jwt_expiry = 3600
+# Allow/disallow new user signups to your project.
+enable_signup = true
+
+[auth.email]
+# Allow/disallow new user signups via email to your project.
+enable_signup = true
+# If enabled, a user will be required to confirm any email change on both the old, and new email
+# addresses. If disabled, only the new email is required to confirm.
+double_confirm_changes = true
+# If enabled, users need to confirm their email address before signing in.
+enable_confirmations = false
+
+# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,
+# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin`, `notion`, `twitch`,
+# `twitter`, `slack`, `spotify`, `workos`, `zoom`.
+[auth.external.apple]
+enabled = false
+client_id = ""
+secret = ""
+# Overrides the default auth redirectUrl.
+redirect_uri = ""
+# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure,
+# or any other third-party OIDC providers.
+url = ""
diff --git a/databases/postgresql-supabase/tsconfig.json b/databases/postgresql-supabase/tsconfig.json
new file mode 100644
index 000000000000..f66715dcb8e2
--- /dev/null
+++ b/databases/postgresql-supabase/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "outDir": "dist",
+ "strict": true,
+ "lib": [
+ "esnext",
+ "dom"
+ ],
+ "esModuleInterop": true
+ }
+}
\ No newline at end of file
diff --git a/databases/prisma-postgres/.env.example b/databases/prisma-postgres/.env.example
new file mode 100644
index 000000000000..01ec50883c4c
--- /dev/null
+++ b/databases/prisma-postgres/.env.example
@@ -0,0 +1 @@
+DATABASE_URL=""
diff --git a/databases/prisma-postgres/.gitignore b/databases/prisma-postgres/.gitignore
new file mode 100644
index 000000000000..95573799811f
--- /dev/null
+++ b/databases/prisma-postgres/.gitignore
@@ -0,0 +1,3 @@
+node_modules/
+dist/
+*.env
diff --git a/databases/prisma-postgres/README.md b/databases/prisma-postgres/README.md
new file mode 100644
index 000000000000..2979ee8c7bba
--- /dev/null
+++ b/databases/prisma-postgres/README.md
@@ -0,0 +1,140 @@
+# Prisma Postgres Example: Queries, Connection Pooling & Caching
+
+This project contains a sample application demonstrating various capabilities and workflows of [Prisma Postgres](https://prisma.io/data-platform/postgres):
+
+- Schema migrations and queries (via [Prisma ORM](https://www.prisma.io/orm))
+- Connection pooling and caching (via [Prisma Accelerate](https://prisma.io/data-platform/accelerate))
+
+## Getting started
+
+### 1. Set up a Prisma Postgres database in Prisma Data Platform
+
+Follow these steps to create your Prisma Postgres database:
+
+1. Log in to [Prisma Data Platform](https://console.prisma.io/).
+1. In a [workspace](https://www.prisma.io/docs/platform/about#workspace) of your choice, click the **New project** button.
+1. Type a name for your project in the **Name** field, e.g. **hello-ppg**.
+1. In the **Prisma Postgres** section, click the **Get started** button.
+1. In the **Region** dropdown, select the region that's closest to your current location, e.g. **US East (N. Virginia)**.
+1. Click the **Create project** button.
+
+At this point, you'll be redirected to the **Database** page where you will need to wait a few seconds while the status of your database changes from **`PROVISIONING`**, to **`ACTIVATING`** to **`CONNECTED`**.
+
+Once the green **`CONNECTED`** label appears, your database is ready to use!
+
+Then, find your database credentials in the **Set up database access** section, copy the `DATABASE_URL` environment variable and store it securely.
+
+```bash no-copy
+DATABASE_URL=
+```
+
+> These `DATABASE_URL` environment variable will be required in the next steps.
+
+Once that setup process has finished, move to the next step.
+
+### 2. Download example and install dependencies
+
+Copy the `try-prisma` command that', paste it into your terminal, and execute it:
+
+```terminal
+npx try-prisma@latest \
+ --template databases/prisma-postgres \
+ --name hello-prisma \
+ --install npm
+```
+
+
+
+Navigate into the project directory and (if you haven't done so via the CLI wizard) install dependencies:
+
+```terminal
+cd hello-prisma
+npm install
+```
+
+### 3. Set database connection
+
+The connection to your database is configured via environment variables in a `.env` file.
+
+First, rename the existing `.env.example` file to just `.env`:
+
+```terminal
+mv .env.example .env
+```
+
+Then, find your database credentials in the **Set up database access** section, copy the `DATABASE_URL` environment variable and paste them into the `.env` file.
+
+For reference, the file should now look similar to this:
+
+```bash
+DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=ey...."
+```
+
+### 4. Create database tables (with a schema migration)
+
+Next, you need to create the tables in your database. You can do this by creating and executing a schema migration with the following command of the Prisma CLI:
+
+```terminal
+npx prisma migrate dev --name init
+```
+
+This will map the `User` and `Post` models that are defined in your [Prisma schema](./prisma/schema.prisma) to your database. You can also review the SQL migration that was executed and created the tables in the newly created `prisma/migrations` directory.
+
+### 5. Execute queries with Prisma ORM
+
+The [`src/queries.ts`](./src/queries.ts) script contains a number of CRUD queries that will write and read data in your database. You can execute it by running the following command in your terminal:
+
+```terminal
+npm run queries
+```
+
+Once the script has completed, you can inspect the logs in your terminal or use Prisma Studio to explore what records have been created in the database:
+
+```terminal
+npx prisma studio
+```
+
+### 6. Explore caching with Prisma Accelerate
+
+The [`src/caching.ts`](./src/caching.ts) script contains a sample query that uses [Stale-While-Revalidate](https://www.prisma.io/docs/accelerate/caching#stale-while-revalidate-swr) (SWR) and [Time-To-Live](https://www.prisma.io/docs/accelerate/caching#time-to-live-ttl) (TTL) to cache a database query using Prisma Accelerate. You can execute it as follows:
+
+```terminal
+npm run caching
+```
+
+Take note of the time that it took to execute the query, e.g.:
+
+```terminal
+The query took 2009.2467149999998ms.
+```
+
+Now, run the script again:
+
+```terminal
+npm run caching
+```
+
+You'll notice that the time the query took will be a lot shorter this time, e.g.:
+
+```terminal
+The query took 300.5655280000001ms.
+```
+
+## Next steps
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/databases/prisma-postgres/package.json b/databases/prisma-postgres/package.json
new file mode 100644
index 000000000000..5e6f90880ab0
--- /dev/null
+++ b/databases/prisma-postgres/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "hello-prisma",
+ "license": "MIT",
+ "scripts": {
+ "queries": "ts-node ./src/queries.ts",
+ "caching": "ts-node ./src/caching.ts"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "@prisma/extension-accelerate": "2.0.2",
+ "@types/node": "22.15.32",
+ "dotenv": "16.6.1"
+ },
+ "devDependencies": {
+ "prisma": "6.9.0",
+ "ts-node": "10.9.2",
+ "typescript": "5.8.2"
+ }
+}
diff --git a/databases/prisma-postgres/prisma/schema.prisma b/databases/prisma-postgres/prisma/schema.prisma
new file mode 100644
index 000000000000..393a98e41f13
--- /dev/null
+++ b/databases/prisma-postgres/prisma/schema.prisma
@@ -0,0 +1,24 @@
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String?
+ published Boolean @default(false)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
diff --git a/databases/prisma-postgres/src/caching.ts b/databases/prisma-postgres/src/caching.ts
new file mode 100644
index 000000000000..c609c985e414
--- /dev/null
+++ b/databases/prisma-postgres/src/caching.ts
@@ -0,0 +1,42 @@
+import { PrismaClient } from '@prisma/client';
+import { withAccelerate } from '@prisma/extension-accelerate';
+
+const prisma = new PrismaClient()
+ .$extends(withAccelerate());
+
+async function main() {
+
+ const startTime = performance.now();
+
+ // Learn more about caching strategies:
+ // https://www.prisma.io/docs/accelerate/caching
+ const cachedUsersWithPosts = await prisma.user.findMany({
+ where: {
+ email: { contains: "alice" }
+ },
+ include: { posts: true },
+ cacheStrategy: {
+ swr: 30, // 30 seconds
+ ttl: 60 // 60 seconds
+ }
+ });
+
+ const endTime = performance.now();
+
+ // Calculate the elapsed time
+ const elapsedTime = endTime - startTime;
+
+ console.log(`The query took ${elapsedTime}ms.`);
+ console.log(`It returned the following data: \n`, cachedUsersWithPosts);
+
+}
+
+main()
+ .then(async () => {
+ await prisma.$disconnect();
+ })
+ .catch(async (e) => {
+ console.error(e);
+ await prisma.$disconnect();
+ process.exit(1);
+ });
diff --git a/databases/prisma-postgres/src/queries.ts b/databases/prisma-postgres/src/queries.ts
new file mode 100644
index 000000000000..5bcd8029c7bd
--- /dev/null
+++ b/databases/prisma-postgres/src/queries.ts
@@ -0,0 +1,110 @@
+import { PrismaClient } from '@prisma/client';
+import { withAccelerate } from '@prisma/extension-accelerate';
+
+const prisma = new PrismaClient()
+ .$extends(withAccelerate());
+
+// A `main` function so that we can use async/await
+async function main() {
+
+ const user1Email = `alice${Date.now()}@prisma.io`;
+ const user2Email = `bob${Date.now()}@prisma.io`;
+
+ // Seed the database with users and posts
+ const user1 = await prisma.user.create({
+ data: {
+ email: user1Email,
+ name: 'Alice',
+ posts: {
+ create: {
+ title: 'Join the Prisma community on Discord',
+ content: 'https://pris.ly/discord',
+ published: true,
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+ });
+ const user2 = await prisma.user.create({
+ data: {
+ email: user2Email,
+ name: 'Bob',
+ posts: {
+ create: [
+ {
+ title: 'Check out Prisma on YouTube',
+ content: 'https://pris.ly/youtube',
+ published: true,
+ },
+ {
+ title: 'Follow Prisma on Twitter',
+ content: 'https://twitter.com/prisma/',
+ published: false,
+ },
+ ],
+ },
+ },
+ include: {
+ posts: true,
+ },
+ });
+ console.log(
+ `Created users: ${user1.name} (${user1.posts.length} post) and ${user2.name} (${user2.posts.length} posts) `,
+ );
+
+ // Retrieve all published posts
+ const allPosts = await prisma.post.findMany({
+ where: { published: true },
+ });
+ console.log(`Retrieved all published posts: ${JSON.stringify(allPosts)}`);
+
+ // Create a new post (written by an already existing user with email alice@prisma.io)
+ const newPost = await prisma.post.create({
+ data: {
+ title: 'Join the Prisma Discord community',
+ content: 'https://pris.ly/discord',
+ published: false,
+ author: {
+ connect: {
+ email: user1Email,
+ },
+ },
+ },
+ });
+ console.log(`Created a new post: ${JSON.stringify(newPost)}`);
+
+ // Publish the new post
+ const updatedPost = await prisma.post.update({
+ where: {
+ id: newPost.id,
+ },
+ data: {
+ published: true,
+ },
+ });
+ console.log(`Published the newly created post: ${JSON.stringify(updatedPost)}`);
+
+ // Retrieve all posts by user with email alice@prisma.io
+ const postsByUser = await prisma.post
+ .findMany({
+ where: {
+ author: {
+ email: user1Email
+ }
+ },
+ });
+ console.log(`Retrieved all posts from a specific user: ${JSON.stringify(postsByUser)}`);
+
+}
+
+main()
+ .then(async () => {
+ await prisma.$disconnect();
+ })
+ .catch(async (e) => {
+ console.error(e);
+ await prisma.$disconnect();
+ process.exit(1);
+ });
diff --git a/databases/prisma-postgres/tsconfig.json b/databases/prisma-postgres/tsconfig.json
new file mode 100644
index 000000000000..86758c0f7a5d
--- /dev/null
+++ b/databases/prisma-postgres/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "outDir": "dist",
+ "strict": true,
+ "lib": ["esnext"],
+ "esModuleInterop": true
+ }
+}
diff --git a/databases/sql-server/.gitignore b/databases/sql-server/.gitignore
new file mode 100644
index 000000000000..e12d4e423842
--- /dev/null
+++ b/databases/sql-server/.gitignore
@@ -0,0 +1,3 @@
+node_modules/
+dist/
+*.env*
diff --git a/databases/sql-server/README.md b/databases/sql-server/README.md
new file mode 100644
index 000000000000..b7b215b4f9ce
--- /dev/null
+++ b/databases/sql-server/README.md
@@ -0,0 +1,98 @@
+# Microsoft SQL Server example
+
+This example shows how to connect Prisma to an SQL Server database, create the database schema with [Prisma Migrate](https://www.prisma.io/migrate) and use [Prisma Client](https://www.prisma.io/client) in a **Node.js script** to read and write data in an SQL Server database.
+
+You can find the Prisma schema in [`./prisma/schema.prisma`](./prisma/schema.prisma) from which the SQL for the database schema is generated.
+
+The example consists of two parts:
+
+- `tests/prisma.test.ts`: Jest test (in TypeScript) with a variety of Prisma Client queries and assertions to showcase access patterns
+- `src/script.js`: Node.js script with queries similar to the ones in the test.
+
+## How to use
+
+### 1. Download example & install dependencies
+
+Clone this repository:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+```
+
+Install npm dependencies:
+
+```
+cd prisma-examples/databases/sql-server
+npm install
+```
+
+### 2. Start SQL Server with Docker Compose
+
+Run the following command from the `sql-server` folder to start SQL Server:
+
+```
+docker-compose up -d
+```
+
+> **Note:** The `docker-compose.yml` is where the super admin password is set with the `SA_PASSWORD` environment variable
+
+### 3. Configure the database connection URL
+
+Prisma will use the `DATABASE_URL` environment variable in `prisma/.env` to connect to the database.
+
+
+Create the file:
+
+```
+touch prisma/.env
+```
+
+Then add the following line:
+
+```
+DATABASE_URL=sqlserver://localhost:1433;database=prisma-demo;user=SA;password=Pr1sm4_Pr1sm4;trustServerCertificate=true;encrypt=true
+```
+
+> **Note:** `DATABASE_URL` uses the `SA` (super admin) user of the database and the same password as defined in `docker-compose.yml`. In production it's recommend to create a dedicated user with only the necessary permissions.
+
+### 4. Create the database schema in SQL Server with Prisma Migrate
+
+Now that you have defined the `DATABASE_URL` in `prisma/.env`, you will use Prisma Migrate to create a migration file with the SQL necessary to create the database schema.
+
+Run the following command from the `sql-server` folder:
+
+```
+npx prisma migrate dev --name "init"
+```
+
+You should see the following output:
+```
+Your database is now in sync with your schema.
+```
+
+> **Note:** The `prisma migrate dev` command will automatically generate Prisma Client for use in `script.js`.
+
+### 5. Run the tests and script
+
+To run the test in `tests/prisma.test.ts`, run the following command:
+
+```
+npm run test
+```
+
+To run the script `src/script.js`, run the following command:
+
+```
+npm run start
+```
+
+
+As a next step, explore the `script.js` file to see how to use Prisma Client to read and write data in the database.
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/databases/sql-server/docker-compose.yml b/databases/sql-server/docker-compose.yml
new file mode 100644
index 000000000000..78ef8e207bbe
--- /dev/null
+++ b/databases/sql-server/docker-compose.yml
@@ -0,0 +1,17 @@
+# https://hub.docker.com/_/microsoft-mssql-server
+# https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-ver15&pivots=cs1-bash
+
+version: '3'
+services:
+ sqlserver:
+ image: mcr.microsoft.com/mssql/server:2019-latest
+ restart: always
+ ports:
+ - '1433:1433'
+ environment:
+ SA_PASSWORD: 'Pr1sm4_Pr1sm4'
+ ACCEPT_EULA: 'Y'
+ volumes:
+ - mssql:/var/opt/mssql
+volumes:
+ mssql:
diff --git a/databases/sql-server/jest.config.js b/databases/sql-server/jest.config.js
new file mode 100644
index 000000000000..87c30aa4a773
--- /dev/null
+++ b/databases/sql-server/jest.config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+}
diff --git a/databases/sql-server/package.json b/databases/sql-server/package.json
new file mode 100644
index 000000000000..5c91aa64b5f9
--- /dev/null
+++ b/databases/sql-server/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "sql-server-example",
+ "version": "1.0.0",
+ "keywords": [],
+ "license": "ISC",
+ "author": "",
+ "main": "index.js",
+ "scripts": {
+ "start": "node ./src/script.js",
+ "test": "jest",
+ "test:watch": "jest --watch"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "jest": "29.7.0"
+ },
+ "devDependencies": {
+ "@types/jest": "29.5.14",
+ "prettyjson": "1.2.5",
+ "prisma": "6.9.0",
+ "ts-jest": "29.4.5",
+ "ts-node": "10.9.2",
+ "ts-node-dev": "2.0.0",
+ "typescript": "5.8.2"
+ }
+}
diff --git a/databases/sql-server/prisma/schema.prisma b/databases/sql-server/prisma/schema.prisma
new file mode 100644
index 000000000000..c40491acc60b
--- /dev/null
+++ b/databases/sql-server/prisma/schema.prisma
@@ -0,0 +1,45 @@
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "sqlserver"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ email String @unique
+ name String?
+ comments Comment[]
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ title String
+ content String?
+ published Boolean @default(false)
+ authorId Int
+ author User @relation(fields: [authorId], references: [id])
+ comments Comment[]
+ tags Tag[] @relation("TagToPost")
+}
+
+model Comment {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ comment String
+ writtenById Int
+ postId Int
+ writtenBy User @relation(fields: [writtenById], references: [id])
+ post Post @relation(fields: [postId], references: [id], onUpdate: NoAction)
+}
+
+model Tag {
+ id Int @id @default(autoincrement())
+ tag String @unique
+ posts Post[] @relation("TagToPost")
+}
diff --git a/databases/sql-server/src/script.js b/databases/sql-server/src/script.js
new file mode 100644
index 000000000000..47e84b9968ed
--- /dev/null
+++ b/databases/sql-server/src/script.js
@@ -0,0 +1,258 @@
+// @ts-check
+const { PrismaClient } = require('@prisma/client')
+const prettyjson = require('prettyjson')
+
+const prisma = new PrismaClient()
+
+// A `main` function so that we can use async/await
+async function main() {
+ const tags = await Promise.all([
+ prisma.tag.create({
+ data: {
+ tag: 'Node.js',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'TypeScript',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Prisma',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Databases',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Microsoft',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'GraphQL',
+ },
+ }),
+ ])
+
+ console.log('Created tags: \n', prettyjson.render(tags))
+
+ // Seed the database with users and posts
+ const user1 = await prisma.user.create({
+ data: {
+ email: 'alice@prisma.io',
+ name: 'Alice',
+ posts: {
+ create: {
+ title: 'Bringing value to users with rapid deployment',
+ published: true,
+ tags: {
+ connect: {
+ tag: 'Prisma',
+ },
+ },
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+ })
+
+ console.log('Created first user: \n', prettyjson.render(user1))
+
+ const user2 = await prisma.user.create({
+ data: {
+ email: 'shakuntala@prisma.io',
+ name: 'Shakuntala',
+ comments: {
+ create: {
+ comment:
+ 'Thanks for sharing. Reducing the size of our releases and deployment more frequently has allowed us to bring more value to our customers.',
+ post: {
+ connect: {
+ id: user1.posts[0].id,
+ },
+ },
+ },
+ },
+ posts: {
+ create: [
+ {
+ title: 'Introducing to Prisma with MSSQL',
+ published: true,
+ content:
+ 'Check out the Prisma blog at https://www.prisma.io/blog for more information',
+ tags: {
+ connect: [
+ {
+ tag: 'Node.js',
+ },
+ {
+ tag: 'Microsoft',
+ },
+ {
+ tag: 'Databases',
+ },
+ ],
+ },
+ },
+ {
+ title: 'Zero cost type safety with Prisma',
+ published: true,
+ tags: {
+ connect: [
+ {
+ tag: 'Node.js',
+ },
+ {
+ tag: 'Databases',
+ },
+ ],
+ },
+ },
+ {
+ title: 'GraphQL Authentication simplified',
+ published: false,
+ },
+ ],
+ },
+ },
+ include: {
+ posts: {
+ include: {
+ tags: true,
+ },
+ },
+ comments: {
+ include: {
+ post: true,
+ },
+ },
+ },
+ })
+
+ console.log('Created second user: \n', prettyjson.render(user2))
+
+ const taggedPosts = await prisma.tag.findUnique({
+ where: {
+ tag: 'Node.js',
+ },
+ include: {
+ posts: true,
+ },
+ })
+
+ console.log(
+ 'Retrieved all posts with the Node.js tag: ',
+ prettyjson.render(taggedPosts),
+ )
+
+ // Retrieve all published posts with a tag
+ const allPosts = await prisma.post.findMany({
+ where: {
+ AND: [
+ { published: true },
+ {
+ tags: {
+ some: {
+ tag: 'Node.js',
+ },
+ },
+ },
+ ],
+ },
+ })
+ console.log(
+ `Retrieved all published posts with the Node.js tag: `,
+ prettyjson.render(allPosts),
+ )
+
+ // Create a new post (written by an already existing user with email alice@prisma.io)
+ const newPost = await prisma.post.create({
+ data: {
+ title: 'Join the Prisma Discord community',
+ content: 'https://pris.ly/discord',
+ published: false,
+ author: {
+ connect: {
+ email: 'alice@prisma.io', // Should have been created during initial seeding
+ },
+ },
+ tags: {
+ connectOrCreate: {
+ create: {
+ tag: 'Community',
+ },
+ where: {
+ tag: 'Community',
+ },
+ },
+ connect: {
+ tag: 'Prisma',
+ },
+ },
+ comments: {
+ create: {
+ comment: 'Looking forward to joining to Prisma community.',
+ writtenBy: {
+ connect: {
+ email: 'shakuntala@prisma.io',
+ },
+ },
+ },
+ },
+ },
+ include: {
+ comments: {
+ include: {
+ writtenBy: true,
+ },
+ },
+ tags: true,
+ },
+ })
+ console.log(`Created a new post: \n`, prettyjson.render(newPost))
+
+ // Publish the new post
+ const updatedPost = await prisma.post.update({
+ where: {
+ id: newPost.id,
+ },
+ data: {
+ published: true,
+ },
+ })
+ console.log(`Published the newly created post: `, updatedPost)
+
+ // Retrieve all posts by user with email alice@prisma.io
+ const postsByUser = await prisma.user
+ .findUnique({
+ where: {
+ email: 'alice@prisma.io',
+ },
+ })
+ .posts()
+ console.log(`Retrieved all posts from a specific user: `, postsByUser)
+}
+
+async function clearDB() {
+ await prisma.tag.deleteMany({})
+ await prisma.comment.deleteMany({})
+ await prisma.post.deleteMany({})
+ await prisma.user.deleteMany({})
+}
+
+clearDB()
+ .then(main)
+ .catch((e) => {
+ console.error(e)
+ process.exit(1)
+ })
+ .finally(async () => {
+ await prisma.$disconnect()
+ })
diff --git a/databases/sql-server/tests/prisma.test.ts b/databases/sql-server/tests/prisma.test.ts
new file mode 100644
index 000000000000..b2983531d026
--- /dev/null
+++ b/databases/sql-server/tests/prisma.test.ts
@@ -0,0 +1,295 @@
+import { PrismaClient } from '@prisma/client'
+
+export const prisma = new PrismaClient()
+
+describe('example test with Prisma Client', () => {
+ beforeAll(async () => {
+ await prisma.tag.deleteMany({})
+ await prisma.comment.deleteMany({})
+ await prisma.post.deleteMany({})
+ await prisma.user.deleteMany({})
+ })
+ afterAll(async () => {
+ await prisma.$disconnect()
+ })
+ test('test query', async () => {
+ const data = await prisma.user.findMany({ take: 1, select: { id: true } })
+ expect(data).toBeTruthy()
+ })
+
+ test('create tags', async () => {
+ const tags = await Promise.all([
+ prisma.tag.create({
+ data: {
+ tag: 'Node.js',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'TypeScript',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Prisma',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Databases',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'Microsoft',
+ },
+ }),
+ prisma.tag.create({
+ data: {
+ tag: 'GraphQL',
+ },
+ }),
+ ])
+
+ expect(tags.length).toEqual(6)
+ expect(typeof tags[0].id).toEqual('number')
+ expect(tags[0].tag).toBeTruthy()
+ })
+
+ test('create two user with posts comments and tags', async () => {
+ let email = 'alice@prisma.io'
+ let name = 'Alice'
+
+ const user1 = await prisma.user.create({
+ data: {
+ email,
+ name,
+ posts: {
+ create: {
+ title: 'Bringing value to users with rapid deployment',
+ published: true,
+ tags: {
+ connect: {
+ tag: 'Prisma',
+ },
+ },
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+ })
+
+ expect(user1.id).toBeTruthy()
+ expect(user1.name).toEqual(name)
+ expect(user1.email).toEqual(email)
+ expect(
+ user1.createdAt.getMonth() === new Date().getMonth() &&
+ user1.createdAt.getFullYear() === new Date().getFullYear(),
+ ).toBeTruthy()
+ expect(user1.posts.length).toEqual(1)
+ expect(user1.posts[0].published).toEqual(true)
+
+ email = 'shakuntala@prisma.io'
+ name = 'Shakuntala'
+
+ const user2 = await prisma.user.create({
+ data: {
+ name,
+ email,
+ comments: {
+ create: {
+ comment:
+ 'Thanks for sharing. Reducing the size of our releases and deployment more frequently has allowed us to bring more value to our customers.',
+ post: {
+ connect: {
+ id: user1.posts[0].id,
+ },
+ },
+ },
+ },
+ posts: {
+ create: [
+ {
+ title: 'Introducing to Prisma with MSSQL',
+ published: true,
+ content:
+ 'Check out the Prisma blog at https://www.prisma.io/blog for more information',
+ tags: {
+ // Creates the rows in the m-n relation table
+ connect: [
+ {
+ tag: 'Node.js',
+ },
+ {
+ tag: 'Microsoft',
+ },
+ {
+ tag: 'Databases',
+ },
+ ],
+ },
+ },
+ {
+ title: 'Zero cost type safety with Prisma',
+ published: true,
+ tags: {
+ // Creates the rows in the m-n relation table
+ connect: [
+ {
+ tag: 'Node.js',
+ },
+ {
+ tag: 'Databases',
+ },
+ ],
+ },
+ },
+ {
+ title: 'GraphQL Authentication simplified',
+ published: false,
+ },
+ ],
+ },
+ },
+ include: {
+ posts: {
+ include: {
+ tags: true,
+ },
+ },
+ comments: {
+ include: {
+ post: true,
+ },
+ },
+ },
+ })
+
+ expect(user2.id).toBeTruthy()
+ expect(user2.name).toEqual(name)
+ expect(user2.email).toEqual(email)
+ expect(user2.posts.length).toEqual(3)
+ expect(user2.posts[0].authorId).toEqual(user2.id)
+ expect(user2.posts[0].tags[0].id).toBeTruthy()
+ expect(
+ user2.comments[0].comment.toLowerCase().includes('thanks'),
+ ).toBeTruthy()
+ expect(user2.comments[0].postId).toEqual(user1.posts[0].id)
+
+ expect(
+ user2.createdAt.getMonth() === new Date().getMonth() &&
+ user2.createdAt.getFullYear() === new Date().getFullYear(),
+ ).toBeTruthy()
+
+ const updatedName = 'Shakuntala Devi'
+ const updatedUser2 = await prisma.user.update({
+ data: {
+ name: updatedName,
+ },
+ where: {
+ id: user2.id,
+ },
+ })
+
+ expect(updatedUser2.name).toEqual(updatedName)
+ })
+
+ test('Get all published posts with a given tag', async () => {
+ // Retrieve all published posts
+ const taggedPosts = await prisma.tag.findUnique({
+ where: {
+ tag: 'Node.js',
+ },
+ include: {
+ posts: true,
+ },
+ })
+ expect(taggedPosts).toBeTruthy()
+ expect(taggedPosts?.tag).toEqual('Node.js')
+ expect(taggedPosts?.posts.length).toEqual(2)
+ })
+
+ test('Create unpublished post with tags and comments for an existing user and then publish', async () => {
+ const newPost = await prisma.post.create({
+ data: {
+ title: 'Join the Prisma Discord community',
+ content: 'https://pris.ly/discord',
+ published: false,
+ author: {
+ connect: {
+ email: 'alice@prisma.io', // Should have been created during initial seeding
+ },
+ },
+ tags: {
+ connectOrCreate: {
+ create: {
+ tag: 'Community',
+ },
+ where: {
+ tag: 'Community',
+ },
+ },
+ connect: {
+ tag: 'Prisma',
+ },
+ },
+ comments: {
+ create: {
+ comment: 'Looking forward to joining to Prisma community.',
+ writtenBy: {
+ connect: {
+ email: 'shakuntala@prisma.io',
+ },
+ },
+ },
+ },
+ },
+ include: {
+ comments: true,
+ tags: true,
+ },
+ })
+ expect(newPost).toBeTruthy()
+ expect(newPost.tags.length).toEqual(2)
+ expect(newPost.tags[0].tag).toBeTruthy()
+ expect(newPost.comments.length).toEqual(1)
+
+ //
+ await prisma.post.update({
+ where: {
+ id: newPost.id,
+ },
+ data: {
+ published: true,
+ },
+ })
+ })
+
+ test('Find comments by a user', async () => {
+ // Retrieve all published posts
+ const userComments = await prisma.user
+ .findUnique({
+ where: {
+ email: 'shakuntala@prisma.io',
+ },
+ })
+ .comments()
+ expect(userComments).toBeTruthy()
+ expect(userComments?.length).toEqual(2)
+ })
+
+ test('Fetch posts by a user', async () => {
+ // Retrieve all published posts
+ const userPosts = await prisma.user
+ .findUnique({
+ where: {
+ email: 'shakuntala@prisma.io',
+ },
+ })
+ .posts()
+ expect(userPosts).toBeTruthy()
+ expect(userPosts?.length).toEqual(3)
+ })
+})
diff --git a/databases/sql-server/tsconfig.json b/databases/sql-server/tsconfig.json
new file mode 100644
index 000000000000..a8744c799f6d
--- /dev/null
+++ b/databases/sql-server/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "outDir": "dist",
+ "target": "ES2018",
+ "module": "commonjs",
+ "strict": true,
+ "lib": ["esnext"],
+ "esModuleInterop": true
+ },
+ "exclude": ["dist"],
+ "include": ["tests"]
+}
diff --git a/databases/turso/.gitignore b/databases/turso/.gitignore
new file mode 100644
index 000000000000..11ddd8dbe662
--- /dev/null
+++ b/databases/turso/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+# Keep environment variables out of version control
+.env
diff --git a/databases/turso/README.md b/databases/turso/README.md
new file mode 100644
index 000000000000..21a8ece89f43
--- /dev/null
+++ b/databases/turso/README.md
@@ -0,0 +1,84 @@
+# Prisma with Turso Example
+
+This example demonstrates how to use [Prisma ORM](https://www.prisma.io/) with [Turso](https://turso.tech/), a distributed database based on libSQL. The project showcases how to perform CRUD operations using [Prisma Client](https://www.prisma.io/docs/orm/prisma-client) in a **Node.js script**.
+
+## How to use
+
+### 1. Download example and navigate into the project directory
+
+Download this example:
+
+```
+npx try-prisma@latest --template databases/turso
+```
+
+Then, navigate into the project directory:
+
+```
+cd turso
+```
+
+Alternative: Clone the entire repo
+
+Clone this repository:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+```
+
+### 2. Install npm dependencies:
+
+```
+cd prisma-examples/databases/turso
+npm install
+```
+
+
+
+### 3. Configure the database connection
+Create a .env file in the root of the project and add your Turso credentials:
+```sh
+touch .env
+```
+If you don't have an existing database, you can provision a database by running the following command:
+```sh
+turso db create turso-prisma-db
+```
+The above command will create a database in the closest region to your location.
+
+Run the following command to retrieve your database's connection string:
+```sh
+turso db show turso-prisma-db
+```
+Next, create an authentication token that will allow you to connect to the database:
+```sh
+turso db tokens create turso-prisma-db
+```
+Update your .env file with the authentication token and connection string:
+```sh
+TURSO_DATABASE_URL="your_turso_database_url"
+TURSO_AUTH_TOKEN="your_turso_auth_token"
+```
+You can learn more from the [Prisma Turso documentation](https://www.prisma.io/docs/orm/overview/databases/turso#what-is-turso)
+
+### 4. Generate Prisma Client
+```sh
+npx prisma generate
+```
+### 5. Run the script
+Execute the script to create, retrieve, update, and delete data:
+```sh
+npm run dev
+```
+### 6. Understanding the project structure
+- `prisma/schema.prisma`: Defines the database schema for Users and Posts.
+- `src/script.ts`: A script demonstrating CRUD operations using Prisma Client.
+- `.env`: Stores environment variables for database credentials.
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/databases/turso/package.json b/databases/turso/package.json
new file mode 100644
index 000000000000..c326790e96b1
--- /dev/null
+++ b/databases/turso/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "turso",
+ "version": "1.0.0",
+ "main": "index.js",
+ "scripts": {
+ "dev": "ts-node src/script.ts"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "description": "",
+ "devDependencies": {
+ "@types/node": "22.15.32",
+ "prisma": "6.9.0",
+ "ts-node": "10.9.2",
+ "typescript": "5.8.2"
+ },
+ "dependencies": {
+ "@libsql/client": "0.15.14",
+ "@prisma/adapter-libsql": "6.9.0",
+ "@prisma/client": "6.9.0",
+ "dotenv": "16.6.1"
+ }
+}
diff --git a/databases/turso/prisma/schema.prisma b/databases/turso/prisma/schema.prisma
new file mode 100644
index 000000000000..4b14249478f5
--- /dev/null
+++ b/databases/turso/prisma/schema.prisma
@@ -0,0 +1,34 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
+// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
+
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["driverAdapters", "typedSql"]
+}
+
+datasource db {
+ provider = "sqlite"
+ url = "file:./dev.db"
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ title String
+ content String?
+ published Boolean @default(false)
+ viewCount Int @default(0)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
diff --git a/databases/turso/src/script.ts b/databases/turso/src/script.ts
new file mode 100644
index 000000000000..bcfdfde817ed
--- /dev/null
+++ b/databases/turso/src/script.ts
@@ -0,0 +1,95 @@
+require('dotenv').config()
+import { PrismaClient } from '@prisma/client'
+import { PrismaLibSQL } from '@prisma/adapter-libsql'
+import { createClient } from '@libsql/client'
+
+
+const libsql = createClient({
+ url: `${process.env.TURSO_DATABASE_URL}`,
+ authToken: `${process.env.TURSO_AUTH_TOKEN}`,
+})
+
+const adapter = new PrismaLibSQL(libsql)
+const prisma = new PrismaClient({ adapter })
+
+async function main() {
+ // create user
+ const user = await prisma.user.create({
+ data: {
+ email: 'hana@hana.io',
+ name: 'Hana',
+ },
+ })
+
+ console.log(user)
+
+ // find user
+ const foundUser = await prisma.user.findUnique({
+ where: {
+ email: 'hana@hana.io'
+ }
+ })
+ console.log(foundUser)
+
+ // update user
+ const updatedUser = await prisma.user.update({
+ where: {
+ email: 'hana@hana.io',
+ },
+ data: {
+ name: 'Peters',
+ },
+ })
+ console.log(updatedUser)
+
+ // delete user
+ const deleteUser = await prisma.user.delete({
+ where: {
+ email: 'hana@hana.io',
+ }
+ })
+ console.log("User deleted", deleteUser)
+
+ // create user with posts
+ const userPosts = await prisma.user.create({
+ data: {
+ email: 'dave@prisma.io',
+ name: 'David',
+ posts: {
+ create: [
+ { title: 'Hello world' },
+ { title: 'Introduction to Prisma with Mongo' },
+ { title: 'MongoDB and schemas' },
+ ],
+ },
+ },
+ include: {
+ posts: true,
+ },
+ })
+
+ console.dir(userPosts, { depth: Infinity })
+
+ // find posts
+ const posts = await prisma.post.findMany({
+ include: {
+ author: true,
+ },
+ orderBy: {
+ createdAt: 'desc',
+ },
+ })
+
+ console.dir(posts, { depth: Infinity })
+}
+
+
+
+
+main()
+ .catch(e => {
+ throw e
+ })
+ .finally(async () => {
+ await prisma.$disconnect()
+ })
diff --git a/databases/turso/tsconfig.json b/databases/turso/tsconfig.json
new file mode 100644
index 000000000000..255e8eb5cb1e
--- /dev/null
+++ b/databases/turso/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "outDir": "dist",
+ "strict": true,
+ "lib": [
+ "esnext",
+ "dom"
+ ],
+ "esModuleInterop": true
+ }
+ }
\ No newline at end of file
diff --git a/deployment-platforms/README.md b/deployment-platforms/README.md
new file mode 100644
index 000000000000..93adbd925b1a
--- /dev/null
+++ b/deployment-platforms/README.md
@@ -0,0 +1,11 @@
+# Deployment platforms
+
+The projects in this directory show what "Prisma Client"-based deployment setups look like for various deployment providers. Learn more about [deployment](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/deployment) in the Prisma documentation.
+
+## Additional resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/deployment-platforms/aws-lambda/.env.example b/deployment-platforms/aws-lambda/.env.example
new file mode 100644
index 000000000000..94a87a05ba8c
--- /dev/null
+++ b/deployment-platforms/aws-lambda/.env.example
@@ -0,0 +1 @@
+DATABASE_URL="postgresql://__USER__:__PASSWORD__@__HOST__/__DATABASE__"
\ No newline at end of file
diff --git a/deployment-platforms/aws-lambda/.gitignore b/deployment-platforms/aws-lambda/.gitignore
new file mode 100644
index 000000000000..103fb12b6e38
--- /dev/null
+++ b/deployment-platforms/aws-lambda/.gitignore
@@ -0,0 +1,3 @@
+.serverless/
+node_modules/
+*.env
diff --git a/deployment-platforms/aws-lambda/README.md b/deployment-platforms/aws-lambda/README.md
new file mode 100644
index 000000000000..0f0e51266e79
--- /dev/null
+++ b/deployment-platforms/aws-lambda/README.md
@@ -0,0 +1,20 @@
+# AWS Lambda deployment example
+
+[Deployment Guide](https://www.prisma.io/docs/guides/deployment/deploying-to-aws-lambda)
+
+## Download manually
+
+```bash
+curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/deployment-platforms/aws-lambda
+cd aws-lambda
+```
+
+The Serverless configuration file includes a package pattern that excludes all Prisma Engine binaries but the one relevant for the Lambda runtime. You can read more in our [documentation](https://www.prisma.io/docs/guides/deployment/deployment-guides/deploying-to-aws-lambda#package-pattern-in-serverlessyml).
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/deployment-platforms/aws-lambda/handlers/create-user.js b/deployment-platforms/aws-lambda/handlers/create-user.js
new file mode 100644
index 000000000000..4dd002eda04d
--- /dev/null
+++ b/deployment-platforms/aws-lambda/handlers/create-user.js
@@ -0,0 +1,33 @@
+const {
+ Prisma,
+ PrismaClient
+} = require('@prisma/client')
+const prisma = new PrismaClient()
+
+exports.handler = async (event, context, callback) => {
+ try {
+ const data = JSON.parse(event.body)
+ const createdUser = await prisma.user.create({ data })
+
+ return {
+ statusCode: 200,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(createdUser)
+ }
+ } catch (e) {
+ if (e instanceof Prisma.PrismaClientRequestError) {
+ if (e.code === 'P2002') {
+ return {
+ statusCode: 409,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ error: 'A user with this email already exists'
+ })
+ }
+ }
+ }
+
+ console.error(e)
+ return { statusCode: 500 }
+ }
+}
diff --git a/deployment-platforms/aws-lambda/handlers/posts.js b/deployment-platforms/aws-lambda/handlers/posts.js
new file mode 100644
index 000000000000..2761e4eeea43
--- /dev/null
+++ b/deployment-platforms/aws-lambda/handlers/posts.js
@@ -0,0 +1,23 @@
+const { PrismaClient } = require('@prisma/client')
+
+const prisma = new PrismaClient()
+
+exports.handler = async (event, context, callback) => {
+ try {
+ const posts = await prisma.post.findMany({
+ include: { author: true }
+ })
+ return {
+ statusCode: 200,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(posts)
+ }
+ } catch (error) {
+ console.error(error)
+ return {
+ statusCode: 500,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(error)
+ }
+ }
+}
diff --git a/deployment-platforms/aws-lambda/handlers/seed.js b/deployment-platforms/aws-lambda/handlers/seed.js
new file mode 100644
index 000000000000..6c06e0cf1fef
--- /dev/null
+++ b/deployment-platforms/aws-lambda/handlers/seed.js
@@ -0,0 +1,78 @@
+const { PrismaClient } = require('@prisma/client')
+const prisma = new PrismaClient()
+
+exports.handler = async (event, context, callback) => {
+ try {
+ await Promise.all([prisma.profile.deleteMany(), prisma.post.deleteMany()])
+ await prisma.user.deleteMany()
+
+ const createdUser = await prisma.user.create({
+ data: seedUser,
+ })
+
+ const createdUser2 = await prisma.user.create({
+ data: seedUser2,
+ })
+
+ return {
+ statusCode: 201,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify([createdUser, createdUser2]),
+ }
+ } catch (error) {
+ console.error(error)
+ return { statusCode: 500 }
+ }
+}
+
+const seedUser = {
+ email: 'jane@prisma.io',
+ name: 'Jane',
+ profile: {
+ create: {
+ bio: 'Health Enthusiast',
+ },
+ },
+ posts: {
+ create: [
+ {
+ title: 'Comparing Database Types: How Database Types Evolved to Meet Different Needs',
+ content: 'https://www.prisma.io/blog/comparison-of-database-models-1iz9u29nwn37/',
+ },
+ {
+ title: 'Analysing Sleep Patterns: The Quantified Self',
+ content: 'https://quantifiedself.com/get-started/',
+ },
+ {
+ title: 'Prisma 2 Docs',
+ content: 'https://www.prisma.io/docs/',
+ },
+ ],
+ },
+}
+
+const seedUser2 = {
+ email: 'toru@prisma.io',
+ name: 'Toru Takemitsu',
+ profile: {
+ create: {
+ bio: 'Musician',
+ },
+ },
+ posts: {
+ create: [
+ {
+ title: 'Requiem for String Orchestra',
+ content: '',
+ },
+ {
+ title: 'Music of Tree',
+ content: '',
+ },
+ {
+ title: 'Waves for clarinet, horn, two trombones and bass drum ',
+ content: '',
+ },
+ ],
+ },
+}
diff --git a/deployment-platforms/aws-lambda/handlers/status.js b/deployment-platforms/aws-lambda/handlers/status.js
new file mode 100644
index 000000000000..391596ab138f
--- /dev/null
+++ b/deployment-platforms/aws-lambda/handlers/status.js
@@ -0,0 +1,7 @@
+exports.handler = async (event, context, callback) => {
+ return {
+ statusCode: 200,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ up: true })
+ }
+}
diff --git a/deployment-platforms/aws-lambda/handlers/users.js b/deployment-platforms/aws-lambda/handlers/users.js
new file mode 100644
index 000000000000..43193ad3e1ca
--- /dev/null
+++ b/deployment-platforms/aws-lambda/handlers/users.js
@@ -0,0 +1,22 @@
+const { PrismaClient } = require('@prisma/client')
+const prisma = new PrismaClient()
+
+exports.handler = async (event, context, callback) => {
+ try {
+ const users = await prisma.user.findMany({
+ include: { profile: true }
+ })
+ return {
+ statusCode: 200,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(users)
+ }
+ } catch (error) {
+ console.error(error)
+ return {
+ statusCode: 500,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(error)
+ }
+ }
+}
diff --git a/deployment-platforms/aws-lambda/package.json b/deployment-platforms/aws-lambda/package.json
new file mode 100644
index 000000000000..4b21132009e0
--- /dev/null
+++ b/deployment-platforms/aws-lambda/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "prisma-aws-lambda-example",
+ "license": "MIT",
+ "scripts": {
+ "start": "node index.js",
+ "prisma:introspect": "prisma introspect",
+ "prisma:generate": "prisma generate"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0"
+ },
+ "devDependencies": {
+ "prisma": "6.9.0",
+ "serverless-dotenv-plugin": "6.0.0"
+ }
+}
diff --git a/deployment-platforms/aws-lambda/prisma/schema.prisma b/deployment-platforms/aws-lambda/prisma/schema.prisma
new file mode 100644
index 000000000000..2916fc83765f
--- /dev/null
+++ b/deployment-platforms/aws-lambda/prisma/schema.prisma
@@ -0,0 +1,34 @@
+generator client {
+ provider = "prisma-client-js"
+ binaryTargets = ["native", "rhel-openssl-1.0.x"]
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+model Post {
+ id Int @default(autoincrement()) @id
+ createdAt DateTime @default(now())
+ title String
+ content String?
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id]) // renamed from `User` -> `author`
+ authorId Int // relation scalar field
+}
+
+model Profile {
+ id Int @default(autoincrement()) @id
+ bio String?
+ userId Int @unique // relation scalar field
+ user User @relation(fields: [userId], references: [id]) // renamed from `User` -> `user`
+}
+
+model User {
+ id Int @default(autoincrement()) @id
+ email String @unique
+ name String?
+ posts Post[] // renamed from `Post` -> `posts`
+ profile Profile? // renamed from `Profile` -> `profile`
+}
diff --git a/deployment-platforms/aws-lambda/schema.sql b/deployment-platforms/aws-lambda/schema.sql
new file mode 100644
index 000000000000..2ef007b9e46b
--- /dev/null
+++ b/deployment-platforms/aws-lambda/schema.sql
@@ -0,0 +1,22 @@
+CREATE TABLE "public"."User" (
+ id SERIAL PRIMARY KEY NOT NULL,
+ name VARCHAR(255),
+ email VARCHAR(255) UNIQUE NOT NULL
+);
+
+CREATE TABLE "public"."Post" (
+ id SERIAL PRIMARY KEY NOT NULL,
+ title VARCHAR(255) NOT NULL,
+ "createdAt" TIMESTAMP NOT NULL DEFAULT now(),
+ content TEXT,
+ published BOOLEAN NOT NULL DEFAULT false,
+ "authorId" INTEGER NOT NULL,
+ FOREIGN KEY ("authorId") REFERENCES "public"."User"(id)
+);
+
+CREATE TABLE "public"."Profile" (
+ id SERIAL PRIMARY KEY NOT NULL,
+ bio TEXT,
+ "userId" INTEGER UNIQUE NOT NULL,
+ FOREIGN KEY ("userId") REFERENCES "public"."User"(id)
+);
\ No newline at end of file
diff --git a/deployment-platforms/aws-lambda/serverless.yml b/deployment-platforms/aws-lambda/serverless.yml
new file mode 100644
index 000000000000..b178ae55cdd4
--- /dev/null
+++ b/deployment-platforms/aws-lambda/serverless.yml
@@ -0,0 +1,48 @@
+service: prisma-aws-lambda-example
+plugins:
+ - serverless-dotenv-plugin
+
+provider:
+ name: aws
+ region: us-east-1
+ runtime: nodejs14.x
+
+functions:
+ status:
+ handler: handlers/status.handler
+ events:
+ - http:
+ method: GET
+ path: /
+ seed:
+ handler: handlers/seed.handler
+ events:
+ - http:
+ method: GET
+ path: /seed
+ getUsers:
+ handler: handlers/users.handler
+ events:
+ - http:
+ method: GET
+ path: /users
+ createUser:
+ handler: handlers/create-user.handler
+ events:
+ - http:
+ method: POST
+ path: /users
+ getPosts:
+ handler: handlers/posts.handler
+ events:
+ - http:
+ method: GET
+ path: /posts
+
+# only include the Prisma binary required on AWS Lambda while packaging
+package:
+ patterns:
+ - '!node_modules/.prisma/client/libquery_engine-*'
+ - 'node_modules/.prisma/client/libquery_engine-rhel-*'
+ - '!node_modules/prisma/libquery_engine-*'
+ - '!node_modules/@prisma/engines/**'
diff --git a/deployment-platforms/azure-functions/.funcignore b/deployment-platforms/azure-functions/.funcignore
new file mode 100644
index 000000000000..517922249795
--- /dev/null
+++ b/deployment-platforms/azure-functions/.funcignore
@@ -0,0 +1,7 @@
+*.js.map
+*.ts
+.git*
+.vscode
+local.settings.json
+test
+tsconfig.json
\ No newline at end of file
diff --git a/deployment-platforms/azure-functions/.gitignore b/deployment-platforms/azure-functions/.gitignore
new file mode 100644
index 000000000000..20c2bf39f921
--- /dev/null
+++ b/deployment-platforms/azure-functions/.gitignore
@@ -0,0 +1,100 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+
+package-lock.json
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# vscode config
+.vscode/
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# TypeScript v1 declaration files
+typings/
+
+# Optional npm cache directory
+.npm
+
+# Optional npm cache directory
+
+# Optional eslint cache
+.eslintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+.env.test
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+
+# next.js build output
+.next
+
+# nuxt.js build output
+.nuxt
+
+# vuepress build output
+.vuepress/dist
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TypeScript output
+dist
+out
+
+# Azure Functions artifacts
+bin
+obj
+appsettings.json
diff --git a/deployment-platforms/azure-functions/CreatePost/function.json b/deployment-platforms/azure-functions/CreatePost/function.json
new file mode 100644
index 000000000000..8d021a491551
--- /dev/null
+++ b/deployment-platforms/azure-functions/CreatePost/function.json
@@ -0,0 +1,19 @@
+{
+ "bindings": [
+ {
+ "authLevel": "anonymous",
+ "type": "httpTrigger",
+ "direction": "in",
+ "name": "req",
+ "methods": [
+ "post"
+ ],
+ "route": "post"
+ },
+ {
+ "type": "http",
+ "direction": "out",
+ "name": "$return"
+ }
+ ]
+}
diff --git a/deployment-platforms/azure-functions/CreatePost/index.js b/deployment-platforms/azure-functions/CreatePost/index.js
new file mode 100644
index 000000000000..1e72c7ea0f35
--- /dev/null
+++ b/deployment-platforms/azure-functions/CreatePost/index.js
@@ -0,0 +1,29 @@
+const prisma = require('../lib/prisma')
+
+module.exports = async function (context, req) {
+ const { title, content, authorEmail } = req.body
+ try {
+ const post = await prisma.post.create({
+ data: {
+ title,
+ content,
+ published: false,
+ author: {
+ connect: {
+ email: authorEmail,
+ },
+ },
+ },
+ })
+
+ return {
+ body: post,
+ }
+ } catch (e) {
+ context.log(e)
+ return {
+ status: 500,
+ body: e.message,
+ }
+ }
+}
diff --git a/deployment-platforms/azure-functions/CreateUser/function.json b/deployment-platforms/azure-functions/CreateUser/function.json
new file mode 100644
index 000000000000..730d90a146a9
--- /dev/null
+++ b/deployment-platforms/azure-functions/CreateUser/function.json
@@ -0,0 +1,19 @@
+{
+ "bindings": [
+ {
+ "authLevel": "anonymous",
+ "type": "httpTrigger",
+ "direction": "in",
+ "name": "req",
+ "methods": [
+ "post"
+ ],
+ "route": "user"
+ },
+ {
+ "type": "http",
+ "direction": "out",
+ "name": "$return"
+ }
+ ]
+}
diff --git a/deployment-platforms/azure-functions/CreateUser/index.js b/deployment-platforms/azure-functions/CreateUser/index.js
new file mode 100644
index 000000000000..7fb1a69b1cb7
--- /dev/null
+++ b/deployment-platforms/azure-functions/CreateUser/index.js
@@ -0,0 +1,24 @@
+const prisma = require('../lib/prisma')
+
+module.exports = async function (context, req) {
+ const { email, name } = req.body
+ try {
+ const user = await prisma.user.create({
+ data: {
+ email,
+ name,
+ },
+ })
+
+ return {
+ status: 200,
+ body: user,
+ }
+ } catch (e) {
+ context.log(e)
+ return {
+ status: 500,
+ body: e.message
+ }
+ }
+}
diff --git a/deployment-platforms/azure-functions/DeletePost/function.json b/deployment-platforms/azure-functions/DeletePost/function.json
new file mode 100644
index 000000000000..ea4b24626a4c
--- /dev/null
+++ b/deployment-platforms/azure-functions/DeletePost/function.json
@@ -0,0 +1,19 @@
+{
+ "bindings": [
+ {
+ "authLevel": "anonymous",
+ "type": "httpTrigger",
+ "direction": "in",
+ "name": "req",
+ "methods": [
+ "delete"
+ ],
+ "route": "post/{postId}"
+ },
+ {
+ "type": "http",
+ "direction": "out",
+ "name": "$return"
+ }
+ ]
+}
diff --git a/deployment-platforms/azure-functions/DeletePost/index.js b/deployment-platforms/azure-functions/DeletePost/index.js
new file mode 100644
index 000000000000..20c865d46075
--- /dev/null
+++ b/deployment-platforms/azure-functions/DeletePost/index.js
@@ -0,0 +1,31 @@
+const { PrismaClientKnownRequestError } = require('@prisma/client')
+const prisma = require('../lib/prisma')
+
+module.exports = async function (context, req) {
+ const { postId } = context.bindingData
+
+ try {
+ const post = await prisma.post.delete({
+ where: {
+ id: parseInt(postId, 10),
+ },
+ })
+ return {
+ body: post,
+ }
+ } catch (e) {
+ context.log(e)
+
+ if (e instanceof PrismaClientKnownRequestError && e.code === 'P2025') {
+ return {
+ status: 400,
+ body: `postId ${postId} cannot be deleted because it does not exist.`,
+ }
+ }
+
+ return {
+ status: 500,
+ body: e.message,
+ }
+ }
+}
diff --git a/deployment-platforms/azure-functions/FilterPosts/function.json b/deployment-platforms/azure-functions/FilterPosts/function.json
new file mode 100644
index 000000000000..6131bcd48ac7
--- /dev/null
+++ b/deployment-platforms/azure-functions/FilterPosts/function.json
@@ -0,0 +1,19 @@
+{
+ "bindings": [
+ {
+ "authLevel": "anonymous",
+ "type": "httpTrigger",
+ "direction": "in",
+ "name": "req",
+ "methods": [
+ "get"
+ ],
+ "route": "filterPosts"
+ },
+ {
+ "type": "http",
+ "direction": "out",
+ "name": "$return"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deployment-platforms/azure-functions/FilterPosts/index.js b/deployment-platforms/azure-functions/FilterPosts/index.js
new file mode 100644
index 000000000000..17e496d930c9
--- /dev/null
+++ b/deployment-platforms/azure-functions/FilterPosts/index.js
@@ -0,0 +1,34 @@
+const prisma = require('../lib/prisma')
+
+module.exports = async function (context, req) {
+ const { searchString } = req.query
+ try {
+ const filteredPosts = await prisma.post.findMany({
+ where: {
+ OR: [
+ {
+ title: {
+ contains: searchString,
+ },
+ },
+ {
+ content: {
+ contains: searchString,
+ },
+ },
+ ],
+ },
+ })
+
+ return {
+ status: 200,
+ body: filteredPosts,
+ }
+ } catch (e) {
+ context.log(e)
+ return {
+ status: 500,
+ body: e.message,
+ }
+ }
+}
diff --git a/deployment-platforms/azure-functions/GetFeed/function.json b/deployment-platforms/azure-functions/GetFeed/function.json
new file mode 100644
index 000000000000..c0a839d89efb
--- /dev/null
+++ b/deployment-platforms/azure-functions/GetFeed/function.json
@@ -0,0 +1,19 @@
+{
+ "bindings": [
+ {
+ "authLevel": "anonymous",
+ "type": "httpTrigger",
+ "direction": "in",
+ "name": "req",
+ "methods": [
+ "get"
+ ],
+ "route": "feed"
+ },
+ {
+ "type": "http",
+ "direction": "out",
+ "name": "$return"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deployment-platforms/azure-functions/GetFeed/index.js b/deployment-platforms/azure-functions/GetFeed/index.js
new file mode 100644
index 000000000000..704e5f0bbdc6
--- /dev/null
+++ b/deployment-platforms/azure-functions/GetFeed/index.js
@@ -0,0 +1,25 @@
+const prisma = require('../lib/prisma')
+
+module.exports = async function (context, req) {
+ try {
+ const posts = await prisma.post.findMany({
+ where: {
+ published: true,
+ },
+ include: {
+ author: true,
+ },
+ })
+
+ return {
+ status: 200,
+ body: posts,
+ }
+ } catch (e) {
+ context.log(e)
+ return {
+ status: 500,
+ body: e.message,
+ }
+ }
+}
diff --git a/deployment-platforms/azure-functions/GetPost/function.json b/deployment-platforms/azure-functions/GetPost/function.json
new file mode 100644
index 000000000000..fac8b3849806
--- /dev/null
+++ b/deployment-platforms/azure-functions/GetPost/function.json
@@ -0,0 +1,19 @@
+{
+ "bindings": [
+ {
+ "authLevel": "anonymous",
+ "type": "httpTrigger",
+ "direction": "in",
+ "name": "req",
+ "methods": [
+ "get"
+ ],
+ "route": "post/{postId}"
+ },
+ {
+ "type": "http",
+ "direction": "out",
+ "name": "$return"
+ }
+ ]
+}
diff --git a/deployment-platforms/azure-functions/GetPost/index.js b/deployment-platforms/azure-functions/GetPost/index.js
new file mode 100644
index 000000000000..9095e152983d
--- /dev/null
+++ b/deployment-platforms/azure-functions/GetPost/index.js
@@ -0,0 +1,24 @@
+const prisma = require('../lib/prisma')
+
+module.exports = async function (context, req) {
+ const { postId } = context.bindingData
+
+ try {
+ const post = await prisma.post.findUnique({
+ where: {
+ id: parseInt(postId, 10),
+ },
+ })
+
+ return {
+ status: 200,
+ body: post,
+ }
+ } catch (e) {
+ context.log(e)
+ return {
+ status: 500,
+ body: e.message,
+ }
+ }
+}
diff --git a/deployment-platforms/azure-functions/PublishPost/function.json b/deployment-platforms/azure-functions/PublishPost/function.json
new file mode 100644
index 000000000000..3b11ad191ab4
--- /dev/null
+++ b/deployment-platforms/azure-functions/PublishPost/function.json
@@ -0,0 +1,19 @@
+{
+ "bindings": [
+ {
+ "authLevel": "anonymous",
+ "type": "httpTrigger",
+ "direction": "in",
+ "name": "req",
+ "methods": [
+ "put"
+ ],
+ "route": "publish/{postId}"
+ },
+ {
+ "type": "http",
+ "direction": "out",
+ "name": "$return"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/deployment-platforms/azure-functions/PublishPost/index.js b/deployment-platforms/azure-functions/PublishPost/index.js
new file mode 100644
index 000000000000..e9fe993ec960
--- /dev/null
+++ b/deployment-platforms/azure-functions/PublishPost/index.js
@@ -0,0 +1,19 @@
+const prisma = require('../lib/prisma')
+
+module.exports = async function (context, req) {
+ const { postId } = context.bindingData
+
+ const publishedPost = await prisma.post.update({
+ where: {
+ id: parseInt(postId, 10),
+ },
+ data: {
+ published: true,
+ },
+ })
+
+ return {
+ status: 200,
+ body: publishedPost,
+ }
+}
diff --git a/deployment-platforms/azure-functions/host.json b/deployment-platforms/azure-functions/host.json
new file mode 100644
index 000000000000..6ab664374ff1
--- /dev/null
+++ b/deployment-platforms/azure-functions/host.json
@@ -0,0 +1,15 @@
+{
+ "version": "2.0",
+ "logging": {
+ "applicationInsights": {
+ "samplingSettings": {
+ "isEnabled": true,
+ "excludedTypes": "Request"
+ }
+ }
+ },
+ "extensionBundle": {
+ "id": "Microsoft.Azure.Functions.ExtensionBundle",
+ "version": "[1.*, 2.0.0)"
+ }
+}
diff --git a/deployment-platforms/azure-functions/lib/prisma.js b/deployment-platforms/azure-functions/lib/prisma.js
new file mode 100644
index 000000000000..18670a329854
--- /dev/null
+++ b/deployment-platforms/azure-functions/lib/prisma.js
@@ -0,0 +1,5 @@
+const { PrismaClient } = require('@prisma/client')
+
+const prisma = new PrismaClient()
+
+module.exports = prisma
\ No newline at end of file
diff --git a/deployment-platforms/azure-functions/package.json b/deployment-platforms/azure-functions/package.json
new file mode 100644
index 000000000000..e00a4be6aabe
--- /dev/null
+++ b/deployment-platforms/azure-functions/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "prisma-azure-example",
+ "version": "1.0.0",
+ "description": "",
+ "scripts": {
+ "dev": "func start"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0"
+ },
+ "devDependencies": {
+ "azure-functions-core-tools": "4.0.7512",
+ "prisma": "6.9.0"
+ }
+}
diff --git a/deployment-platforms/azure-functions/prisma/migrations/20210322111219_init/migration.sql b/deployment-platforms/azure-functions/prisma/migrations/20210322111219_init/migration.sql
new file mode 100644
index 000000000000..efa64a4c9f42
--- /dev/null
+++ b/deployment-platforms/azure-functions/prisma/migrations/20210322111219_init/migration.sql
@@ -0,0 +1,24 @@
+-- CreateTable
+CREATE TABLE [dbo].[User] (
+ [id] INT NOT NULL IDENTITY(1,1),
+ [createdAt] DATETIME2 NOT NULL CONSTRAINT [DF__User__createdAt] DEFAULT CURRENT_TIMESTAMP,
+ [email] NVARCHAR(1000) NOT NULL,
+ [name] NVARCHAR(1000),
+ CONSTRAINT [PK__User__id] PRIMARY KEY ([id]),
+ CONSTRAINT [User_email_unique] UNIQUE ([email])
+);
+
+-- CreateTable
+CREATE TABLE [dbo].[Post] (
+ [id] INT NOT NULL IDENTITY(1,1),
+ [createdAt] DATETIME2 NOT NULL CONSTRAINT [DF__Post__createdAt] DEFAULT CURRENT_TIMESTAMP,
+ [updatedAt] DATETIME2 NOT NULL,
+ [title] NVARCHAR(1000) NOT NULL,
+ [content] NVARCHAR(1000),
+ [published] BIT NOT NULL CONSTRAINT [DF__Post__published] DEFAULT 0,
+ [authorId] INT,
+ CONSTRAINT [PK__Post__id] PRIMARY KEY ([id])
+);
+
+-- AddForeignKey
+ALTER TABLE [dbo].[Post] ADD CONSTRAINT [FK__Post__authorId] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE SET NULL ON UPDATE CASCADE;
diff --git a/deployment-platforms/azure-functions/prisma/migrations/migration_lock.toml b/deployment-platforms/azure-functions/prisma/migrations/migration_lock.toml
new file mode 100644
index 000000000000..9845b170e3b4
--- /dev/null
+++ b/deployment-platforms/azure-functions/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "mssql"
\ No newline at end of file
diff --git a/deployment-platforms/azure-functions/prisma/schema.prisma b/deployment-platforms/azure-functions/prisma/schema.prisma
new file mode 100644
index 000000000000..56e922b93d24
--- /dev/null
+++ b/deployment-platforms/azure-functions/prisma/schema.prisma
@@ -0,0 +1,31 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+datasource db {
+ provider = "sqlserver"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+ binaryTargets = ["native", "debian-openssl-1.1.x"]
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ email String @unique
+ name String?
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ title String
+ content String?
+ published Boolean @default(false)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
diff --git a/deployment-platforms/azure-functions/proxies.json b/deployment-platforms/azure-functions/proxies.json
new file mode 100644
index 000000000000..b385252f5ed7
--- /dev/null
+++ b/deployment-platforms/azure-functions/proxies.json
@@ -0,0 +1,4 @@
+{
+ "$schema": "http://json.schemastore.org/proxies",
+ "proxies": {}
+}
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/.editorconfig b/deployment-platforms/edge/cloudflare-workers/with-d1/.editorconfig
new file mode 100644
index 000000000000..a727df347a12
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/.editorconfig
@@ -0,0 +1,12 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = tab
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.yml]
+indent_style = space
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/.gitignore b/deployment-platforms/edge/cloudflare-workers/with-d1/.gitignore
new file mode 100644
index 000000000000..3b0fe33c47f1
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/.gitignore
@@ -0,0 +1,172 @@
+# Logs
+
+logs
+_.log
+npm-debug.log_
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# Runtime data
+
+pids
+_.pid
+_.seed
+\*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+
+lib-cov
+
+# Coverage directory used by tools like istanbul
+
+coverage
+\*.lcov
+
+# nyc test coverage
+
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+
+bower_components
+
+# node-waf configuration
+
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+
+build/Release
+
+# Dependency directories
+
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+
+web_modules/
+
+# TypeScript cache
+
+\*.tsbuildinfo
+
+# Optional npm cache directory
+
+.npm
+
+# Optional eslint cache
+
+.eslintcache
+
+# Optional stylelint cache
+
+.stylelintcache
+
+# Microbundle cache
+
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+
+.node_repl_history
+
+# Output of 'npm pack'
+
+\*.tgz
+
+# Yarn Integrity file
+
+.yarn-integrity
+
+# dotenv environment variable files
+
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+
+.cache
+.parcel-cache
+
+# Next.js build output
+
+.next
+out
+
+# Nuxt.js build / generate output
+
+.nuxt
+dist
+
+# Gatsby files
+
+.cache/
+
+# Comment in the public line in if your project uses Gatsby and not Next.js
+
+# https://nextjs.org/blog/next-9-1#public-directory-support
+
+# public
+
+# vuepress build output
+
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+
+.temp
+.cache
+
+# Docusaurus cache and generated files
+
+.docusaurus
+
+# Serverless directories
+
+.serverless/
+
+# FuseBox cache
+
+.fusebox/
+
+# DynamoDB Local files
+
+.dynamodb/
+
+# TernJS port file
+
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+
+.vscode-test
+
+# yarn v2
+
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.\*
+
+# wrangler project
+
+.dev.vars
+.wrangler/
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/.prettierrc b/deployment-platforms/edge/cloudflare-workers/with-d1/.prettierrc
new file mode 100644
index 000000000000..5c7b5d3c7a75
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/.prettierrc
@@ -0,0 +1,6 @@
+{
+ "printWidth": 140,
+ "singleQuote": true,
+ "semi": true,
+ "useTabs": true
+}
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/README.md b/deployment-platforms/edge/cloudflare-workers/with-d1/README.md
new file mode 100644
index 000000000000..80f5c971fedc
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/README.md
@@ -0,0 +1,132 @@
+# Deploy a Cloudflare Worker with D1
+
+This example demonstrates how to deploy a [Cloudflare Worker](https://workers.cloudflare.com/) with a [D1 database](https://developers.cloudflare.com/d1/). It's based on Cloudflare's [`hello-world`](https://github.com/cloudflare/workers-sdk/tree/4fdd8987772d914cf50725e9fa8cb91a82a6870d/packages/create-cloudflare/templates/hello-world) template for Workers.
+
+
+## Getting started
+
+### 1. Download example and install dependencies
+
+Download this example:
+
+```
+git clone git@github.com:prisma/prisma-examples.git --depth=1
+```
+
+Navigate into the project directory and install npm dependencies:
+
+```
+cd deployment-platforms/edge/cloudflare-workers/with-d1/
+npm install
+```
+
+### 2. Create D1 database
+
+Create your D1 database using the `wrangler` CLI:
+
+```
+npx wrangler d1 create prisma-demo-db
+```
+
+> **Note**: This command requires you to be logged into your Cloudflare account.
+
+The command outputs the [binding](https://developers.cloudflare.com/workers/configuration/bindings/) configuration for your D1 database.
+
+Take this output and paste it into [`wrangler.toml`](./wrangler.toml) which then should look similar to this:
+
+```diff
+# wrangler.toml
+name = "prisma-d1-example"
+main = "src/index.ts"
+compatibility_date = "2024-03-20"
+compatibility_flags = ["nodejs_compat"]
+
+# Add the binding for your D1 database here
++[[d1_databases]]
++binding = "DB" # i.e. available in your Worker on env.DB
++database_name = "prisma-demo-db"
++database_id = "__YOUR_D1_DATABASE_ID__"
+```
+
+Note that `__YOUR_D1_DATABASE_ID__` in the snippet above is a placeholder that should be replaced with the database ID of your own D1 instance. If you weren't able to grab this ID from the terminal output, you can also find it in the [Cloudflare Dashboard](https://dash.cloudflare.com/) or by running `npx wrangler d1 info prisma-demo-db` in your terminal.
+
+
+### 3. Create a table in the database and seed some dummy data
+
+Prisma Migrate doesn't support D1 yet, so you can't follow the "default" migration workflows using `prisma migrate dev` or `prisma db push`. For this example, the file [`./prisma/schema.sql`](./prisma/schema.sql) contains a SQL statement to create a `User` table that mirros the shape of the `User` model in [`./prisma/schema.prisma`](./prisma/schema.prisma).
+
+To apply this SQL statement to your D1 instance, run the following command.
+
+First, for the _local_ database to enable you to test your Worker with D1 locally:
+
+```
+npx wrangler d1 execute prisma-demo-db --file=prisma/schema.sql --local
+```
+
+> **Note**: Your local D1 instance is located in `.wrangler/state/v3/d1`
+
+And one more time for the _remote_ database which is managed by Cloudflare in the cloud:
+
+```
+npx wrangler d1 execute prisma-demo-db --file=prisma/schema.sql --remote
+```
+
+Next, create some dummy data using the same `wrangler d1 execute` command again. This time, the SQL statement is hardcoded in the terminal command.
+
+Start with the _local_ database:
+
+```
+npx wrangler d1 execute prisma-demo-db --command "INSERT INTO \"User\" (\"email\", \"name\") VALUES
+('jane@prisma.io', 'Jane Doe (Local)');" --local
+```
+
+And then execute the same command against the _remote_ database:
+
+```
+npx wrangler d1 execute prisma-demo-db --command "INSERT INTO \"User\" (\"email\", \"name\") VALUES
+('jane@prisma.io', 'Jane Doe (Remote)');" --remote
+```
+
+### 4. Run the Worker locally
+
+Run the Worker locally using the following command:
+
+```
+npm run dev
+```
+
+You can now access the Worker on [`http://localhost:8787`](http://localhost:8787). It should render the following JSON data in the browser:
+
+```json
+[{"id":1,"email":"jane@prisma.io","name":"Jane Doe (Local)"}]
+```
+
+### 5. Deploy the Worker
+
+To deploy the Worker, run the following command:
+
+```
+npx wrangler deploy
+```
+
+You can now access the Worker on `https://prisma-d1-example.__USERNAME__.workers.dev`. It should render the following JSON data in the browser:
+
+```json
+[{"id":1,"email":"jane@prisma.io","name":"Jane Doe (Remote)"}]
+```
+
+
+## Notes about migrations
+
+This project uses an already existing [SQL schema](./prisma/schema.sql) file which you execute via `wrangler d1 execute` to keep the demo simple.
+
+If you want to evolve your schema and keep track of the migration history, you can take a look at the recommended [migration workflows](https://www.prisma.io/docs/orm/overview/databases/cloudflare-d1#migration-workflows) for D1 in the Prisma docs.
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
+
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/package.json b/deployment-platforms/edge/cloudflare-workers/with-d1/package.json
new file mode 100644
index 000000000000..28dd2ddd2701
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "prisma-d1-example",
+ "version": "0.0.0",
+ "private": true,
+ "scripts": {
+ "deploy": "wrangler deploy",
+ "dev": "wrangler dev",
+ "start": "wrangler dev",
+ "test": "vitest"
+ },
+ "devDependencies": {
+ "@cloudflare/vitest-pool-workers": "0.8.70",
+ "@cloudflare/workers-types": "4.20250806.0",
+ "prisma": "6.9.0",
+ "typescript": "5.8.2",
+ "vitest": "3.2.4",
+ "wrangler": "4.28.0"
+ },
+ "dependencies": {
+ "@prisma/adapter-d1": "6.9.0",
+ "@prisma/client": "6.9.0"
+ }
+}
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/prisma/schema.prisma b/deployment-platforms/edge/cloudflare-workers/with-d1/prisma/schema.prisma
new file mode 100644
index 000000000000..9928599c29cd
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/prisma/schema.prisma
@@ -0,0 +1,22 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["driverAdapters"]
+}
+
+// This `datasource` file isn't used but Prisma ORM still requires the `datasource` definition.
+// Your SQLite database file will be managed by D1:
+// - A local version will exist in `.wrangler`.
+// - The remote version is managed by Cloudflare in the Cloud.
+datasource db {
+ provider = "sqlite"
+ url = "file:./dev.db"
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+}
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/prisma/schema.sql b/deployment-platforms/edge/cloudflare-workers/with-d1/prisma/schema.sql
new file mode 100644
index 000000000000..fdcc5694acaa
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/prisma/schema.sql
@@ -0,0 +1,10 @@
+-- CreateTable
+CREATE TABLE "User" (
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ "email" TEXT NOT NULL,
+ "name" TEXT
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
+
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/src/index.ts b/deployment-platforms/edge/cloudflare-workers/with-d1/src/index.ts
new file mode 100644
index 000000000000..d72673f37b7d
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/src/index.ts
@@ -0,0 +1,17 @@
+import { PrismaClient } from '@prisma/client'
+import { PrismaD1 } from '@prisma/adapter-d1'
+
+export interface Env {
+ DB: D1Database
+}
+
+export default {
+ async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise {
+ const adapter = new PrismaD1(env.DB)
+ const prisma = new PrismaClient({ adapter })
+
+ const users = await prisma.user.findMany()
+ const result = JSON.stringify(users)
+ return new Response(result);
+ },
+};
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/test/index.spec.ts b/deployment-platforms/edge/cloudflare-workers/with-d1/test/index.spec.ts
new file mode 100644
index 000000000000..d31c7a13553f
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/test/index.spec.ts
@@ -0,0 +1,25 @@
+// test/index.spec.ts
+import { env, createExecutionContext, waitOnExecutionContext, SELF } from "cloudflare:test";
+import { describe, it, expect } from "vitest";
+import worker from "../src/index";
+
+// For now, you'll need to do something like this to get a correctly-typed
+// `Request` to pass to `worker.fetch()`.
+const IncomingRequest = Request;
+
+describe("Hello World worker", () => {
+ it("responds with Hello World! (unit style)", async () => {
+ const request = new IncomingRequest("http://example.com/");
+ // Create an empty context to pass to `worker.fetch()`.
+ const ctx = createExecutionContext();
+ const response = await worker.fetch(request, env, ctx);
+ // Wait for all `Promise`s passed to `ctx.waitUntil()` to settle before running test assertions
+ await waitOnExecutionContext(ctx);
+ expect(await response.text()).toMatchInlineSnapshot(`"Hello World!"`);
+ });
+
+ it("responds with Hello World! (integration style)", async () => {
+ const response = await SELF.fetch("http://github.com/service/https://example.com/");
+ expect(await response.text()).toMatchInlineSnapshot(`"Hello World!"`);
+ });
+});
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/test/tsconfig.json b/deployment-platforms/edge/cloudflare-workers/with-d1/test/tsconfig.json
new file mode 100644
index 000000000000..509425ffecb6
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/test/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "types": [
+ "@cloudflare/workers-types/experimental",
+ "@cloudflare/vitest-pool-workers"
+ ]
+ },
+ "include": ["./**/*.ts", "../src/env.d.ts"],
+ "exclude": []
+}
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/tsconfig.json b/deployment-platforms/edge/cloudflare-workers/with-d1/tsconfig.json
new file mode 100644
index 000000000000..91924903c20c
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/tsconfig.json
@@ -0,0 +1,104 @@
+{
+ "compilerOptions": {
+ /* Visit https://aka.ms/tsconfig.json to read more about this file */
+
+ /* Projects */
+ // "incremental": true, /* Enable incremental compilation */
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
+ // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
+
+ /* Language and Environment */
+ "target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
+ "lib": ["es2021"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
+ "jsx": "react" /* Specify what JSX code is generated. */,
+ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
+ // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
+
+ /* Modules */
+ "module": "es2022" /* Specify what module code is generated. */,
+ // "rootDir": "./", /* Specify the root folder within your source files. */
+ "moduleResolution": "Bundler" /* Specify how TypeScript looks up a file from a given module specifier. */,
+ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
+ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
+ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
+ // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
+ "types": [
+ "@cloudflare/workers-types/2023-07-01"
+ ] /* Specify type package names to be included without being referenced in a source file. */,
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
+ "resolveJsonModule": true /* Enable importing .json files */,
+ // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */
+
+ /* JavaScript Support */
+ "allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
+ "checkJs": false /* Enable error reporting in type-checked JavaScript files. */,
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
+
+ /* Emit */
+ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
+ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
+ // "outDir": "./", /* Specify an output folder for all emitted files. */
+ // "removeComments": true, /* Disable emitting comments. */
+ "noEmit": true /* Disable emitting files from a compilation. */,
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
+ // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
+ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+ /* Interop Constraints */
+ "isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */,
+ "allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */,
+ // "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
+
+ /* Type Checking */
+ "strict": true /* Enable all strict type-checking options. */,
+ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
+ // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+ // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
+ // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
+ // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
+ // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
+ // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
+
+ /* Completeness */
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
+ },
+ "exclude": ["test"]
+}
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/vitest.config.ts b/deployment-platforms/edge/cloudflare-workers/with-d1/vitest.config.ts
new file mode 100644
index 000000000000..973627c26808
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/vitest.config.ts
@@ -0,0 +1,11 @@
+import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
+
+export default defineWorkersConfig({
+ test: {
+ poolOptions: {
+ workers: {
+ wrangler: { configPath: "./wrangler.toml" },
+ },
+ },
+ },
+});
diff --git a/deployment-platforms/edge/cloudflare-workers/with-d1/wrangler.toml b/deployment-platforms/edge/cloudflare-workers/with-d1/wrangler.toml
new file mode 100644
index 000000000000..5982691d0f2d
--- /dev/null
+++ b/deployment-platforms/edge/cloudflare-workers/with-d1/wrangler.toml
@@ -0,0 +1,10 @@
+name = "prisma-d1-example"
+main = "src/index.ts"
+compatibility_date = "2024-03-20"
+compatibility_flags = ["nodejs_compat"]
+
+# Add the binding for your D1 database here
+[[d1_databases]]
+binding = "DB" # i.e. available in your Worker on env.DB
+database_name = "prisma-demo-db"
+database_id = "__YOUR_D1_DATABASE_ID__"
diff --git a/deployment-platforms/google-cloud-functions/README.md b/deployment-platforms/google-cloud-functions/README.md
new file mode 100644
index 000000000000..f3b31d081a09
--- /dev/null
+++ b/deployment-platforms/google-cloud-functions/README.md
@@ -0,0 +1,27 @@
+# Google Cloud Functions
+
+## Deployment
+
+When deploying on this platform, the build is created on the server and hence the correct binary is available as `prisma generate` runs on the server.
+
+Hence, we do not need to provide additional platform targeting options like `platforms`. With no additional parameters necessary, the generate section of the Prisma schema file looks like the following:
+
+```
+generator photon {
+ provider = "photonjs"
+}
+```
+
+## Environment
+
+Deploying to this platform requires setting up the production environment variables correctly. Please refer to the following section to find out how that can be done
+
+https://cloud.google.com/functions/docs/env-var
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/deployment-platforms/heroku/.gitignore b/deployment-platforms/heroku/.gitignore
new file mode 100644
index 000000000000..d3156068b49c
--- /dev/null
+++ b/deployment-platforms/heroku/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+*.env*
diff --git a/deployment-platforms/heroku/Procfile b/deployment-platforms/heroku/Procfile
new file mode 100644
index 000000000000..2c779cfc8c65
--- /dev/null
+++ b/deployment-platforms/heroku/Procfile
@@ -0,0 +1,3 @@
+web: npm start
+
+release: npx prisma migrate deploy
diff --git a/deployment-platforms/heroku/README.md b/deployment-platforms/heroku/README.md
new file mode 100644
index 000000000000..438ce93fdf12
--- /dev/null
+++ b/deployment-platforms/heroku/README.md
@@ -0,0 +1,18 @@
+# Heroku deployment example
+
+[Deployment guide](https://www.prisma.io/docs/guides/deployment/deploying-to-heroku)
+
+## Download manually
+
+```bash
+curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/deployment-platforms/heroku
+cd heroku
+```
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/deployment-platforms/heroku/package.json b/deployment-platforms/heroku/package.json
new file mode 100644
index 000000000000..a93f90cee70d
--- /dev/null
+++ b/deployment-platforms/heroku/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "prisma-heroku",
+ "version": "1.0.0",
+ "license": "MIT",
+ "scripts": {
+ "build": "prisma generate",
+ "dev": "PORT=3000 node src/index.js",
+ "start": "node src/index.js"
+ },
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "body-parser": "2.2.0",
+ "express": "5.1.0",
+ "prisma": "6.9.0"
+ },
+ "devDependencies": {}
+}
\ No newline at end of file
diff --git a/deployment-platforms/heroku/prisma/migrations/20210310152103_init/migration.sql b/deployment-platforms/heroku/prisma/migrations/20210310152103_init/migration.sql
new file mode 100644
index 000000000000..4461323dcc64
--- /dev/null
+++ b/deployment-platforms/heroku/prisma/migrations/20210310152103_init/migration.sql
@@ -0,0 +1,25 @@
+-- CreateTable
+CREATE TABLE "User" (
+ "email" TEXT NOT NULL,
+ "id" SERIAL NOT NULL,
+ "name" TEXT,
+
+ PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Post" (
+ "authorId" INTEGER,
+ "content" TEXT,
+ "id" SERIAL NOT NULL,
+ "published" BOOLEAN NOT NULL DEFAULT false,
+ "title" TEXT NOT NULL,
+
+ PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User.email_unique" ON "User"("email");
+
+-- AddForeignKey
+ALTER TABLE "Post" ADD FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
diff --git a/deployment-platforms/heroku/prisma/migrations/migration_lock.toml b/deployment-platforms/heroku/prisma/migrations/migration_lock.toml
new file mode 100644
index 000000000000..fbffa92c2bb7
--- /dev/null
+++ b/deployment-platforms/heroku/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "postgresql"
\ No newline at end of file
diff --git a/deployment-platforms/heroku/prisma/schema.prisma b/deployment-platforms/heroku/prisma/schema.prisma
new file mode 100644
index 000000000000..fb21f9c091e0
--- /dev/null
+++ b/deployment-platforms/heroku/prisma/schema.prisma
@@ -0,0 +1,24 @@
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ email String @unique
+ id Int @id @default(autoincrement())
+ name String?
+ posts Post[]
+}
+
+model Post {
+ authorId Int?
+ content String?
+ id Int @id @default(autoincrement())
+ published Boolean @default(false)
+ title String
+ author User? @relation(fields: [authorId], references: [id])
+}
diff --git a/deployment-platforms/heroku/public/index.html b/deployment-platforms/heroku/public/index.html
new file mode 100644
index 000000000000..a89790b44c5e
--- /dev/null
+++ b/deployment-platforms/heroku/public/index.html
@@ -0,0 +1,116 @@
+
+
+
+ Prisma example
+
+
+
+
+
+
+
+ Prisma example
+
+
+ Check API status
+
+
+ Seed data
+
+
+ Load feed
+
+
+
+
+
+
+
+
+
+
diff --git a/deployment-platforms/heroku/src/index.js b/deployment-platforms/heroku/src/index.js
new file mode 100644
index 000000000000..f7b5b0977907
--- /dev/null
+++ b/deployment-platforms/heroku/src/index.js
@@ -0,0 +1,148 @@
+const express = require('express')
+const bodyParser = require('body-parser')
+const { PrismaClient } = require('@prisma/client')
+
+const prisma = new PrismaClient()
+const app = express()
+
+app.use(bodyParser.json())
+app.use(express.static('public'))
+
+app.get(`/api`, async (req, res) => {
+ res.json({ up: true })
+})
+
+app.get(`/api/seed`, async (req, res) => {
+ const seedUser = {
+ email: 'jane@prisma.io',
+ name: 'Jane',
+ posts: {
+ create: [
+ {
+ title:
+ 'Comparing Database Types: How Database Types Evolved to Meet Different Needs',
+ content:
+ 'https://www.prisma.io/blog/comparison-of-database-models-1iz9u29nwn37/',
+ published: true,
+ },
+ {
+ title: 'Analysing Sleep Patterns: The Quantified Self',
+ content: 'https://quantifiedself.com/get-started/',
+ published: true,
+ },
+ ],
+ },
+ }
+
+ try {
+ await prisma.post.deleteMany({
+ where: {
+ author: {
+ email: 'jane@prisma.io',
+ },
+ },
+ })
+ await prisma.user.deleteMany({
+ where: {
+ email: 'jane@prisma.io',
+ },
+ })
+
+ const result = await prisma.user.create({
+ data: seedUser,
+ })
+ res.json(result)
+ } catch (e) {
+ console.error(e)
+ res.sendStatus(500)
+ }
+})
+
+app.post(`/api/user`, async (req, res) => {
+ const result = await prisma.user.create({
+ data: {
+ ...req.body,
+ },
+ })
+ res.json(result)
+})
+
+app.post(`/api/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.put('/api/publish/:id', async (req, res) => {
+ const { id } = req.params
+ const post = await prisma.post.update({
+ where: {
+ id: parseInt(id),
+ },
+ data: { published: true },
+ })
+ res.json(post)
+})
+
+app.delete(`/api/post/:id`, async (req, res) => {
+ const { id } = req.params
+ const post = await prisma.post.delete({
+ where: {
+ id: parseInt(id),
+ },
+ })
+ res.json(post)
+})
+
+app.get(`/api/post/:id`, async (req, res) => {
+ const { id } = req.params
+ const post = await prisma.post.findUnique({
+ where: {
+ id: parseInt(id),
+ },
+ })
+ res.json(post)
+})
+
+app.get('/api/feed', async (req, res) => {
+ const posts = await prisma.post.findMany({
+ where: { published: true },
+ include: { author: true },
+ })
+ res.json(posts)
+})
+
+app.get('/api/filterPosts', async (req, res) => {
+ const { searchString } = req.query
+ const draftPosts = await prisma.post.findMany({
+ where: {
+ OR: [
+ {
+ title: {
+ contains: searchString,
+ },
+ },
+ {
+ content: {
+ contains: searchString,
+ },
+ },
+ ],
+ },
+ })
+ res.json(draftPosts)
+})
+
+const PORT = process.env.PORT || 3000
+const server = app.listen(PORT, () =>
+ console.log(
+ `🚀 Server ready at: http://localhost:${PORT}\n⭐️ See sample requests: https://github.com/prisma/prisma-examples/blob/latest/orm/express/README.md#using-the-rest-api`,
+ ),
+)
diff --git a/deployment-platforms/railway/.gitignore b/deployment-platforms/railway/.gitignore
new file mode 100644
index 000000000000..47466b149398
--- /dev/null
+++ b/deployment-platforms/railway/.gitignore
@@ -0,0 +1,3 @@
+/node_modules
+src/generated/prisma/
+.env
\ No newline at end of file
diff --git a/deployment-platforms/railway/README.md b/deployment-platforms/railway/README.md
new file mode 100644
index 000000000000..9a8d6e55a0a5
--- /dev/null
+++ b/deployment-platforms/railway/README.md
@@ -0,0 +1,18 @@
+# Railway deployment example
+
+[Deployment guide](https://www.prisma.io/docs/guides/deployment/deploying-to-railway)
+
+## Download manually
+
+```bash
+curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/deployment-platforms/railway
+cd railway
+```
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/deployment-platforms/railway/package.json b/deployment-platforms/railway/package.json
new file mode 100644
index 000000000000..778767faa5cf
--- /dev/null
+++ b/deployment-platforms/railway/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "railway",
+ "type": "module",
+ "scripts": {
+ "dev": "tsx watch src/index.ts",
+ "start": "tsx src/index.ts"
+ },
+ "dependencies": {
+ "@hono/node-server": "1.19.1",
+ "@prisma/client": "6.15.0",
+ "dotenv": "17.2.2",
+ "hono": "4.9.6"
+ },
+ "devDependencies": {
+ "@types/node": "22.18.1",
+ "prisma": "6.15.0",
+ "tsx": "4.20.6"
+ }
+}
diff --git a/deployment-platforms/railway/prisma/migrations/20250905152121_init/migration.sql b/deployment-platforms/railway/prisma/migrations/20250905152121_init/migration.sql
new file mode 100644
index 000000000000..2aaf2d0054ac
--- /dev/null
+++ b/deployment-platforms/railway/prisma/migrations/20250905152121_init/migration.sql
@@ -0,0 +1,25 @@
+-- CreateTable
+CREATE TABLE "public"."User" (
+ "email" TEXT NOT NULL,
+ "id" SERIAL NOT NULL,
+ "name" TEXT,
+
+ CONSTRAINT "User_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "public"."Post" (
+ "authorId" INTEGER,
+ "content" TEXT,
+ "id" SERIAL NOT NULL,
+ "published" BOOLEAN NOT NULL DEFAULT false,
+ "title" TEXT NOT NULL,
+
+ CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email");
+
+-- AddForeignKey
+ALTER TABLE "public"."Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "public"."User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
diff --git a/deployment-platforms/railway/prisma/migrations/migration_lock.toml b/deployment-platforms/railway/prisma/migrations/migration_lock.toml
new file mode 100644
index 000000000000..044d57cdb0d5
--- /dev/null
+++ b/deployment-platforms/railway/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (e.g., Git)
+provider = "postgresql"
diff --git a/deployment-platforms/railway/prisma/schema.prisma b/deployment-platforms/railway/prisma/schema.prisma
new file mode 100644
index 000000000000..a914655c16d1
--- /dev/null
+++ b/deployment-platforms/railway/prisma/schema.prisma
@@ -0,0 +1,25 @@
+generator client {
+ provider = "prisma-client"
+ output = "../src/generated/prisma"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ email String @unique
+ id Int @id @default(autoincrement())
+ name String?
+ posts Post[]
+}
+
+model Post {
+ authorId Int?
+ content String?
+ id Int @id @default(autoincrement())
+ published Boolean @default(false)
+ title String
+ author User? @relation(fields: [authorId], references: [id])
+}
diff --git a/deployment-platforms/railway/src/index.ts b/deployment-platforms/railway/src/index.ts
new file mode 100644
index 000000000000..b3c44e7076dd
--- /dev/null
+++ b/deployment-platforms/railway/src/index.ts
@@ -0,0 +1,126 @@
+import 'dotenv/config'
+import { Hono } from 'hono'
+import { PrismaClient } from './generated/prisma/client'
+import { serve } from '@hono/node-server'
+
+const prisma = new PrismaClient()
+const app = new Hono()
+
+app.get('/', (c) => {
+ const html = `
+
+
+
+ Prisma + Railway Example
+
+
+
+ API Endpoints
+
+
+ GET /api
+ Test
+
+
+
+ GET /api/feed
+ Test
+
+
+
+ GET /api/seed
+ Test
+
+
+ Click a button to test an endpoint
+
+
+
+
+ `
+ return c.html(html)
+})
+
+app.get('/api', async (c) => {
+ return c.json({ up: true })
+})
+
+app.get('/api/seed', async (c) => {
+ try {
+ await prisma.post.deleteMany({})
+ await prisma.user.deleteMany({})
+
+ const author1 = await prisma.user.create({
+ data: {
+ email: 'jane@prisma.io',
+ name: 'Jane Doe',
+ posts: {
+ create: {
+ title: 'Comparing Database Types',
+ content:
+ 'https://www.prisma.io/blog/comparison-of-database-models-1iz9u29nwn37/',
+ published: true,
+ },
+ },
+ },
+ include: { posts: true },
+ })
+
+ const author2 = await prisma.user.create({
+ data: {
+ email: 'john@prisma.io',
+ name: 'John Smith',
+ posts: {
+ create: {
+ title: 'Getting Started with Prisma',
+ content: 'https://www.prisma.io/docs/getting-started',
+ published: true,
+ },
+ },
+ },
+ include: { posts: true },
+ })
+
+ return c.json({
+ message: 'Database seeded successfully',
+ authors: [author1, author2],
+ })
+ } catch (e) {
+ return c.json({ error: 'Failed to seed database' }, 500)
+ }
+})
+
+app.get('/api/feed', async (c) => {
+ const posts = await prisma.post.findMany({
+ where: { published: true },
+ include: { author: true },
+ })
+ return c.json(posts)
+})
+
+const port = process.env.PORT ? Number(process.env.PORT) : 3000
+console.log(`Server is running at http://localhost:${port}`)
+
+serve({
+ fetch: app.fetch,
+ port,
+})
diff --git a/deployment-platforms/railway/tsconfig.json b/deployment-platforms/railway/tsconfig.json
new file mode 100644
index 000000000000..23345376b79c
--- /dev/null
+++ b/deployment-platforms/railway/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "strict": true,
+ "skipLibCheck": true,
+ "lib": [
+ "ESNext"
+ ],
+ "jsx": "react-jsx",
+ "jsxImportSource": "hono/jsx"
+ },
+}
\ No newline at end of file
diff --git a/deployment-platforms/render/.gitignore b/deployment-platforms/render/.gitignore
new file mode 100644
index 000000000000..13dfa3637203
--- /dev/null
+++ b/deployment-platforms/render/.gitignore
@@ -0,0 +1,2 @@
+.env
+node_modules/
\ No newline at end of file
diff --git a/deployment-platforms/render/README.md b/deployment-platforms/render/README.md
new file mode 100644
index 000000000000..c6393f941928
--- /dev/null
+++ b/deployment-platforms/render/README.md
@@ -0,0 +1,22 @@
+# Render deployment example
+
+This example demonstrates how to deploy an Express app with Prisma ORM on [Render](https://render.com).
+
+See the [Render deployment guide](https://www.prisma.io/docs/guides/deployment/deploying-to-render) for full details.
+
+## Download this code
+```bash
+curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/deployment-platforms/render
+cd render
+```
+
+## About Render
+Render enables developers to easily host and scale full-stack web applications. Render natively supports [common runtimes](https://docs.render.com/language-support), including Node.js and Bun. Render also supports deploying from a Dockerfile or Docker registry.
+
+## Resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/deployment-platforms/render/package.json b/deployment-platforms/render/package.json
new file mode 100644
index 000000000000..486e89d7a7fc
--- /dev/null
+++ b/deployment-platforms/render/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "prisma-on-render",
+ "version": "1.0.0",
+ "type": "module",
+ "description": "Example Express API that uses Prisma ORM, deployed on Render",
+ "main": "index.js",
+ "scripts": {
+ "build": "prisma generate",
+ "dev": "PORT=3000 node src/index.js",
+ "start": "node src/index.js"
+ },
+ "author": "@jess-render",
+ "license": "ISC",
+ "dependencies": {
+ "@prisma/client": "6.9.0",
+ "body-parser": "2.2.0",
+ "express": "5.1.0"
+ },
+ "devDependencies": {
+ "prisma": "6.9.0"
+ },
+ "prisma": {
+ "seed": "node prisma/seed.js"
+ }
+}
diff --git a/deployment-platforms/render/prisma/migrations/20241104163549_init/migration.sql b/deployment-platforms/render/prisma/migrations/20241104163549_init/migration.sql
new file mode 100644
index 000000000000..88c2bfca736c
--- /dev/null
+++ b/deployment-platforms/render/prisma/migrations/20241104163549_init/migration.sql
@@ -0,0 +1,25 @@
+-- CreateTable
+CREATE TABLE "User" (
+ "email" TEXT NOT NULL,
+ "id" SERIAL NOT NULL,
+ "name" TEXT,
+
+ CONSTRAINT "User_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Post" (
+ "authorId" INTEGER,
+ "content" TEXT,
+ "id" SERIAL NOT NULL,
+ "published" BOOLEAN NOT NULL DEFAULT false,
+ "title" TEXT NOT NULL,
+
+ CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
+
+-- AddForeignKey
+ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
diff --git a/deployment-platforms/render/prisma/migrations/migration_lock.toml b/deployment-platforms/render/prisma/migrations/migration_lock.toml
new file mode 100644
index 000000000000..fbffa92c2bb7
--- /dev/null
+++ b/deployment-platforms/render/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "postgresql"
\ No newline at end of file
diff --git a/deployment-platforms/render/prisma/schema.prisma b/deployment-platforms/render/prisma/schema.prisma
new file mode 100644
index 000000000000..8d8cb9259a6b
--- /dev/null
+++ b/deployment-platforms/render/prisma/schema.prisma
@@ -0,0 +1,24 @@
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ email String @unique
+ id Int @id @default(autoincrement())
+ name String?
+ posts Post[]
+}
+
+model Post {
+ authorId Int?
+ content String?
+ id Int @id @default(autoincrement())
+ published Boolean @default(false)
+ title String
+ author User? @relation(fields: [authorId], references: [id])
+}
diff --git a/deployment-platforms/render/prisma/seed.js b/deployment-platforms/render/prisma/seed.js
new file mode 100644
index 000000000000..836457fb541b
--- /dev/null
+++ b/deployment-platforms/render/prisma/seed.js
@@ -0,0 +1,62 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ const jane = await prisma.user.upsert({
+ where: { email: 'jane@prisma.io' },
+ update: {},
+ create: {
+ email: 'jane@prisma.io',
+ name: 'Jane',
+ posts: {
+ create: [
+ {
+ title:
+ 'Comparing Database Types: How Database Types Evolved to Meet Different Needs',
+ content:
+ 'https://www.prisma.io/blog/comparison-of-database-models-1iz9u29nwn37/',
+ published: true,
+ },
+ {
+ title: 'Analysing Sleep Patterns: The Quantified Self',
+ content: 'https://quantifiedself.com/get-started/',
+ published: true,
+ },
+ ]
+ }
+ }
+ })
+
+ const bob = await prisma.user.upsert({
+ where: { email: 'bob@prisma.io' },
+ update: {},
+ create: {
+ email: 'bob@prisma.io',
+ name: 'Bob',
+ posts: {
+ create: [
+ {
+ title:
+ 'Deploying Prisma ORM to Traditional servers',
+ content:
+ 'https://www.prisma.io/docs/orm/prisma-client/deployment/traditional',
+ published: true,
+ },
+ ]
+ }
+ }
+ })
+
+ console.log({ jane, bob })
+}
+
+main()
+ .then(async () => {
+ await prisma.$disconnect()
+ })
+ .catch(async (e) => {
+ console.error(e)
+ await prisma.$disconnect()
+ process.exit(1)
+ })
\ No newline at end of file
diff --git a/deployment-platforms/render/public/index.html b/deployment-platforms/render/public/index.html
new file mode 100644
index 000000000000..3e77d848a528
--- /dev/null
+++ b/deployment-platforms/render/public/index.html
@@ -0,0 +1,64 @@
+
+
+
+ Prisma example
+
+
+
+
+
+
+
+ Prisma example
+
+
+ Check API status
+
+
+ Load feed
+
+
+
+
+
+
+
+
+
+
diff --git a/deployment-platforms/render/render.yaml b/deployment-platforms/render/render.yaml
new file mode 100644
index 000000000000..96d12844a704
--- /dev/null
+++ b/deployment-platforms/render/render.yaml
@@ -0,0 +1,27 @@
+services:
+- type: web
+ name: express-with-prisma-orm
+ runtime: node
+ plan: free
+ envVars:
+ - key: DATABASE_URL
+ fromDatabase:
+ name: express-with-prisma-orm-db
+ property: connectionString
+ region: oregon # optional: customize this region
+ buildCommand: npm install --production=false
+ startCommand: npm run start
+ preDeployCommand: npx prisma migrate deploy
+
+databases:
+- name: express-with-prisma-orm-db
+ databaseName: express_prisma_db
+ user: express_prisma_db_user
+ plan: free
+ region: oregon
+ ipAllowList:
+ - source: 0.0.0.0/0
+ description: everywhere
+ postgresMajorVersion: "16"
+
+version: "1"
\ No newline at end of file
diff --git a/deployment-platforms/render/src/index.js b/deployment-platforms/render/src/index.js
new file mode 100644
index 000000000000..bfaa96ca935b
--- /dev/null
+++ b/deployment-platforms/render/src/index.js
@@ -0,0 +1,103 @@
+import express from 'express'
+import bodyParser from 'body-parser'
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+const app = express()
+
+app.use(bodyParser.json())
+app.use(express.static('public'))
+
+app.get(`/api`, async (req, res) => {
+ res.json({ up: true })
+})
+
+app.post(`/api/user`, async (req, res) => {
+ const result = await prisma.user.create({
+ data: {
+ ...req.body,
+ },
+ })
+ res.json(result)
+})
+
+app.post(`/api/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.put('/api/publish/:id', async (req, res) => {
+ const { id } = req.params
+ const post = await prisma.post.update({
+ where: {
+ id: parseInt(id),
+ },
+ data: { published: true },
+ })
+ res.json(post)
+})
+
+app.delete(`/api/post/:id`, async (req, res) => {
+ const { id } = req.params
+ const post = await prisma.post.delete({
+ where: {
+ id: parseInt(id),
+ },
+ })
+ res.json(post)
+})
+
+app.get(`/api/post/:id`, async (req, res) => {
+ const { id } = req.params
+ const post = await prisma.post.findUnique({
+ where: {
+ id: parseInt(id),
+ },
+ })
+ res.json(post)
+})
+
+app.get('/api/feed', async (req, res) => {
+ const posts = await prisma.post.findMany({
+ where: { published: true },
+ include: { author: true },
+ })
+ res.json(posts)
+})
+
+app.get('/api/filterPosts', async (req, res) => {
+ const { searchString } = req.query
+ const draftPosts = await prisma.post.findMany({
+ where: {
+ OR: [
+ {
+ title: {
+ contains: searchString,
+ },
+ },
+ {
+ content: {
+ contains: searchString,
+ },
+ },
+ ],
+ },
+ })
+ res.json(draftPosts)
+})
+
+const PORT = process.env.PORT || 3000
+const server = app.listen(PORT, () =>
+ console.log(
+ `🚀 Server ready at: http://localhost:${PORT}\n⭐️ See sample requests: https://github.com/prisma/prisma-examples/blob/latest/orm/express/README.md#using-the-rest-api`,
+ ),
+)
+
diff --git a/deployment-platforms/vercel/README.md b/deployment-platforms/vercel/README.md
new file mode 100644
index 000000000000..8338b902e9c8
--- /dev/null
+++ b/deployment-platforms/vercel/README.md
@@ -0,0 +1,13 @@
+# Vercel deployment example
+
+The deployment example has moved to https://github.com/prisma/deployment-example-vercel
+
+[Deployment guide](https://www.prisma.io/docs/guides/deployment/deploying-to-vercel)
+
+## Additional resources
+
+- Check out the [Prisma docs](https://www.prisma.io/docs)
+- [Join our community on Discord](https://pris.ly/discord?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) to share feedback and interact with other users.
+- [Subscribe to our YouTube channel](https://pris.ly/youtube?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for live demos and video tutorials.
+- [Follow us on X](https://pris.ly/x?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section) for the latest updates.
+- Report issues or ask [questions on GitHub](https://pris.ly/github?utm_source=github&utm_medium=prisma_examples&utm_content=next_steps_section).
diff --git a/flow/graphql/.babelrc b/flow/graphql/.babelrc
deleted file mode 100644
index 844b18fde8f0..000000000000
--- a/flow/graphql/.babelrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "presets": ["@babel/preset-env", "@babel/preset-flow"]
-}
diff --git a/flow/graphql/.flowconfig b/flow/graphql/.flowconfig
deleted file mode 100644
index 1454726c4c08..000000000000
--- a/flow/graphql/.flowconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-[ignore]
-# this is required until this issue gets fixed: https://github.com/prisma/prisma/issues/3617
-.*/node_modules/graphql/jsutils/keyValMap.js.flow
-
-[include]
-
-[libs]
-
-[lints]
-
-[options]
-
-[strict]
diff --git a/flow/graphql/README.md b/flow/graphql/README.md
deleted file mode 100644
index 8f3acbce704d..000000000000
--- a/flow/graphql/README.md
+++ /dev/null
@@ -1,293 +0,0 @@
-# GraphQL Server Example
-
-This example shows how to implement a **GraphQL server with Flow** based on Prisma & [graphql-yoga](https://github.com/prisma/graphql-yoga).
-
-## How to use
-
-### 1. Download example & install dependencies
-
-Clone the repository:
-
-```
-git clone git@github.com:prisma/prisma-examples.git
-```
-
-Install Node dependencies:
-
-```
-cd prisma-examples/flow/graphql
-npm install
-```
-
-### 2. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 3. Set up database & deploy Prisma datamodel
-
-For this example, you'll use a free _demo database_ (AWS Aurora) hosted in Prisma Cloud. To set up your database, run:
-
-```
-prisma deploy
-```
-
-Then, follow these steps in the interactive CLI wizard:
-
-1. Select **Demo server**
-1. **Authenticate** with Prisma Cloud in your browser (if necessary)
-1. Back in your terminal, **confirm all suggested values**
-
-
- Alternative: Run Prisma locally via Docker
-
-1. Ensure you have Docker installed on your machine. If not, you can get it from [here](https://store.docker.com/search?offering=community&type=edition).
-1. Create `docker-compose.yml` for MySQL (see [here](https://www.prisma.io/docs/prisma-server/database-connector-POSTGRES-jgfr/) for Postgres):
- ```yml
- version: '3'
- services:
- prisma:
- image: prismagraphql/prisma:1.27
- restart: always
- ports:
- - "4466:4466"
- environment:
- PRISMA_CONFIG: |
- port: 4466
- databases:
- default:
- connector: mysql
- host: mysql
- port: 3306
- user: root
- password: prisma
- migrations: true
- mysql:
- image: mysql:5.7
- restart: always
- environment:
- MYSQL_ROOT_PASSWORD: prisma
- volumes:
- - mysql:/var/lib/mysql
- volumes:
- mysql:
- ```
-1. Run `docker-compose up -d`
-1. Set the `endpoint` in `prisma.yml` to `http://localhost:4466`
-1. Run `prisma deploy`
-
-
-
-### 4. Start the GraphQL server
-
-Launch your GraphQL server with this command:
-
-```
-npm run start
-```
-
-Navigate to [http://localhost:4000](http://localhost:4000) in your browser to explore the API of your GraphQL server in a [GraphQL Playground](https://github.com/prisma/graphql-playground).
-
-### 5. Using the GraphQL API
-
-The schema that specifies the API operations of your GraphQL server is defined in [`./src/schema.graphql`](./src/schema.graphql). Below are a number of operations that you can send to the API using the GraphQL Playground.
-
-Feel free to adjust any operation by adding or removing fields. The GraphQL Playground helps you with its auto-completion and query validation features.
-
-#### Retrieve all published posts and their authors
-
-```graphql
-query {
- feed {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-See more API operations
-
-#### Register a new user
-
-You can send the following mutation in the Playground to sign up a new user and retrieve an authentication token for them:
-
-```graphql
-mutation {
- signup(name: "Alice", email: "alice@prisma.io", password: "graphql") {
- token
- }
-}
-```
-
-#### Log in an existing user
-
-This mutation will log in an existing user by requesting a new authentication token for them:
-
-```graphql
-mutation {
- login(email: "alice@prisma.io", password: "graphql") {
- token
- }
-}
-```
-
-#### Check whether a user is currently logged in with the `me` query
-
-For this query, you need to make sure a valid authentication token is sent along with the `Bearer`-prefix in the `Authorization` header of the request. Inside the Playground, you can set HTTP headers in the bottom-left corner:
-
-
-
-Once you've set the header, you can send the following query to check whether the token is valid:
-
-```graphql
-{
- me {
- id
- name
- email
- }
-}
-```
-
-#### Create a new draft
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground.
-
-```graphql
-mutation {
- createDraft(
- title: "Join the Prisma Slack"
- content: "https://slack.prisma.io/"
- authorEmail: "alice@prisma.io"
- ) {
- id
- published
- }
-}
-```
-
-#### Publish an existing draft
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground. The authentication token must belong to the user who created the post.
-
-```graphql
-mutation {
- publish(id: "__POST_ID__") {
- id
- published
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-#### Search for posts with a specific title or content
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground.
-
-```graphql
-{
- filterPosts(searchString: "graphql") {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-#### Retrieve a single post
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground.
-
-```graphql
-{
- posts(id: "__POST_ID__") {
- id
- title
- content
- published
- author {
- id
- name
- email
- }
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-#### Delete a post
-
-You need to be logged in for this query to work, i.e. an authentication token that was retrieved through a `signup` or `login` mutation needs to be added to the `Authorization` header in the GraphQL Playground. The authentication token must belong to the user who created the post.
-
-```graphql
-mutation {
- deletePost(id: "__POST_ID__") {
- id
- }
-}
-```
-
-> **Note**: You need to replace the `__POST_ID__`-placeholder with an actual `id` from a `Post` item. You can find one e.g. using the `filterPosts`-query.
-
-
-
-### 6. Testing GraphQL subscriptions in the Playground
-
-To test the `post` subscription, you need to send a subscription query in the Playground, e.g.:
-
-```graphql
-subscription {
- posts {
- id
- createdAt
- title
- content
- published
- }
-}
-```
-
-When hitting the _Play_-button, you won't see an immediate response. Instead there's a loading indicator in the response pane of the Playground:
-
-
-
-Now, whenever a post is created (or updated), e.g. with this mutation (you can run it in another tab):
-
-```graphql
-mutation {
- createDraft(
- title: "Join the Prisma community on Slack"
- content: "https://slack.prisma.io/"
- ) {
- id
- }
-}
-```
-
-You will see the results appear in the tab where the subscription is running:
-
-
-
-## Next steps
-
-- [Use Prisma with an existing database](https://www.prisma.io/docs/-f003/)
-- [Explore the Prisma client API](https://www.prisma.io/client/client-flow)
-- [Learn more about the GraphQL schema](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e/)
\ No newline at end of file
diff --git a/flow/graphql/graphqlgen.yml b/flow/graphql/graphqlgen.yml
deleted file mode 100644
index ba407f9b4d34..000000000000
--- a/flow/graphql/graphqlgen.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-# The target programming language for the generated code.
-language: flow
-
-# The file path pointing to your GraphQL schema.
-schema: ./src/schema.graphql
-
-# Type definition for the resolver context object.
-context: ./src/types.js:Context
-
-# Map SDL types from the GraphQL schema to Flow models.
-models:
- files:
- - ./src/generated/prisma-client
- - ./src/types.js
-
-# Generated typings for resolvers and default resolver implementations
-# DO NOT EDIT THIS FILE but just _import_ from it into your own source files.
-output: ./src/generated/graphqlgen.js
-
-# Temporary scaffolded resolvers to copy and paste into your own source files.
-resolver-scaffolding:
- output: ./src/generated/tmp-resolvers/
- layout: file-per-type
diff --git a/flow/graphql/package.json b/flow/graphql/package.json
deleted file mode 100644
index dcd3b967d926..000000000000
--- a/flow/graphql/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "graphql",
- "devDependencies": {
- "@babel/node": "7.2.2",
- "@babel/core": "7.3.3",
- "@babel/preset-env": "7.3.1",
- "@babel/preset-flow": "7.0.0",
- "flow-bin": "0.93.0",
- "graphqlgen": "0.5.1"
- },
- "dependencies": {
- "graphql-yoga": "1.17.4",
- "prisma-client-lib": "1.27.1"
- },
- "scripts": {
- "start": "babel-node src/index.js",
- "generate": "graphqlgen",
- "flow": "flow"
- }
-}
diff --git a/flow/graphql/prisma/datamodel.prisma b/flow/graphql/prisma/datamodel.prisma
deleted file mode 100644
index 74e803e03f72..000000000000
--- a/flow/graphql/prisma/datamodel.prisma
+++ /dev/null
@@ -1,16 +0,0 @@
-type User {
- id: ID! @unique
- email: String! @unique
- name: String
- posts: [Post!]!
-}
-
-type Post {
- id: ID! @unique
- createdAt: DateTime!
- updatedAt: DateTime!
- published: Boolean! @default(value: "false")
- title: String!
- content: String
- author: User!
-}
\ No newline at end of file
diff --git a/flow/graphql/prisma/prisma.yml b/flow/graphql/prisma/prisma.yml
deleted file mode 100644
index f58d63fc5490..000000000000
--- a/flow/graphql/prisma/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: flow-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- import: seed.graphql
\ No newline at end of file
diff --git a/flow/graphql/prisma/seed.graphql b/flow/graphql/prisma/seed.graphql
deleted file mode 100644
index 0542eaea579a..000000000000
--- a/flow/graphql/prisma/seed.graphql
+++ /dev/null
@@ -1,32 +0,0 @@
-mutation {
- user1: createUser(data: {
- email: "alice@prisma.io"
- name: "Alice"
- posts: {
- create: {
- title: "Join us for GraphQL Conf 2019 in Berlin"
- content: "https://www.graphqlconf.org/"
- published: true
- }
- }
- }) {
- id
- }
-
- user2: createUser(data: {
- email: "bob@prisma.io"
- name: "Bob"
- posts: {
- create: [{
- title: "Subscribe to GraphQL Weekly for community news"
- content: "https://graphqlweekly.com/"
- published: true
- } {
- title: "Follow Prisma on Twitter"
- content: "https://twitter.com/prisma"
- }]
- }
- }) {
- id
- }
-}
\ No newline at end of file
diff --git a/flow/graphql/src/generated/graphqlgen.js b/flow/graphql/src/generated/graphqlgen.js
deleted file mode 100644
index 6b28f21b3156..000000000000
--- a/flow/graphql/src/generated/graphqlgen.js
+++ /dev/null
@@ -1,324 +0,0 @@
-/* @flow */
-// Code generated by github.com/prisma/graphqlgen, DO NOT EDIT.
-
-import type { GraphQLResolveInfo } from 'graphql'
-import type { Post, User } from './prisma-client'
-import type { Context } from '../types'
-
-// Types for Query
-export const Query_defaultResolvers = {}
-
-export interface Query_Args_FilterPosts {
- searchString: string | null;
-}
-
-export interface Query_Args_Post {
- id: string;
-}
-
-export type Query_Feed_Resolver = (
- parent: {},
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => Post[] | Promise
-
-export type Query_FilterPosts_Resolver = (
- parent: {},
- args: Query_Args_FilterPosts,
- ctx: Context,
- info: GraphQLResolveInfo,
-) => Post[] | Promise
-
-export type Query_Post_Resolver = (
- parent: {},
- args: Query_Args_Post,
- ctx: Context,
- info: GraphQLResolveInfo,
-) => Post | null | Promise
-
-export interface Query_Resolvers {
- feed: (
- parent: {},
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => Post[] | Promise;
-
- filterPosts: (
- parent: {},
- args: Query_Args_FilterPosts,
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => Post[] | Promise;
-
- post: (
- parent: {},
- args: Query_Args_Post,
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => Post | null | Promise;
-}
-
-// Types for Post
-export const Post_defaultResolvers = {
- id: (parent: Post) => parent.id,
- createdAt: (parent: Post) => parent.createdAt,
- updatedAt: (parent: Post) => parent.updatedAt,
- published: (parent: Post) => parent.published,
- title: (parent: Post) => parent.title,
- content: (parent: Post) =>
- parent.content === undefined ? null : parent.content,
-}
-
-export type Post_Id_Resolver = (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => string | Promise
-
-export type Post_CreatedAt_Resolver = (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => string | Promise
-
-export type Post_UpdatedAt_Resolver = (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => string | Promise
-
-export type Post_Published_Resolver = (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => boolean | Promise
-
-export type Post_Title_Resolver = (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => string | Promise
-
-export type Post_Content_Resolver = (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => string | null | Promise
-
-export type Post_Author_Resolver = (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => User | Promise
-
-export interface Post_Resolvers {
- id: (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => string | Promise;
-
- createdAt: (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => string | Promise;
-
- updatedAt: (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => string | Promise;
-
- published: (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => boolean | Promise;
-
- title: (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => string | Promise;
-
- content: (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => string | null | Promise;
-
- author: (
- parent: Post,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => User | Promise;
-}
-
-// Types for User
-export const User_defaultResolvers = {
- id: (parent: User) => parent.id,
- email: (parent: User) => parent.email,
- name: (parent: User) => (parent.name === undefined ? null : parent.name),
-}
-
-export type User_Id_Resolver = (
- parent: User,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => string | Promise
-
-export type User_Email_Resolver = (
- parent: User,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => string | Promise
-
-export type User_Name_Resolver = (
- parent: User,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => string | null | Promise
-
-export type User_Posts_Resolver = (
- parent: User,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
-) => Post[] | Promise
-
-export interface User_Resolvers {
- id: (
- parent: User,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => string | Promise;
-
- email: (
- parent: User,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => string | Promise;
-
- name: (
- parent: User,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => string | null | Promise;
-
- posts: (
- parent: User,
- args: {},
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => Post[] | Promise;
-}
-
-// Types for Mutation
-export const Mutation_defaultResolvers = {}
-
-export interface Mutation_Args_SignupUser {
- email: string;
- name: string | null;
-}
-
-export interface Mutation_Args_CreateDraft {
- title: string;
- content: string | null;
- authorEmail: string;
-}
-
-export interface Mutation_Args_DeletePost {
- id: string;
-}
-
-export interface Mutation_Args_Publish {
- id: string;
-}
-
-export type Mutation_SignupUser_Resolver = (
- parent: {},
- args: Mutation_Args_SignupUser,
- ctx: Context,
- info: GraphQLResolveInfo,
-) => User | Promise
-
-export type Mutation_CreateDraft_Resolver = (
- parent: {},
- args: Mutation_Args_CreateDraft,
- ctx: Context,
- info: GraphQLResolveInfo,
-) => Post | Promise
-
-export type Mutation_DeletePost_Resolver = (
- parent: {},
- args: Mutation_Args_DeletePost,
- ctx: Context,
- info: GraphQLResolveInfo,
-) => Post | null | Promise
-
-export type Mutation_Publish_Resolver = (
- parent: {},
- args: Mutation_Args_Publish,
- ctx: Context,
- info: GraphQLResolveInfo,
-) => Post | null | Promise
-
-export interface Mutation_Resolvers {
- signupUser: (
- parent: {},
- args: Mutation_Args_SignupUser,
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => User | Promise;
-
- createDraft: (
- parent: {},
- args: Mutation_Args_CreateDraft,
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => Post | Promise;
-
- deletePost: (
- parent: {},
- args: Mutation_Args_DeletePost,
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => Post | null | Promise;
-
- publish: (
- parent: {},
- args: Mutation_Args_Publish,
- ctx: Context,
- info: GraphQLResolveInfo,
- ) => Post | null | Promise;
-}
-
-export interface Resolvers {
- Query: Query_Resolvers;
- Post: Post_Resolvers;
- User: User_Resolvers;
- Mutation: Mutation_Resolvers;
-}
diff --git a/flow/graphql/src/generated/prisma-client/index.js b/flow/graphql/src/generated/prisma-client/index.js
deleted file mode 100644
index 99abd84e192d..000000000000
--- a/flow/graphql/src/generated/prisma-client/index.js
+++ /dev/null
@@ -1,786 +0,0 @@
-/**
- * @flow
- */
-
-// Code generated by Prisma (prisma@1.21.1). DO NOT EDIT.
-// Please don't change this file manually but run `prisma generate` to update it.
-// For more information, please read the docs: https://www.prisma.io/docs/prisma-client/
-
-import type { GraphQLSchema, DocumentNode } from 'graphql'
-import type { BasePrismaOptions as BPOType, Options } from 'prisma-client-lib'
-import { makePrismaClientClass } from 'prisma-client-lib'
-import { typeDefs } from './prisma-schema'
-
-type NodePromise = Promise
-
-type AtLeastOne = $Shape
-
-export interface Exists {
- post(where?: PostWhereInput): Promise;
- user(where?: UserWhereInput): Promise;
-}
-
-export interface Node {}
-
-export type FragmentableArray = Promise> & Fragmentable
-
-export interface Fragmentable {
- $fragment(fragment: string | DocumentNode): Promise;
-}
-
-interface PrismaInterface {
- $exists: Exists;
- $graphql: (
- query: string,
- variables?: { [key: string]: any },
- ) => Promise;
-
- /**
- * Queries
- */
-
- post: (where: PostWhereUniqueInput) => PostPromise;
- posts: (args?: {
- where?: PostWhereInput,
- orderBy?: PostOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => FragmentableArray;
- postsConnection: (args?: {
- where?: PostWhereInput,
- orderBy?: PostOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => PostConnectionPromise;
- user: (where: UserWhereUniqueInput) => UserPromise;
- users: (args?: {
- where?: UserWhereInput,
- orderBy?: UserOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => FragmentableArray;
- usersConnection: (args?: {
- where?: UserWhereInput,
- orderBy?: UserOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => UserConnectionPromise;
- node: (args: { id: ID_Output }) => Node;
-
- /**
- * Mutations
- */
-
- createPost: (data: PostCreateInput) => PostPromise;
- updatePost: (args: {
- data: PostUpdateInput,
- where: PostWhereUniqueInput,
- }) => PostPromise;
- updateManyPosts: (args: {
- data: PostUpdateManyMutationInput,
- where?: PostWhereInput,
- }) => BatchPayloadPromise;
- upsertPost: (args: {
- where: PostWhereUniqueInput,
- create: PostCreateInput,
- update: PostUpdateInput,
- }) => PostPromise;
- deletePost: (where: PostWhereUniqueInput) => PostPromise;
- deleteManyPosts: (where?: PostWhereInput) => BatchPayloadPromise;
- createUser: (data: UserCreateInput) => UserPromise;
- updateUser: (args: {
- data: UserUpdateInput,
- where: UserWhereUniqueInput,
- }) => UserPromise;
- updateManyUsers: (args: {
- data: UserUpdateManyMutationInput,
- where?: UserWhereInput,
- }) => BatchPayloadPromise;
- upsertUser: (args: {
- where: UserWhereUniqueInput,
- create: UserCreateInput,
- update: UserUpdateInput,
- }) => UserPromise;
- deleteUser: (where: UserWhereUniqueInput) => UserPromise;
- deleteManyUsers: (where?: UserWhereInput) => BatchPayloadPromise;
-
- /**
- * Subscriptions
- */
-
- $subscribe: Subscription;
-}
-
-export interface Subscription {
- post: (
- where?: PostSubscriptionWhereInput,
- ) => PostSubscriptionPayloadSubscription;
- user: (
- where?: UserSubscriptionWhereInput,
- ) => UserSubscriptionPayloadSubscription;
-}
-
-export type ClientConstructor = (options?: BPOType) => T
-
-/**
- * Types
- */
-
-export type PostOrderByInput =
- | 'id_ASC'
- | 'id_DESC'
- | 'createdAt_ASC'
- | 'createdAt_DESC'
- | 'updatedAt_ASC'
- | 'updatedAt_DESC'
- | 'published_ASC'
- | 'published_DESC'
- | 'title_ASC'
- | 'title_DESC'
- | 'content_ASC'
- | 'content_DESC'
-
-export type UserOrderByInput =
- | 'id_ASC'
- | 'id_DESC'
- | 'email_ASC'
- | 'email_DESC'
- | 'name_ASC'
- | 'name_DESC'
- | 'createdAt_ASC'
- | 'createdAt_DESC'
- | 'updatedAt_ASC'
- | 'updatedAt_DESC'
-
-export type MutationType = 'CREATED' | 'UPDATED' | 'DELETED'
-
-export interface UserCreateWithoutPostsInput {
- email: String;
- name?: String;
-}
-
-export type PostWhereUniqueInput = AtLeastOne<{
- id: ID_Input,
-}>
-
-export interface UserUpdateInput {
- email?: String;
- name?: String;
- posts?: PostUpdateManyWithoutAuthorInput;
-}
-
-export interface UserUpsertWithoutPostsInput {
- update: UserUpdateWithoutPostsDataInput;
- create: UserCreateWithoutPostsInput;
-}
-
-export interface PostCreateWithoutAuthorInput {
- published?: Boolean;
- title: String;
- content?: String;
-}
-
-export interface UserUpdateWithoutPostsDataInput {
- email?: String;
- name?: String;
-}
-
-export interface PostCreateManyWithoutAuthorInput {
- create?: PostCreateWithoutAuthorInput[];
- connect?: PostWhereUniqueInput[];
-}
-
-export interface UserWhereInput {
- id?: ID_Input;
- id_not?: ID_Input;
- id_in?: ID_Input[];
- id_not_in?: ID_Input[];
- id_lt?: ID_Input;
- id_lte?: ID_Input;
- id_gt?: ID_Input;
- id_gte?: ID_Input;
- id_contains?: ID_Input;
- id_not_contains?: ID_Input;
- id_starts_with?: ID_Input;
- id_not_starts_with?: ID_Input;
- id_ends_with?: ID_Input;
- id_not_ends_with?: ID_Input;
- email?: String;
- email_not?: String;
- email_in?: String[];
- email_not_in?: String[];
- email_lt?: String;
- email_lte?: String;
- email_gt?: String;
- email_gte?: String;
- email_contains?: String;
- email_not_contains?: String;
- email_starts_with?: String;
- email_not_starts_with?: String;
- email_ends_with?: String;
- email_not_ends_with?: String;
- name?: String;
- name_not?: String;
- name_in?: String[];
- name_not_in?: String[];
- name_lt?: String;
- name_lte?: String;
- name_gt?: String;
- name_gte?: String;
- name_contains?: String;
- name_not_contains?: String;
- name_starts_with?: String;
- name_not_starts_with?: String;
- name_ends_with?: String;
- name_not_ends_with?: String;
- posts_every?: PostWhereInput;
- posts_some?: PostWhereInput;
- posts_none?: PostWhereInput;
- AND?: UserWhereInput[];
- OR?: UserWhereInput[];
- NOT?: UserWhereInput[];
-}
-
-export interface PostSubscriptionWhereInput {
- mutation_in?: MutationType[];
- updatedFields_contains?: String;
- updatedFields_contains_every?: String[];
- updatedFields_contains_some?: String[];
- node?: PostWhereInput;
- AND?: PostSubscriptionWhereInput[];
- OR?: PostSubscriptionWhereInput[];
- NOT?: PostSubscriptionWhereInput[];
-}
-
-export interface PostUpsertWithWhereUniqueWithoutAuthorInput {
- where: PostWhereUniqueInput;
- update: PostUpdateWithoutAuthorDataInput;
- create: PostCreateWithoutAuthorInput;
-}
-
-export interface PostCreateInput {
- published?: Boolean;
- title: String;
- content?: String;
- author: UserCreateOneWithoutPostsInput;
-}
-
-export interface PostUpdateWithWhereUniqueWithoutAuthorInput {
- where: PostWhereUniqueInput;
- data: PostUpdateWithoutAuthorDataInput;
-}
-
-export interface UserCreateOneWithoutPostsInput {
- create?: UserCreateWithoutPostsInput;
- connect?: UserWhereUniqueInput;
-}
-
-export interface PostUpdateManyWithoutAuthorInput {
- create?: PostCreateWithoutAuthorInput[];
- delete?: PostWhereUniqueInput[];
- connect?: PostWhereUniqueInput[];
- disconnect?: PostWhereUniqueInput[];
- update?: PostUpdateWithWhereUniqueWithoutAuthorInput[];
- upsert?: PostUpsertWithWhereUniqueWithoutAuthorInput[];
-}
-
-export interface PostUpdateManyMutationInput {
- published?: Boolean;
- title?: String;
- content?: String;
-}
-
-export interface UserUpdateOneRequiredWithoutPostsInput {
- create?: UserCreateWithoutPostsInput;
- update?: UserUpdateWithoutPostsDataInput;
- upsert?: UserUpsertWithoutPostsInput;
- connect?: UserWhereUniqueInput;
-}
-
-export interface PostUpdateInput {
- published?: Boolean;
- title?: String;
- content?: String;
- author?: UserUpdateOneRequiredWithoutPostsInput;
-}
-
-export interface UserCreateInput {
- email: String;
- name?: String;
- posts?: PostCreateManyWithoutAuthorInput;
-}
-
-export interface PostWhereInput {
- id?: ID_Input;
- id_not?: ID_Input;
- id_in?: ID_Input[];
- id_not_in?: ID_Input[];
- id_lt?: ID_Input;
- id_lte?: ID_Input;
- id_gt?: ID_Input;
- id_gte?: ID_Input;
- id_contains?: ID_Input;
- id_not_contains?: ID_Input;
- id_starts_with?: ID_Input;
- id_not_starts_with?: ID_Input;
- id_ends_with?: ID_Input;
- id_not_ends_with?: ID_Input;
- createdAt?: DateTimeInput;
- createdAt_not?: DateTimeInput;
- createdAt_in?: DateTimeInput[];
- createdAt_not_in?: DateTimeInput[];
- createdAt_lt?: DateTimeInput;
- createdAt_lte?: DateTimeInput;
- createdAt_gt?: DateTimeInput;
- createdAt_gte?: DateTimeInput;
- updatedAt?: DateTimeInput;
- updatedAt_not?: DateTimeInput;
- updatedAt_in?: DateTimeInput[];
- updatedAt_not_in?: DateTimeInput[];
- updatedAt_lt?: DateTimeInput;
- updatedAt_lte?: DateTimeInput;
- updatedAt_gt?: DateTimeInput;
- updatedAt_gte?: DateTimeInput;
- published?: Boolean;
- published_not?: Boolean;
- title?: String;
- title_not?: String;
- title_in?: String[];
- title_not_in?: String[];
- title_lt?: String;
- title_lte?: String;
- title_gt?: String;
- title_gte?: String;
- title_contains?: String;
- title_not_contains?: String;
- title_starts_with?: String;
- title_not_starts_with?: String;
- title_ends_with?: String;
- title_not_ends_with?: String;
- content?: String;
- content_not?: String;
- content_in?: String[];
- content_not_in?: String[];
- content_lt?: String;
- content_lte?: String;
- content_gt?: String;
- content_gte?: String;
- content_contains?: String;
- content_not_contains?: String;
- content_starts_with?: String;
- content_not_starts_with?: String;
- content_ends_with?: String;
- content_not_ends_with?: String;
- author?: UserWhereInput;
- AND?: PostWhereInput[];
- OR?: PostWhereInput[];
- NOT?: PostWhereInput[];
-}
-
-export type UserWhereUniqueInput = AtLeastOne<{
- id: ID_Input,
- email?: String,
-}>
-
-export interface PostUpdateWithoutAuthorDataInput {
- published?: Boolean;
- title?: String;
- content?: String;
-}
-
-export interface UserUpdateManyMutationInput {
- email?: String;
- name?: String;
-}
-
-export interface UserSubscriptionWhereInput {
- mutation_in?: MutationType[];
- updatedFields_contains?: String;
- updatedFields_contains_every?: String[];
- updatedFields_contains_some?: String[];
- node?: UserWhereInput;
- AND?: UserSubscriptionWhereInput[];
- OR?: UserSubscriptionWhereInput[];
- NOT?: UserSubscriptionWhereInput[];
-}
-
-export interface NodeNode {
- id: ID_Output;
-}
-
-export interface UserPreviousValues {
- id: ID_Output;
- email: String;
- name?: String;
-}
-
-export interface UserPreviousValuesPromise
- extends Promise,
- Fragmentable {
- id: () => Promise;
- email: () => Promise;
- name: () => Promise;
-}
-
-export interface UserPreviousValuesSubscription
- extends Promise>,
- Fragmentable {
- id: () => Promise>;
- email: () => Promise>;
- name: () => Promise>;
-}
-
-export interface PostEdge {
- cursor: String;
-}
-
-export interface PostEdgePromise extends Promise, Fragmentable {
- node: () => T;
- cursor: () => Promise;
-}
-
-export interface PostEdgeSubscription
- extends Promise>,
- Fragmentable {
- node: () => T;
- cursor: () => Promise>;
-}
-
-export interface User {
- id: ID_Output;
- email: String;
- name?: String;
-}
-
-export interface UserPromise extends Promise, Fragmentable {
- id: () => Promise;
- email: () => Promise;
- name: () => Promise;
- posts: >(args?: {
- where?: PostWhereInput,
- orderBy?: PostOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => T;
-}
-
-export interface UserSubscription
- extends Promise>,
- Fragmentable {
- id: () => Promise>;
- email: () => Promise>;
- name: () => Promise>;
- posts: >>(args?: {
- where?: PostWhereInput,
- orderBy?: PostOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => T;
-}
-
-export interface AggregatePost {
- count: Int;
-}
-
-export interface AggregatePostPromise
- extends Promise,
- Fragmentable {
- count: () => Promise;
-}
-
-export interface AggregatePostSubscription
- extends Promise>,
- Fragmentable {
- count: () => Promise>;
-}
-
-export interface Post {
- id: ID_Output;
- createdAt: DateTimeOutput;
- updatedAt: DateTimeOutput;
- published: Boolean;
- title: String;
- content?: String;
-}
-
-export interface PostPromise extends Promise, Fragmentable {
- id: () => Promise;
- createdAt: () => Promise;
- updatedAt: () => Promise;
- published: () => Promise;
- title: () => Promise;
- content: () => Promise;
- author: () => T;
-}
-
-export interface PostSubscription
- extends Promise>,
- Fragmentable {
- id: () => Promise>;
- createdAt: () => Promise>;
- updatedAt: () => Promise>;
- published: () => Promise>;
- title: () => Promise>;
- content: () => Promise>;
- author: () => T;
-}
-
-export interface PageInfo {
- hasNextPage: Boolean;
- hasPreviousPage: Boolean;
- startCursor?: String;
- endCursor?: String;
-}
-
-export interface PageInfoPromise extends Promise, Fragmentable {
- hasNextPage: () => Promise;
- hasPreviousPage: () => Promise;
- startCursor: () => Promise;
- endCursor: () => Promise;
-}
-
-export interface PageInfoSubscription
- extends Promise>,
- Fragmentable {
- hasNextPage: () => Promise>;
- hasPreviousPage: () => Promise>;
- startCursor: () => Promise>;
- endCursor: () => Promise>;
-}
-
-export interface PostSubscriptionPayload {
- mutation: MutationType;
- updatedFields?: String[];
-}
-
-export interface PostSubscriptionPayloadPromise
- extends Promise,
- Fragmentable {
- mutation: () => Promise;
- node: () => T;
- updatedFields: () => Promise;
- previousValues: () => T;
-}
-
-export interface PostSubscriptionPayloadSubscription
- extends Promise>,
- Fragmentable {
- mutation: () => Promise>;
- node: () => T;
- updatedFields: () => Promise>;
- previousValues: () => T;
-}
-
-export interface PostConnection {}
-
-export interface PostConnectionPromise
- extends Promise,
- Fragmentable {
- pageInfo: () => T;
- edges: >() => T;
- aggregate: () => T;
-}
-
-export interface PostConnectionSubscription
- extends Promise>,
- Fragmentable {
- pageInfo: () => T;
- edges: >>() => T;
- aggregate: () => T;
-}
-
-export interface PostPreviousValues {
- id: ID_Output;
- createdAt: DateTimeOutput;
- updatedAt: DateTimeOutput;
- published: Boolean;
- title: String;
- content?: String;
-}
-
-export interface PostPreviousValuesPromise
- extends Promise,
- Fragmentable {
- id: () => Promise;
- createdAt: () => Promise;
- updatedAt: () => Promise;
- published: () => Promise;
- title: () => Promise;
- content: () => Promise;
-}
-
-export interface PostPreviousValuesSubscription
- extends Promise>,
- Fragmentable {
- id: () => Promise>;
- createdAt: () => Promise>;
- updatedAt: () => Promise>;
- published: () => Promise>;
- title: () => Promise>;
- content: () => Promise>;
-}
-
-export interface BatchPayload {
- count: Long;
-}
-
-export interface BatchPayloadPromise
- extends Promise,
- Fragmentable {
- count: () => Promise;
-}
-
-export interface BatchPayloadSubscription
- extends Promise>,
- Fragmentable {
- count: () => Promise>;
-}
-
-export interface AggregateUser {
- count: Int;
-}
-
-export interface AggregateUserPromise
- extends Promise,
- Fragmentable {
- count: () => Promise;
-}
-
-export interface AggregateUserSubscription
- extends Promise>,
- Fragmentable {
- count: () => Promise>;
-}
-
-export interface UserSubscriptionPayload {
- mutation: MutationType;
- updatedFields?: String[];
-}
-
-export interface UserSubscriptionPayloadPromise
- extends Promise,
- Fragmentable {
- mutation: () => Promise;
- node: () => T;
- updatedFields: () => Promise;
- previousValues: () => T;
-}
-
-export interface UserSubscriptionPayloadSubscription
- extends Promise>,
- Fragmentable {
- mutation: () => Promise>;
- node: () => T;
- updatedFields: () => Promise>;
- previousValues: () => T;
-}
-
-export interface UserConnection {}
-
-export interface UserConnectionPromise
- extends Promise,
- Fragmentable {
- pageInfo: () => T;
- edges: >() => T;
- aggregate: () => T;
-}
-
-export interface UserConnectionSubscription
- extends Promise>,
- Fragmentable {
- pageInfo: () => T;
- edges: >>() => T;
- aggregate: () => T;
-}
-
-export interface UserEdge {
- cursor: String;
-}
-
-export interface UserEdgePromise extends Promise, Fragmentable {
- node: () => T;
- cursor: () => Promise;
-}
-
-export interface UserEdgeSubscription
- extends Promise>,
- Fragmentable {
- node: () => T;
- cursor: () => Promise>;
-}
-
-/*
-The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
-*/
-export type String = string
-
-export type Long = string
-
-/*
-DateTime scalar input type, allowing Date
-*/
-export type DateTimeInput = Date | string
-
-/*
-DateTime scalar output type, which is always a string
-*/
-export type DateTimeOutput = string
-
-/*
-The `Boolean` scalar type represents `true` or `false`.
-*/
-export type Boolean = boolean
-
-/*
-The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.
-*/
-export type ID_Input = string | number
-export type ID_Output = string
-
-/*
-The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
-*/
-export type Int = number
-
-/**
- * Model Metadata
- */
-
-export const models = [
- {
- name: 'Post',
- embedded: false,
- },
- {
- name: 'User',
- embedded: false,
- },
-]
-
-/**
- * Type Defs
- */
-
-export const Prisma: ClientConstructor = makePrismaClientClass(
- { typeDefs, models, endpoint: `` },
-)
-
-export const prisma = new Prisma()
diff --git a/flow/graphql/src/generated/prisma-client/prisma-schema.js b/flow/graphql/src/generated/prisma-client/prisma-schema.js
deleted file mode 100644
index bc54a708f5ae..000000000000
--- a/flow/graphql/src/generated/prisma-client/prisma-schema.js
+++ /dev/null
@@ -1,464 +0,0 @@
-export const typeDefs = /* GraphQL */ `
- type AggregatePost {
- count: Int!
- }
-
- type AggregateUser {
- count: Int!
- }
-
- type BatchPayload {
- count: Long!
- }
-
- scalar DateTime
-
- scalar Long
-
- type Mutation {
- createPost(data: PostCreateInput!): Post!
- updatePost(data: PostUpdateInput!, where: PostWhereUniqueInput!): Post
- updateManyPosts(
- data: PostUpdateManyMutationInput!
- where: PostWhereInput
- ): BatchPayload!
- upsertPost(
- where: PostWhereUniqueInput!
- create: PostCreateInput!
- update: PostUpdateInput!
- ): Post!
- deletePost(where: PostWhereUniqueInput!): Post
- deleteManyPosts(where: PostWhereInput): BatchPayload!
- createUser(data: UserCreateInput!): User!
- updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
- updateManyUsers(
- data: UserUpdateManyMutationInput!
- where: UserWhereInput
- ): BatchPayload!
- upsertUser(
- where: UserWhereUniqueInput!
- create: UserCreateInput!
- update: UserUpdateInput!
- ): User!
- deleteUser(where: UserWhereUniqueInput!): User
- deleteManyUsers(where: UserWhereInput): BatchPayload!
- }
-
- enum MutationType {
- CREATED
- UPDATED
- DELETED
- }
-
- interface Node {
- id: ID!
- }
-
- type PageInfo {
- hasNextPage: Boolean!
- hasPreviousPage: Boolean!
- startCursor: String
- endCursor: String
- }
-
- type Post {
- id: ID!
- createdAt: DateTime!
- updatedAt: DateTime!
- published: Boolean!
- title: String!
- content: String
- author: User!
- }
-
- type PostConnection {
- pageInfo: PageInfo!
- edges: [PostEdge]!
- aggregate: AggregatePost!
- }
-
- input PostCreateInput {
- published: Boolean
- title: String!
- content: String
- author: UserCreateOneWithoutPostsInput!
- }
-
- input PostCreateManyWithoutAuthorInput {
- create: [PostCreateWithoutAuthorInput!]
- connect: [PostWhereUniqueInput!]
- }
-
- input PostCreateWithoutAuthorInput {
- published: Boolean
- title: String!
- content: String
- }
-
- type PostEdge {
- node: Post!
- cursor: String!
- }
-
- enum PostOrderByInput {
- id_ASC
- id_DESC
- createdAt_ASC
- createdAt_DESC
- updatedAt_ASC
- updatedAt_DESC
- published_ASC
- published_DESC
- title_ASC
- title_DESC
- content_ASC
- content_DESC
- }
-
- type PostPreviousValues {
- id: ID!
- createdAt: DateTime!
- updatedAt: DateTime!
- published: Boolean!
- title: String!
- content: String
- }
-
- type PostSubscriptionPayload {
- mutation: MutationType!
- node: Post
- updatedFields: [String!]
- previousValues: PostPreviousValues
- }
-
- input PostSubscriptionWhereInput {
- mutation_in: [MutationType!]
- updatedFields_contains: String
- updatedFields_contains_every: [String!]
- updatedFields_contains_some: [String!]
- node: PostWhereInput
- AND: [PostSubscriptionWhereInput!]
- OR: [PostSubscriptionWhereInput!]
- NOT: [PostSubscriptionWhereInput!]
- }
-
- input PostUpdateInput {
- published: Boolean
- title: String
- content: String
- author: UserUpdateOneRequiredWithoutPostsInput
- }
-
- input PostUpdateManyMutationInput {
- published: Boolean
- title: String
- content: String
- }
-
- input PostUpdateManyWithoutAuthorInput {
- create: [PostCreateWithoutAuthorInput!]
- delete: [PostWhereUniqueInput!]
- connect: [PostWhereUniqueInput!]
- disconnect: [PostWhereUniqueInput!]
- update: [PostUpdateWithWhereUniqueWithoutAuthorInput!]
- upsert: [PostUpsertWithWhereUniqueWithoutAuthorInput!]
- }
-
- input PostUpdateWithoutAuthorDataInput {
- published: Boolean
- title: String
- content: String
- }
-
- input PostUpdateWithWhereUniqueWithoutAuthorInput {
- where: PostWhereUniqueInput!
- data: PostUpdateWithoutAuthorDataInput!
- }
-
- input PostUpsertWithWhereUniqueWithoutAuthorInput {
- where: PostWhereUniqueInput!
- update: PostUpdateWithoutAuthorDataInput!
- create: PostCreateWithoutAuthorInput!
- }
-
- input PostWhereInput {
- id: ID
- id_not: ID
- id_in: [ID!]
- id_not_in: [ID!]
- id_lt: ID
- id_lte: ID
- id_gt: ID
- id_gte: ID
- id_contains: ID
- id_not_contains: ID
- id_starts_with: ID
- id_not_starts_with: ID
- id_ends_with: ID
- id_not_ends_with: ID
- createdAt: DateTime
- createdAt_not: DateTime
- createdAt_in: [DateTime!]
- createdAt_not_in: [DateTime!]
- createdAt_lt: DateTime
- createdAt_lte: DateTime
- createdAt_gt: DateTime
- createdAt_gte: DateTime
- updatedAt: DateTime
- updatedAt_not: DateTime
- updatedAt_in: [DateTime!]
- updatedAt_not_in: [DateTime!]
- updatedAt_lt: DateTime
- updatedAt_lte: DateTime
- updatedAt_gt: DateTime
- updatedAt_gte: DateTime
- published: Boolean
- published_not: Boolean
- title: String
- title_not: String
- title_in: [String!]
- title_not_in: [String!]
- title_lt: String
- title_lte: String
- title_gt: String
- title_gte: String
- title_contains: String
- title_not_contains: String
- title_starts_with: String
- title_not_starts_with: String
- title_ends_with: String
- title_not_ends_with: String
- content: String
- content_not: String
- content_in: [String!]
- content_not_in: [String!]
- content_lt: String
- content_lte: String
- content_gt: String
- content_gte: String
- content_contains: String
- content_not_contains: String
- content_starts_with: String
- content_not_starts_with: String
- content_ends_with: String
- content_not_ends_with: String
- author: UserWhereInput
- AND: [PostWhereInput!]
- OR: [PostWhereInput!]
- NOT: [PostWhereInput!]
- }
-
- input PostWhereUniqueInput {
- id: ID
- }
-
- type Query {
- post(where: PostWhereUniqueInput!): Post
- posts(
- where: PostWhereInput
- orderBy: PostOrderByInput
- skip: Int
- after: String
- before: String
- first: Int
- last: Int
- ): [Post]!
- postsConnection(
- where: PostWhereInput
- orderBy: PostOrderByInput
- skip: Int
- after: String
- before: String
- first: Int
- last: Int
- ): PostConnection!
- user(where: UserWhereUniqueInput!): User
- users(
- where: UserWhereInput
- orderBy: UserOrderByInput
- skip: Int
- after: String
- before: String
- first: Int
- last: Int
- ): [User]!
- usersConnection(
- where: UserWhereInput
- orderBy: UserOrderByInput
- skip: Int
- after: String
- before: String
- first: Int
- last: Int
- ): UserConnection!
- node(id: ID!): Node
- }
-
- type Subscription {
- post(where: PostSubscriptionWhereInput): PostSubscriptionPayload
- user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
- }
-
- type User {
- id: ID!
- email: String!
- name: String
- posts(
- where: PostWhereInput
- orderBy: PostOrderByInput
- skip: Int
- after: String
- before: String
- first: Int
- last: Int
- ): [Post!]
- }
-
- type UserConnection {
- pageInfo: PageInfo!
- edges: [UserEdge]!
- aggregate: AggregateUser!
- }
-
- input UserCreateInput {
- email: String!
- name: String
- posts: PostCreateManyWithoutAuthorInput
- }
-
- input UserCreateOneWithoutPostsInput {
- create: UserCreateWithoutPostsInput
- connect: UserWhereUniqueInput
- }
-
- input UserCreateWithoutPostsInput {
- email: String!
- name: String
- }
-
- type UserEdge {
- node: User!
- cursor: String!
- }
-
- enum UserOrderByInput {
- id_ASC
- id_DESC
- email_ASC
- email_DESC
- name_ASC
- name_DESC
- createdAt_ASC
- createdAt_DESC
- updatedAt_ASC
- updatedAt_DESC
- }
-
- type UserPreviousValues {
- id: ID!
- email: String!
- name: String
- }
-
- type UserSubscriptionPayload {
- mutation: MutationType!
- node: User
- updatedFields: [String!]
- previousValues: UserPreviousValues
- }
-
- input UserSubscriptionWhereInput {
- mutation_in: [MutationType!]
- updatedFields_contains: String
- updatedFields_contains_every: [String!]
- updatedFields_contains_some: [String!]
- node: UserWhereInput
- AND: [UserSubscriptionWhereInput!]
- OR: [UserSubscriptionWhereInput!]
- NOT: [UserSubscriptionWhereInput!]
- }
-
- input UserUpdateInput {
- email: String
- name: String
- posts: PostUpdateManyWithoutAuthorInput
- }
-
- input UserUpdateManyMutationInput {
- email: String
- name: String
- }
-
- input UserUpdateOneRequiredWithoutPostsInput {
- create: UserCreateWithoutPostsInput
- update: UserUpdateWithoutPostsDataInput
- upsert: UserUpsertWithoutPostsInput
- connect: UserWhereUniqueInput
- }
-
- input UserUpdateWithoutPostsDataInput {
- email: String
- name: String
- }
-
- input UserUpsertWithoutPostsInput {
- update: UserUpdateWithoutPostsDataInput!
- create: UserCreateWithoutPostsInput!
- }
-
- input UserWhereInput {
- id: ID
- id_not: ID
- id_in: [ID!]
- id_not_in: [ID!]
- id_lt: ID
- id_lte: ID
- id_gt: ID
- id_gte: ID
- id_contains: ID
- id_not_contains: ID
- id_starts_with: ID
- id_not_starts_with: ID
- id_ends_with: ID
- id_not_ends_with: ID
- email: String
- email_not: String
- email_in: [String!]
- email_not_in: [String!]
- email_lt: String
- email_lte: String
- email_gt: String
- email_gte: String
- email_contains: String
- email_not_contains: String
- email_starts_with: String
- email_not_starts_with: String
- email_ends_with: String
- email_not_ends_with: String
- name: String
- name_not: String
- name_in: [String!]
- name_not_in: [String!]
- name_lt: String
- name_lte: String
- name_gt: String
- name_gte: String
- name_contains: String
- name_not_contains: String
- name_starts_with: String
- name_not_starts_with: String
- name_ends_with: String
- name_not_ends_with: String
- posts_every: PostWhereInput
- posts_some: PostWhereInput
- posts_none: PostWhereInput
- AND: [UserWhereInput!]
- OR: [UserWhereInput!]
- NOT: [UserWhereInput!]
- }
-
- input UserWhereUniqueInput {
- id: ID
- email: String
- }
-`
diff --git a/flow/graphql/src/index.js b/flow/graphql/src/index.js
deleted file mode 100644
index 9c4c50c4d7a4..000000000000
--- a/flow/graphql/src/index.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import { GraphQLServer } from 'graphql-yoga'
-import { prisma } from './generated/prisma-client'
-import { resolvers } from './resolvers'
-
-const server = new GraphQLServer({
- typeDefs: './src/schema.graphql',
- resolvers,
- context: {
- prisma,
- },
-})
-
-server.start(() => console.log('Server is running on http://localhost:4000'))
diff --git a/flow/graphql/src/resolvers/Mutation.js b/flow/graphql/src/resolvers/Mutation.js
deleted file mode 100644
index afd80f41aabf..000000000000
--- a/flow/graphql/src/resolvers/Mutation.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/* @flow */
-import type { Mutation_Resolvers } from '../generated/graphqlgen'
-
-export const Mutation: Mutation_Resolvers = {
- signupUser: (parent, { email, name }, ctx, info) => {
- return ctx.prisma.createUser({
- name,
- email,
- })
- },
- createDraft: (parent, { title, content, authorEmail }, ctx, info) => {
- return ctx.prisma.createPost({
- title,
- content,
- author: {
- connect: { email: authorEmail },
- },
- })
- },
- deletePost: (parent, { id }, ctx, info) => {
- return ctx.prisma.deletePost({
- id,
- })
- },
- publish: (parent, { id }, ctx, info) => {
- return ctx.prisma.updatePost({
- where: { id },
- data: {
- published: true,
- },
- })
- },
-}
diff --git a/flow/graphql/src/resolvers/Post.js b/flow/graphql/src/resolvers/Post.js
deleted file mode 100644
index 0188b6cb89fa..000000000000
--- a/flow/graphql/src/resolvers/Post.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/* @flow */
-import { Post_defaultResolvers } from '../generated/graphqlgen'
-import type { Post_Resolvers } from '../generated/graphqlgen'
-
-export const Post: Post_Resolvers = {
- ...Post_defaultResolvers,
-
- author: ({ id }, args, ctx, info) => {
- return ctx.prisma.post({ id }).author()
- },
-}
diff --git a/flow/graphql/src/resolvers/Query.js b/flow/graphql/src/resolvers/Query.js
deleted file mode 100644
index 91c69d545a42..000000000000
--- a/flow/graphql/src/resolvers/Query.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/* @flow */
-import type { Query_Resolvers } from '../generated/graphqlgen'
-
-export const Query: Query_Resolvers = {
- feed: (parent, args, ctx, info) => {
- return ctx.prisma.posts({
- where: {
- published: true,
- },
- })
- },
- filterPosts: (parent, { searchString }, ctx, info) => {
- return ctx.prisma.posts({
- where: {
- OR: [
- {
- title_contains: searchString,
- },
- {
- content_contains: searchString,
- },
- ],
- },
- })
- },
- post: (parent, { id }, ctx, info) => {
- return ctx.prisma.post({ id })
- },
-}
diff --git a/flow/graphql/src/resolvers/User.js b/flow/graphql/src/resolvers/User.js
deleted file mode 100644
index 40f4ff1c614f..000000000000
--- a/flow/graphql/src/resolvers/User.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/* @flow */
-import { User_defaultResolvers } from '../generated/graphqlgen'
-import type { User_Resolvers } from '../generated/graphqlgen'
-
-export const User: User_Resolvers = {
- ...User_defaultResolvers,
-
- posts: ({ id }, args, ctx, info) => {
- return ctx.prisma.user({ id }).posts()
- },
-}
diff --git a/flow/graphql/src/resolvers/index.js b/flow/graphql/src/resolvers/index.js
deleted file mode 100644
index d660c9bed885..000000000000
--- a/flow/graphql/src/resolvers/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// @flow
-// This resolver file was scaffolded by github.com/prisma/graphqlgen, DO NOT EDIT.
-// Please do not import this file directly but copy & paste to your application code.
-
-import type { Resolvers } from '../generated/graphqlgen'
-
-import { Query } from './Query'
-import { Post } from './Post'
-import { User } from './User'
-import { Mutation } from './Mutation'
-
-export const resolvers: Resolvers = {
- Query,
- Post,
- User,
- Mutation,
-}
diff --git a/flow/graphql/src/schema.graphql b/flow/graphql/src/schema.graphql
deleted file mode 100644
index dbed32c15f19..000000000000
--- a/flow/graphql/src/schema.graphql
+++ /dev/null
@@ -1,31 +0,0 @@
-scalar DateTime
-
-type Query {
- feed: [Post!]!
- filterPosts(searchString: String): [Post!]!
- post(id: ID!): Post
-}
-
-type Mutation {
- signupUser(email: String!, name: String): User!
- createDraft(title: String!, content: String, authorEmail: String!): Post!
- deletePost(id: ID!): Post
- publish(id: ID!): Post
-}
-
-type Post {
- id: ID!
- createdAt: DateTime!
- updatedAt: DateTime!
- published: Boolean!
- title: String!
- content: String
- author: User!
-}
-
-type User {
- id: ID!
- email: String!
- name: String
- posts: [Post!]!
-}
\ No newline at end of file
diff --git a/flow/graphql/src/types.js b/flow/graphql/src/types.js
deleted file mode 100644
index 4a9d843563dc..000000000000
--- a/flow/graphql/src/types.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * @flow
- */
-
-// The comment will be removed once this is fixed: https://github.com/prisma/prisma/issues/3630
-// import type { Prisma } from './generated/prisma-client'
-
-export interface Context {
- // prisma: Prisma
- prisma: any;
-}
diff --git a/flow/script/.babelrc b/flow/script/.babelrc
deleted file mode 100644
index 99f037f55d20..000000000000
--- a/flow/script/.babelrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "presets": ["@babel/preset-env", "@babel/preset-flow"]
-}
\ No newline at end of file
diff --git a/flow/script/.flowconfig b/flow/script/.flowconfig
deleted file mode 100644
index 1454726c4c08..000000000000
--- a/flow/script/.flowconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-[ignore]
-# this is required until this issue gets fixed: https://github.com/prisma/prisma/issues/3617
-.*/node_modules/graphql/jsutils/keyValMap.js.flow
-
-[include]
-
-[libs]
-
-[lints]
-
-[options]
-
-[strict]
diff --git a/flow/script/README.md b/flow/script/README.md
deleted file mode 100644
index a8adc403d226..000000000000
--- a/flow/script/README.md
+++ /dev/null
@@ -1,96 +0,0 @@
-# Simple Flow Script Example
-
-This example shows how to use the Prisma client in a **simple Flow script** to read and write data in a database.
-
-## How to use
-
-### 1. Download example & install dependencies
-
-Clone the repository:
-
-```
-git clone git@github.com:prisma/prisma-examples.git
-```
-
-Install Node dependencies:
-
-```
-cd prisma-examples/flow/script
-npm install
-```
-
-### 2. Install the Prisma CLI
-
-To run the example, you need the Prisma CLI. Please install it via NPM or [using another method](https://www.prisma.io/docs/prisma-cli-and-configuration/using-the-prisma-cli-alx4/#installation):
-
-```
-npm install -g prisma
-```
-
-### 3. Set up database & deploy Prisma datamodel
-
-For this example, you'll use a free _demo database_ (AWS Aurora) hosted in Prisma Cloud. To set up your database, run:
-
-```
-prisma deploy
-```
-
-Then, follow these steps in the interactive CLI wizard:
-
-1. Select **Demo server**
-1. **Authenticate** with Prisma Cloud in your browser (if necessary)
-1. Back in your terminal, **confirm all suggested values**
-
-
- Alternative: Run Prisma locally via Docker
-
-1. Ensure you have Docker installed on your machine. If not, you can get it from [here](https://store.docker.com/search?offering=community&type=edition).
-1. Create `docker-compose.yml` for MySQL (see [here](https://www.prisma.io/docs/prisma-server/database-connector-POSTGRES-jgfr/) for Postgres):
- ```yml
- version: '3'
- services:
- prisma:
- image: prismagraphql/prisma:1.27
- restart: always
- ports:
- - "4466:4466"
- environment:
- PRISMA_CONFIG: |
- port: 4466
- databases:
- default:
- connector: mysql
- host: mysql
- port: 3306
- user: root
- password: prisma
- migrations: true
- mysql:
- image: mysql:5.7
- restart: always
- environment:
- MYSQL_ROOT_PASSWORD: prisma
- volumes:
- - mysql:/var/lib/mysql
- volumes:
- mysql:
- ```
-1. Run `docker-compose up -d`
-1. Set the `endpoint` in `prisma.yml` to `http://localhost:4466`
-1. Run `prisma deploy`
-
-
-
-### 4. Run the script
-
-Execute the script with this command:
-
-```
-npm run start
-```
-
-## Next steps
-
-- [Use Prisma with an existing database](https://www.prisma.io/docs/-f003/)
-- [Explore the Prisma client API](https://www.prisma.io/client/client-flow)
-- [Learn more about the GraphQL schema](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e/)
\ No newline at end of file
diff --git a/flow/script/package.json b/flow/script/package.json
deleted file mode 100644
index 51e1c7e00ecb..000000000000
--- a/flow/script/package.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "name": "script",
- "devDependencies": {
- "@babel/node": "7.2.2",
- "@babel/core": "7.3.3",
- "@babel/preset-env": "7.3.1",
- "@babel/preset-flow": "7.0.0",
- "flow-bin": "0.93.0"
- },
- "dependencies": {
- "prisma-client-lib": "1.27.1"
- },
- "scripts": {
- "start": "babel-node src/script.js",
- "flow": "flow"
- }
-}
diff --git a/flow/script/prisma/datamodel.prisma b/flow/script/prisma/datamodel.prisma
deleted file mode 100644
index 74e803e03f72..000000000000
--- a/flow/script/prisma/datamodel.prisma
+++ /dev/null
@@ -1,16 +0,0 @@
-type User {
- id: ID! @unique
- email: String! @unique
- name: String
- posts: [Post!]!
-}
-
-type Post {
- id: ID! @unique
- createdAt: DateTime!
- updatedAt: DateTime!
- published: Boolean! @default(value: "false")
- title: String!
- content: String
- author: User!
-}
\ No newline at end of file
diff --git a/flow/script/prisma/prisma.yml b/flow/script/prisma/prisma.yml
deleted file mode 100644
index f58d63fc5490..000000000000
--- a/flow/script/prisma/prisma.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Specifies the HTTP endpoint of your Prisma API.
-endpoint: ''
-
-# Defines your models, each model is mapped to the database as a table.
-datamodel: datamodel.prisma
-
-# Specifies the language and directory for the generated Prisma client.
-generate:
- - generator: flow-client
- output: ../src/generated/prisma-client/
-
-# Ensures Prisma client is re-generated after a datamodel change.
-hooks:
- post-deploy:
- - prisma generate
-
-# Seeds initial data into the database by running a script.
-seed:
- import: seed.graphql
\ No newline at end of file
diff --git a/flow/script/prisma/seed.graphql b/flow/script/prisma/seed.graphql
deleted file mode 100644
index 0542eaea579a..000000000000
--- a/flow/script/prisma/seed.graphql
+++ /dev/null
@@ -1,32 +0,0 @@
-mutation {
- user1: createUser(data: {
- email: "alice@prisma.io"
- name: "Alice"
- posts: {
- create: {
- title: "Join us for GraphQL Conf 2019 in Berlin"
- content: "https://www.graphqlconf.org/"
- published: true
- }
- }
- }) {
- id
- }
-
- user2: createUser(data: {
- email: "bob@prisma.io"
- name: "Bob"
- posts: {
- create: [{
- title: "Subscribe to GraphQL Weekly for community news"
- content: "https://graphqlweekly.com/"
- published: true
- } {
- title: "Follow Prisma on Twitter"
- content: "https://twitter.com/prisma"
- }]
- }
- }) {
- id
- }
-}
\ No newline at end of file
diff --git a/flow/script/src/generated/prisma-client/index.js b/flow/script/src/generated/prisma-client/index.js
deleted file mode 100644
index 12c84130a911..000000000000
--- a/flow/script/src/generated/prisma-client/index.js
+++ /dev/null
@@ -1,877 +0,0 @@
-/**
- * @flow
- */
-
-// Code generated by Prisma (prisma@1.24.0). DO NOT EDIT.
-// Please don't change this file manually but run `prisma generate` to update it.
-// For more information, please read the docs: https://www.prisma.io/docs/prisma-client/
-
-import type { DocumentNode } from 'graphql'
-import type { BasePrismaOptions as BPOType } from 'prisma-client-lib'
-import { makePrismaClientClass, Model } from 'prisma-client-lib'
-import { typeDefs } from './prisma-schema'
-
-type NodePromise = Promise
-
-export type AtLeastOne = $Shape
-
-export interface Exists {
- post(where?: PostWhereInput): Promise;
- user(where?: UserWhereInput): Promise;
-}
-
-export interface Node {}
-
-export type FragmentableArray = Promise> & Fragmentable
-
-export interface Fragmentable {
- $fragment(fragment: string | DocumentNode): Promise;
-}
-
-interface PrismaInterface {
- $exists: Exists;
- $graphql: (
- query: string,
- variables?: { [key: string]: any },
- ) => Promise;
-
- /**
- * Queries
- */
-
- post: (where: PostWhereUniqueInput) => PostPromise;
- posts: (args?: {
- where?: PostWhereInput,
- orderBy?: PostOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => FragmentableArray;
- postsConnection: (args?: {
- where?: PostWhereInput,
- orderBy?: PostOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => PostConnectionPromise;
- user: (where: UserWhereUniqueInput) => UserPromise;
- users: (args?: {
- where?: UserWhereInput,
- orderBy?: UserOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => FragmentableArray;
- usersConnection: (args?: {
- where?: UserWhereInput,
- orderBy?: UserOrderByInput,
- skip?: Int,
- after?: String,
- before?: String,
- first?: Int,
- last?: Int,
- }) => UserConnectionPromise;
- node: (args: { id: ID_Output }) => Node;
-
- /**
- * Mutations
- */
-
- createPost: (data: PostCreateInput) => PostPromise;
- updatePost: (args: {
- data: PostUpdateInput,
- where: PostWhereUniqueInput,
- }) => PostPromise;
- updateManyPosts: (args: {
- data: PostUpdateManyMutationInput,
- where?: PostWhereInput,
- }) => BatchPayloadPromise;
- upsertPost: (args: {
- where: PostWhereUniqueInput,
- create: PostCreateInput,
- update: PostUpdateInput,
- }) => PostPromise;
- deletePost: (where: PostWhereUniqueInput) => PostPromise;
- deleteManyPosts: (where?: PostWhereInput) => BatchPayloadPromise;
- createUser: (data: UserCreateInput) => UserPromise;
- updateUser: (args: {
- data: UserUpdateInput,
- where: UserWhereUniqueInput,
- }) => UserPromise;
- updateManyUsers: (args: {
- data: UserUpdateManyMutationInput,
- where?: UserWhereInput,
- }) => BatchPayloadPromise;
- upsertUser: (args: {
- where: UserWhereUniqueInput,
- create: UserCreateInput,
- update: UserUpdateInput,
- }) => UserPromise;
- deleteUser: (where: UserWhereUniqueInput) => UserPromise;
- deleteManyUsers: (where?: UserWhereInput) => BatchPayloadPromise;
-
- /**
- * Subscriptions
- */
-
- $subscribe: Subscription;
-}
-
-export interface Subscription {
- post: (
- where?: PostSubscriptionWhereInput,
- ) => PostSubscriptionPayloadSubscription;
- user: (
- where?: UserSubscriptionWhereInput,
- ) => UserSubscriptionPayloadSubscription;
-}
-
-export type ClientConstructor = (options?: BPOType) => T
-
-/**
- * Types
- */
-
-export type PostOrderByInput =
- | 'id_ASC'
- | 'id_DESC'
- | 'createdAt_ASC'
- | 'createdAt_DESC'
- | 'updatedAt_ASC'
- | 'updatedAt_DESC'
- | 'published_ASC'
- | 'published_DESC'
- | 'title_ASC'
- | 'title_DESC'
- | 'content_ASC'
- | 'content_DESC'
-
-export type UserOrderByInput =
- | 'id_ASC'
- | 'id_DESC'
- | 'email_ASC'
- | 'email_DESC'
- | 'name_ASC'
- | 'name_DESC'
- | 'createdAt_ASC'
- | 'createdAt_DESC'
- | 'updatedAt_ASC'
- | 'updatedAt_DESC'
-
-export type MutationType = 'CREATED' | 'UPDATED' | 'DELETED'
-
-export interface UserUpdateOneRequiredWithoutPostsInput {
- create?: UserCreateWithoutPostsInput;
- update?: UserUpdateWithoutPostsDataInput;
- upsert?: UserUpsertWithoutPostsInput;
- connect?: UserWhereUniqueInput;
-}
-
-export type PostWhereUniqueInput = AtLeastOne<{
- id: ID_Input,
-}>
-
-export interface PostUpdateWithWhereUniqueWithoutAuthorInput {
- where: PostWhereUniqueInput;
- data: PostUpdateWithoutAuthorDataInput;
-}
-
-export interface UserCreateInput {
- email: String;
- name?: String;
- posts?: PostCreateManyWithoutAuthorInput;
-}
-
-export interface PostUpdateManyWithoutAuthorInput {
- create?: PostCreateWithoutAuthorInput[];
- delete?: PostWhereUniqueInput[];
- connect?: PostWhereUniqueInput[];
- disconnect?: PostWhereUniqueInput[];
- update?: PostUpdateWithWhereUniqueWithoutAuthorInput[];
- upsert?: PostUpsertWithWhereUniqueWithoutAuthorInput[];
- deleteMany?: PostScalarWhereInput[];
- updateMany?: PostUpdateManyWithWhereNestedInput[];
-}
-
-export interface UserUpsertWithoutPostsInput {
- update: UserUpdateWithoutPostsDataInput;
- create: UserCreateWithoutPostsInput;
-}
-
-export interface UserWhereInput {
- id?: ID_Input;
- id_not?: ID_Input;
- id_in?: ID_Input[];
- id_not_in?: ID_Input[];
- id_lt?: ID_Input;
- id_lte?: ID_Input;
- id_gt?: ID_Input;
- id_gte?: ID_Input;
- id_contains?: ID_Input;
- id_not_contains?: ID_Input;
- id_starts_with?: ID_Input;
- id_not_starts_with?: ID_Input;
- id_ends_with?: ID_Input;
- id_not_ends_with?: ID_Input;
- email?: String;
- email_not?: String;
- email_in?: String[];
- email_not_in?: String[];
- email_lt?: String;
- email_lte?: String;
- email_gt?: String;
- email_gte?: String;
- email_contains?: String;
- email_not_contains?: String;
- email_starts_with?: String;
- email_not_starts_with?: String;
- email_ends_with?: String;
- email_not_ends_with?: String;
- name?: String;
- name_not?: String;
- name_in?: String[];
- name_not_in?: String[];
- name_lt?: String;
- name_lte?: String;
- name_gt?: String;
- name_gte?: String;
- name_contains?: String;
- name_not_contains?: String;
- name_starts_with?: String;
- name_not_starts_with?: String;
- name_ends_with?: String;
- name_not_ends_with?: String;
- posts_every?: PostWhereInput;
- posts_some?: PostWhereInput;
- posts_none?: PostWhereInput;
- AND?: UserWhereInput[];
- OR?: UserWhereInput[];
- NOT?: UserWhereInput[];
-}
-
-export interface PostSubscriptionWhereInput {
- mutation_in?: MutationType[];
- updatedFields_contains?: String;
- updatedFields_contains_every?: String[];
- updatedFields_contains_some?: String[];
- node?: PostWhereInput;
- AND?: PostSubscriptionWhereInput[];
- OR?: PostSubscriptionWhereInput[];
- NOT?: PostSubscriptionWhereInput[];
-}
-
-export interface PostCreateInput {
- published?: Boolean;
- title: String;
- content?: String;
- author: UserCreateOneWithoutPostsInput;
-}
-
-export interface PostUpdateManyDataInput {
- published?: Boolean;
- title?: String;
- content?: String;
-}
-
-export interface UserCreateOneWithoutPostsInput {
- create?: UserCreateWithoutPostsInput;
- connect?: UserWhereUniqueInput;
-}
-
-export interface PostScalarWhereInput {
- id?: ID_Input;
- id_not?: ID_Input;
- id_in?: ID_Input[];
- id_not_in?: ID_Input[];
- id_lt?: ID_Input;
- id_lte?: ID_Input;
- id_gt?: ID_Input;
- id_gte?: ID_Input;
- id_contains?: ID_Input;
- id_not_contains?: ID_Input;
- id_starts_with?: ID_Input;
- id_not_starts_with?: ID_Input;
- id_ends_with?: ID_Input;
- id_not_ends_with?: ID_Input;
- createdAt?: DateTimeInput;
- createdAt_not?: DateTimeInput;
- createdAt_in?: DateTimeInput[];
- createdAt_not_in?: DateTimeInput[];
- createdAt_lt?: DateTimeInput;
- createdAt_lte?: DateTimeInput;
- createdAt_gt?: DateTimeInput;
- createdAt_gte?: DateTimeInput;
- updatedAt?: DateTimeInput;
- updatedAt_not?: DateTimeInput;
- updatedAt_in?: DateTimeInput[];
- updatedAt_not_in?: DateTimeInput[];
- updatedAt_lt?: DateTimeInput;
- updatedAt_lte?: DateTimeInput;
- updatedAt_gt?: DateTimeInput;
- updatedAt_gte?: DateTimeInput;
- published?: Boolean;
- published_not?: Boolean;
- title?: String;
- title_not?: String;
- title_in?: String[];
- title_not_in?: String[];
- title_lt?: String;
- title_lte?: String;
- title_gt?: String;
- title_gte?: String;
- title_contains?: String;
- title_not_contains?: String;
- title_starts_with?: String;
- title_not_starts_with?: String;
- title_ends_with?: String;
- title_not_ends_with?: String;
- content?: String;
- content_not?: String;
- content_in?: String[];
- content_not_in?: String[];
- content_lt?: String;
- content_lte?: String;
- content_gt?: String;
- content_gte?: String;
- content_contains?: String;
- content_not_contains?: String;
- content_starts_with?: String;
- content_not_starts_with?: String;
- content_ends_with?: String;
- content_not_ends_with?: String;
- AND?: PostScalarWhereInput[];
- OR?: PostScalarWhereInput[];
- NOT?: PostScalarWhereInput[];
-}
-
-export interface UserCreateWithoutPostsInput {
- email: String;
- name?: String;
-}
-
-export interface PostUpsertWithWhereUniqueWithoutAuthorInput {
- where: PostWhereUniqueInput;
- update: PostUpdateWithoutAuthorDataInput;
- create: PostCreateWithoutAuthorInput;
-}
-
-export interface PostUpdateInput {
- published?: Boolean;
- title?: String;
- content?: String;
- author?: UserUpdateOneRequiredWithoutPostsInput;
-}
-
-export interface PostWhereInput {
- id?: ID_Input;
- id_not?: ID_Input;
- id_in?: ID_Input[];
- id_not_in?: ID_Input[];
- id_lt?: ID_Input;
- id_lte?: ID_Input;
- id_gt?: ID_Input;
- id_gte?: ID_Input;
- id_contains?: ID_Input;
- id_not_contains?: ID_Input;
- id_starts_with?: ID_Input;
- id_not_starts_with?: ID_Input;
- id_ends_with?: ID_Input;
- id_not_ends_with?: ID_Input;
- createdAt?: DateTimeInput;
- createdAt_not?: DateTimeInput;
- createdAt_in?: DateTimeInput[];
- createdAt_not_in?: DateTimeInput[];
- createdAt_lt?: DateTimeInput;
- createdAt_lte?: DateTimeInput;
- createdAt_gt?: DateTimeInput;
- createdAt_gte?: DateTimeInput;
- updatedAt?: DateTimeInput;
- updatedAt_not?: DateTimeInput;
- updatedAt_in?: DateTimeInput[];
- updatedAt_not_in?: DateTimeInput[];
- updatedAt_lt?: DateTimeInput;
- updatedAt_lte?: DateTimeInput;
- updatedAt_gt?: DateTimeInput;
- updatedAt_gte?: DateTimeInput;
- published?: Boolean;
- published_not?: Boolean;
- title?: String;
- title_not?: String;
- title_in?: String[];
- title_not_in?: String[];
- title_lt?: String;
- title_lte?: String;
- title_gt?: String;
- title_gte?: String;
- title_contains?: String;
- title_not_contains?: String;
- title_starts_with?: String;
- title_not_starts_with?: String;
- title_ends_with?: String;
- title_not_ends_with?: String;
- content?: String;
- content_not?: String;
- content_in?: String[];
- content_not_in?: String[];
- content_lt?: String;
- content_lte?: String;
- content_gt?: String;
- content_gte?: String;
- content_contains?: String;
- content_not_contains?: String;
- content_starts_with?: String;
- content_not_starts_with?: String;
- content_ends_with?: String;
- content_not_ends_with?: String;
- author?: UserWhereInput;
- AND?: PostWhereInput[];
- OR?: PostWhereInput[];
- NOT?: PostWhereInput[];
-}
-
-export interface UserUpdateInput {
- email?: String;
- name?: String;
- posts?: PostUpdateManyWithoutAuthorInput;
-}
-
-export interface UserUpdateManyMutationInput {
- email?: String;
- name?: String;
-}
-
-export interface PostCreateManyWithoutAuthorInput {
- create?: PostCreateWithoutAuthorInput[];
- connect?: PostWhereUniqueInput[];
-}
-
-export interface PostUpdateManyMutationInput {
- published?: Boolean;
- title?: String;
- content?: String;
-}
-
-export interface PostCreateWithoutAuthorInput {
- published?: Boolean;
- title: String;
- content?: String;
-}
-
-export interface UserUpdateWithoutPostsDataInput {
- email?: String;
- name?: String;
-}
-
-export interface PostUpdateManyWithWhereNestedInput {
- where: PostScalarWhereInput;
- data: PostUpdateManyDataInput;
-}
-
-export interface UserSubscriptionWhereInput {
- mutation_in?: MutationType[];
- updatedFields_contains?: String;
- updatedFields_contains_every?: String[];
- updatedFields_contains_some?: String[];
- node?: UserWhereInput;
- AND?: UserSubscriptionWhereInput[];
- OR?: UserSubscriptionWhereInput[];
- NOT?: UserSubscriptionWhereInput[];
-}
-
-export interface PostUpdateWithoutAuthorDataInput {
- published?: Boolean;
- title?: String;
- content?: String;
-}
-
-export type UserWhereUniqueInput = AtLeastOne<{
- id: ID_Input,
- email?: String,
-}>
-
-export interface NodeNode {
- id: ID_Output;
-}
-
-export interface UserPreviousValues {
- id: ID_Output;
- email: String;
- name?: String;
-}
-
-export interface UserPreviousValuesPromise
- extends Promise,
- Fragmentable {
- id: () => Promise;
- email: () => Promise;
- name: () => Promise;
-}
-
-export interface UserPreviousValuesSubscription
- extends Promise>,
- Fragmentable {
- id: () => Promise>;
- email: () => Promise>;
- name: () => Promise>;
-}
-
-export interface PostPreviousValues {
- id: ID_Output;
- createdAt: DateTimeOutput;
- updatedAt: DateTimeOutput;
- published: Boolean;
- title: String;
- content?: String;
-}
-
-export interface PostPreviousValuesPromise
- extends Promise,
- Fragmentable {
- id: () => Promise;
- createdAt: () => Promise;
- updatedAt: () => Promise;
- published: () => Promise;
- title: () => Promise;
- content: () => Promise;
-}
-
-export interface PostPreviousValuesSubscription
- extends Promise>,
- Fragmentable {
- id: () => Promise>;
- createdAt: () => Promise>;
- updatedAt: () => Promise>;
- published: () => Promise>;
- title: () => Promise>;
- content: () => Promise>;
-}
-
-export interface Post {
- id: ID_Output;
- createdAt: DateTimeOutput;
- updatedAt: DateTimeOutput;
- published: Boolean;
- title: String;
- content?: String;
-}
-
-export interface PostPromise extends Promise, Fragmentable {
- id: () => Promise;
- createdAt: () => Promise;
- updatedAt: () => Promise;
- published: () => Promise