Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: edits for Prisma guide #9682

Merged
merged 2 commits into from
Jan 15, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 9 additions & 223 deletions docs/repo-docs/guides/tools/prisma.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,232 +10,18 @@ import { CreateTurboCallout } from './create-turbo-callout.tsx';

[Prisma](https://www.prisma.io/) unlocks a new level of developer experience when working with databases thanks to its intuitive data model, automated migrations, type-safety & auto-completion.

<CreateTurboCallout />
[Their official guide](https://www.prisma.io/docs/guides/using-prisma-orm-with-turborepo#1-create-your-monorepo-using-turborepo) describes how to integrate Prisma into a Turborepo, including:

This guide shows you how to:
- Prisma client initialization
- Packaging the client as an [Internal Package](/repo/docs/core-concepts/internal-packages)
- Performing migrations
- Working on your applications locally
- Deploying

1. Set up Prisma in a monorepo
2. Handle migration and code generation scripts
3. Ensure that they're always run whenever `dev` or `build` is run
## Example

If you've already got Prisma set up in your database, you can skip to [step 4](#create-scripts).

<Steps>
<Step>

## Create your monorepo

If you don't have an existing project, use our [quickstart](/repo/docs/getting-started/installation) to create a new monorepo.

</Step>
<Step>
## Add a new `database` package

Create a new folder called `database` inside packages with a `package.json` inside:

```json title="packages/database/package.json"
{
"name": "@repo/db",
"version": "0.0.0",
"dependencies": {
"@prisma/client": "latest" // Replace with latest version
},
"devDependencies": {
"prisma": "latest" // Replace with latest version
}
}
```

Run your package manager's install step to install the new dependencies.

</Step>
<Step>

## Run `prisma init`

`cd` into `packages/database`:
To get started with our community-supported Prisma example, run:

```bash title="Terminal"
cd packages/database
npx create-turbo@latest -e with-prisma
```

Run `npx prisma init`.

This should create several files inside `packages/database`:

- `schema.prisma` is where your [Prisma schema](https://www.prisma.io/docs/concepts/components/prisma-schema) lives. Here, you'll be able to modify the shape of your database.
- `.gitignore` adds some ignored files to git
- `.env` lets you manually specify your `DATABASE_URL` for prisma.

At this point, you should refer to the Prisma docs for [connecting your database to Prisma](https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-postgres).

Once you've got a database connected and have a few data tables to work with, you can move on.

</Step>
<Step>

## Create scripts

Let's add some scripts to the `package.json` inside `packages/database`:

```json title="packages/database/package.json"
{
"scripts": {
"db:generate": "prisma generate",
"db:push": "prisma db push --skip-generate"
}
}
```

Let's also add these scripts to `turbo.json` in the root:

```json title="./turbo.json"
{
"tasks": {
"db:generate": {
"cache": false
},
"db:push": {
"cache": false
}
}
}
```

Now, run `turbo db:push db:generate` from the root of our repository to automatically migrate our database and generate our type-safe Prisma client.

<Callout type="info">
Use the `--skip-generate` flag on `db:push` to ensure it doesn't automatically
run `prisma generate` after migrating the database. This ends up being faster
when using Turborepo because it automatically parallelizes the tasks.
</Callout>

</Step>

<Step>

## Exporting your client

Next, export the `@prisma/client` so it can used in your applications. Let's add an `index.ts` file to `packages/database`:

```ts title="packages/database/src/index.ts"
export * from '@prisma/client';
```

Following the [Just-in-Time packaging pattern](/repo/docs/core-concepts/internal-packages#just-in-time-packages), you'll also create an entrypoint to the package inside `packages/database/package.json`.

```json title="packages/database/package.json"
{
"exports": {
// [!code highlight]
".": "./src/index.ts" // [!code highlight]
} // [!code highlight]
}
```

<Callout type="info">
Note that you're using [the Just-in-Time Package
pattern](/repo/docs/core-concepts/internal-packages#just-in-time-packages)
here, which assumes your application can consume TypeScript directly. You may
need to adjust to a different strategy as if needed.
</Callout>

### Importing `database`

Import the database package into one of our apps.

Let's say you have an app at `apps/web`. Add the dependency to `apps/web/package.json`:

<PackageManagerTabs>
<Tab>
```json title="apps/web/package.json"
{
"dependencies": {
"@repo/db": "*"
}
}
```
</Tab>
<Tab>
```json title="apps/web/package.json"
{
"dependencies": {
"@repo/db": "*"
}
}
```
</Tab>
<Tab>
```json title="apps/web/package.json"
{
"dependencies": {
"@repo/db": "workspace:*"
}
}
```
</Tab>
</PackageManagerTabs>

Run your package manager's install command.

You can now import `PrismaClient` from `database` anywhere in your app:

```ts title="./apps/web/app/page.tsx"
import { PrismaClient } from '@repo/db';

const client = new PrismaClient();
```

</Step>

<Step>

## Figuring out the scripts

You now have a reusable `@repo/db` package that you can import into any of your applications and a `turbo db:push` script to push schema changes

However, your `db:generate` scripts aren't optimized yet. They provide crucial code to our `dev` and `build` tasks. If a new developer runs `turbo dev` on an application without running `db:generate` first, they'll get errors.

So, let's make sure that `db:generate` is always run _before_ you run `dev`:

```json title="./turbo.json"
{
"tasks": {
"dev": {
"dependsOn": ["^db:generate"],
"cache": false
},
"build": {
"dependsOn": ["^db:generate"],
"outputs": ["your-outputs-here"]
},
"db:generate": {
"cache": false
}
}
}
```

Check out the section on [running tasks](/repo/docs/crafting-your-repository/running-tasks) to learn more about the `^db:generate` syntax.

### Caching the results of `prisma generate`

`prisma generate` outputs files to the filesystem, usually inside `node_modules`. In theory, it should be possible to cache the output of `prisma generate` with Turborepo to save a few seconds.

However, Prisma behaves differently with different package managers. This can lead to unpredictable results, which might lead to broken deployments in some situations. Instead of documenting the intricacies of each approach, we recommend _not_ caching the results of `prisma generate`. Since `prisma generate` usually only takes 5-6 seconds, and tends not to take longer with larger `schema` files, this seems like a fine trade-off.

You may also wish to experiment with caching the generated files in a way that satisfies the constraints for your repository.

</Step>

<Step>

## Going to production

Now that you've made it this far, you're ready to deploy your application. Depending on where your database lives, you'll want to design your deployment pipeline according to the documentation for your database's setup.

There are many factors to take into consideration from this point on, so we can't provide a one-size-fits-all solution. You likely want to visit the documentation for your database and its deployment platform to learn more.

</Step>

</Steps>
Loading