From 9559ff592e6c34cff2bdead6c0ed9fb9dd1df1b4 Mon Sep 17 00:00:00 2001 From: Sylvain Marroufin Date: Tue, 9 Apr 2024 12:39:47 +0200 Subject: [PATCH 1/2] docs(recipes): prisma usage --- docs/content/docs/3.recipes/3.prisma.md | 187 ++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 docs/content/docs/3.recipes/3.prisma.md diff --git a/docs/content/docs/3.recipes/3.prisma.md b/docs/content/docs/3.recipes/3.prisma.md new file mode 100644 index 00000000..0a18ddc9 --- /dev/null +++ b/docs/content/docs/3.recipes/3.prisma.md @@ -0,0 +1,187 @@ +--- +title: Prisma ORM +description: Learn how to setup Prisma ORM with NuxtHub. +--- + +::alert{icon="i-ph-warning" color="red" title="WIP"} +This ORM is not fully compatible with NuxtHub yet. +:br +- [Migrations](#migrations) are not supported yet. +- Deployment has an addressed issue, that will be solved soon ([unwasm/issues#21](https://github.com/unjs/unwasm/issues/21){target=_blank}). +:: + +::callout{icon="i-ph-link" to="https://www.prisma.io/orm" external} +Learn more about **Prisma ORM**. +:: + +## Setup + +To enhance your Developer Experience with the database, we can create a `usePrisma()` server composable with few steps. + +### Install Prisma + +1. Install the `prisma`, `@prisma/adapter-d1` and `@prisma/client` packages to your project: + +::code-group +```bash [pnpm] +pnpm add prisma @prisma/adapter-d1 @prisma/client +``` +```bash [yarn] +yarn add prisma @prisma/adapter-d1 @prisma/client +``` +```bash [npm] +npm install prisma @prisma/adapter-d1 @prisma/client +``` +```bash [bun] +bun add prisma @prisma/adapter-d1 @prisma/client +``` +:: + +### Init Prisma + +To init Prisma and generate its schema file, run this command: + +```bash +npx prisma init --datasource-provider sqlite +``` + +Now you have `.prisma/schema.prisma` in your project, make it match this config: + +```[schema.prisma] +generator client { + provider = "prisma-client-js" + // preview feature enabling binding adapter + previewFeatures = ["driverAdapters"] +} + +datasource db { + provider = "sqlite" + // url is required but won't be used + url = env("DATABASE_URL") +} +``` + +::note +No need to define `DATABASE_URL` in your `.env` file, it won't be used. +:: + +### Create Models + +Your models are defined in the same file as the rest of Prisma config, `schema.prisma`. Let's add a model: + +```[schema.prisma] +model Todos { + id Int @id @default(autoincrement()) + title String + completed Boolean @default(false) + createdAt DateTime @default(now()) +} +``` + +::callout{icon="i-ph-link" to="https://www.prisma.io/docs/orm/prisma-schema/data-model/models" external} +Help yourself defining your models and explore Prisma Models documentation +:: + +### Generate Prisma Client + +Run this command to generate Prisma client: + +```bash +npx prisma generate +``` + +::note +Don't forget to run this command each time you update your `schema.prisma` file. +:: + +### `usePrisma()` + +Let's define our convenient server composable to finally be able to communicate with our database: + +```ts[server/utils/prisma.ts] +import { PrismaD1 } from '@prisma/adapter-d1' +import { PrismaClient } from '@prisma/client' + +export function usePrisma() { + const binding = process.env.DB || globalThis.__env__?.DB || globalThis.DB + const adapter = new PrismaD1(binding) + return new PrismaClient({ adapter }) +} +``` + +### Migrations + +::callout{icon="i-ph-link" to="https://developers.cloudflare.com/d1/tutorials/d1-and-prisma-orm#4-create-a-table-in-the-database" external} +This is not supported at the moment as Prisma Migrate does not support D1 yet. +:: + +## Usage + +### Select + +```ts [server/api/todos/index.get.ts] +export default eventHandler(async () => { + const todos = await usePrisma().todos.findMany() + + return todos +}) +``` + +### Insert + +```ts [server/api/todos/index.post.ts] +export default eventHandler(async (event) => { + const { title } = await readBody(event) + + const todo = await usePrisma().todos.create({ + data: { + title, + createdAt: new Date() + } + }) + + return todo +}) +``` + +### Update + +```ts [server/api/todos/[id].patch.ts] +export default eventHandler(async (event) => { + const { id } = getRouterParams(event) + const { completed } = await readBody(event) + + const todo = await usePrisma().todos.update({ + where: { + id: Number(id) + }, + data: { + completed + } + }) + + return todo +}) +``` + +### Delete + +```ts [server/api/todos/[id].delete.ts] +export default eventHandler(async (event) => { + const { id } = getRouterParams(event) + + const deletedTodo = await usePrisma().todos.delete({ + where: { + id: Number(id) + } + }) + + if (!deletedTodo) { + throw createError({ + statusCode: 404, + message: 'Todo not found' + }) + } + return deletedTodo +}) +``` From 4bce26b3358446d5bb65023ac15bd9e4de7201b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Chopin?= Date: Fri, 6 Sep 2024 10:22:53 +0200 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Jon Harrell <4829245+jharrell@users.noreply.github.com> --- docs/content/docs/3.recipes/3.prisma.md | 57 +++++++++++-------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/docs/content/docs/3.recipes/3.prisma.md b/docs/content/docs/3.recipes/3.prisma.md index 0a18ddc9..cacdd69a 100644 --- a/docs/content/docs/3.recipes/3.prisma.md +++ b/docs/content/docs/3.recipes/3.prisma.md @@ -6,7 +6,6 @@ description: Learn how to setup Prisma ORM with NuxtHub. ::alert{icon="i-ph-warning" color="red" title="WIP"} This ORM is not fully compatible with NuxtHub yet. :br -- [Migrations](#migrations) are not supported yet. - Deployment has an addressed issue, that will be solved soon ([unwasm/issues#21](https://github.com/unjs/unwasm/issues/21){target=_blank}). :: @@ -16,30 +15,36 @@ Learn more about **Prisma ORM**. ## Setup -To enhance your Developer Experience with the database, we can create a `usePrisma()` server composable with few steps. +To enhance your Developer Experience with the database, we can use the `nuxt-prisma` module with a few steps. -### Install Prisma +### 1. Install Prisma -1. Install the `prisma`, `@prisma/adapter-d1` and `@prisma/client` packages to your project: +Install the `@prisma/nuxt` and `@prisma/adapter-d1` packages to your project: ::code-group ```bash [pnpm] -pnpm add prisma @prisma/adapter-d1 @prisma/client +pnpm add @prisma/nuxt @prisma/adapter-d1 ``` ```bash [yarn] -yarn add prisma @prisma/adapter-d1 @prisma/client +yarn add @prisma/nuxt @prisma/adapter-d1 ``` ```bash [npm] -npm install prisma @prisma/adapter-d1 @prisma/client +npm install @prisma/nuxt @prisma/adapter-d1 ``` ```bash [bun] -bun add prisma @prisma/adapter-d1 @prisma/client +bun add @prisma/nuxt @prisma/adapter-d1 ``` :: -### Init Prisma +### 2. Init Prisma -To init Prisma and generate its schema file, run this command: +Add `@prisma/nuxt` to the `modules` section of `nuxt.config.ts` +```javascript +export default defineNuxtConfig({ + modules: ["@prisma/nuxt"], +}); + +To generate needed directories and files, run this command: ```bash npx prisma init --datasource-provider sqlite @@ -79,10 +84,10 @@ model Todos { ``` ::callout{icon="i-ph-link" to="https://www.prisma.io/docs/orm/prisma-schema/data-model/models" external} -Help yourself defining your models and explore Prisma Models documentation +Prisma's documentation is a great resource to learn how to create the models you need. :: -### Generate Prisma Client +### 4. Generate Prisma Client Run this command to generate Prisma client: @@ -94,25 +99,15 @@ npx prisma generate Don't forget to run this command each time you update your `schema.prisma` file. :: -### `usePrisma()` - -Let's define our convenient server composable to finally be able to communicate with our database: +#### Example -```ts[server/utils/prisma.ts] -import { PrismaD1 } from '@prisma/adapter-d1' -import { PrismaClient } from '@prisma/client' +The [nuxt-prisma-nuxt-module](https://github.com/prisma/prisma-examples/tree/latest/typescript/nuxt-prisma-nuxt-module) example shows how `@prisma/nuxt` is used. -export function usePrisma() { - const binding = process.env.DB || globalThis.__env__?.DB || globalThis.DB - const adapter = new PrismaD1(binding) - return new PrismaClient({ adapter }) -} -``` -### Migrations +### 5. Migrations -::callout{icon="i-ph-link" to="https://developers.cloudflare.com/d1/tutorials/d1-and-prisma-orm#4-create-a-table-in-the-database" external} -This is not supported at the moment as Prisma Migrate does not support D1 yet. +::callout{icon="i-ph-link" to="https://www.prisma.io/docs/orm/overview/databases/cloudflare-d1#migration-workflows" external} +Prisma Migrate does not fully support migrations with D1, but it is possible. See the link for a full guide. :: ## Usage @@ -121,7 +116,7 @@ This is not supported at the moment as Prisma Migrate does not support D1 yet. ```ts [server/api/todos/index.get.ts] export default eventHandler(async () => { - const todos = await usePrisma().todos.findMany() + const todos = await usePrismaClient().todos.findMany() return todos }) @@ -133,7 +128,7 @@ export default eventHandler(async () => { export default eventHandler(async (event) => { const { title } = await readBody(event) - const todo = await usePrisma().todos.create({ + const todo = await usePrismaClient().todos.create({ data: { title, createdAt: new Date() @@ -151,7 +146,7 @@ export default eventHandler(async (event) => { const { id } = getRouterParams(event) const { completed } = await readBody(event) - const todo = await usePrisma().todos.update({ + const todo = await usePrismaClient().todos.update({ where: { id: Number(id) }, @@ -170,7 +165,7 @@ export default eventHandler(async (event) => { export default eventHandler(async (event) => { const { id } = getRouterParams(event) - const deletedTodo = await usePrisma().todos.delete({ + const deletedTodo = await usePrismaClient().todos.delete({ where: { id: Number(id) }