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..cacdd69a --- /dev/null +++ b/docs/content/docs/3.recipes/3.prisma.md @@ -0,0 +1,182 @@ +--- +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 +- 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 use the `nuxt-prisma` module with a few steps. + +### 1. Install Prisma + +Install the `@prisma/nuxt` and `@prisma/adapter-d1` packages to your project: + +::code-group +```bash [pnpm] +pnpm add @prisma/nuxt @prisma/adapter-d1 +``` +```bash [yarn] +yarn add @prisma/nuxt @prisma/adapter-d1 +``` +```bash [npm] +npm install @prisma/nuxt @prisma/adapter-d1 +``` +```bash [bun] +bun add @prisma/nuxt @prisma/adapter-d1 +``` +:: + +### 2. Init Prisma + +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 +``` + +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} +Prisma's documentation is a great resource to learn how to create the models you need. +:: + +### 4. 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. +:: + +#### Example + +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. + + +### 5. Migrations + +::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 + +### Select + +```ts [server/api/todos/index.get.ts] +export default eventHandler(async () => { + const todos = await usePrismaClient().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 usePrismaClient().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 usePrismaClient().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 usePrismaClient().todos.delete({ + where: { + id: Number(id) + } + }) + + if (!deletedTodo) { + throw createError({ + statusCode: 404, + message: 'Todo not found' + }) + } + return deletedTodo +}) +```