From e35e70541812311e48d4f7a56e7cd0aa362667ad Mon Sep 17 00:00:00 2001 From: Aidan McAlister <105178005+aidankmcalister@users.noreply.github.com> Date: Tue, 4 Nov 2025 11:54:31 -0500 Subject: [PATCH 01/23] DC-5044 `prisma-client-js` deprecated (#7219) * `prisma-client-js` deprecated * chore: empty commit * broken link updated --- .../10-overview/03-generators.mdx | 145 +++++++++--------- .../100-prisma-schema-reference.mdx | 2 +- 2 files changed, 75 insertions(+), 72 deletions(-) diff --git a/content/200-orm/100-prisma-schema/10-overview/03-generators.mdx b/content/200-orm/100-prisma-schema/10-overview/03-generators.mdx index 843aef49f0..f66f0baf9c 100644 --- a/content/200-orm/100-prisma-schema/10-overview/03-generators.mdx +++ b/content/200-orm/100-prisma-schema/10-overview/03-generators.mdx @@ -15,79 +15,10 @@ generator client { A generator determines which assets are created when you run the `prisma generate` command. -There are two generators for Prisma Client: - -- `prisma-client` (recommended): Newer and more flexible version of `prisma-client-js` with ESM support; it outputs plain TypeScript code and _requires_ a custom `output` path (read more about it [here](https://www.prisma.io/blog/why-prisma-orm-generates-code-into-node-modules-and-why-it-ll-change)) -- `prisma-client-js`: Generates Prisma Client into `node_modules` +The default generator for Prisma Client is `prisma-client`, which outputs plain TypeScript code and _requires_ a custom `output` path (read more about it [here](https://www.prisma.io/blog/why-prisma-orm-generates-code-into-node-modules-and-why-it-ll-change)). Alternatively, you can configure any npm package that complies with our generator specification. -## `prisma-client-js` - -The `prisma-client-js` is the default generator for Prisma ORM 6.X versions and before. It requires the `@prisma/client` npm package and generates Prisma Client into `node_modules`. - -### Field reference - -The generator for Prisma's JavaScript Client accepts multiple additional properties: - -- `previewFeatures`: [Preview features](/orm/reference/preview-features) to include -- `binaryTargets`: Engine binary targets for `prisma-client-js` (for example, `debian-openssl-1.1.x` if you are deploying to Ubuntu 18+, or `native` if you are working locally) - -```prisma -generator client { - provider = "prisma-client-js" - previewFeatures = ["sample-preview-feature"] - binaryTargets = ["debian-openssl-1.1.x"] // defaults to `"native"` -} -``` - -### Binary targets - -:::note - -As of [v6.16.0](https://pris.ly/release/6.16.0), Prisma ORM can be used without Rust engines in production applications. Learn more [here](/orm/prisma-client/setup-and-configuration/no-rust-engine). - -**When enabled, your Prisma Client will be generated without a Rust-based query engine binary**: - -```prisma -generator client { - provider = "prisma-client-js" // or "prisma-client" - output = "../src/generated/prisma" - engineType = "client" // no Rust engine -} -``` - -Note that [driver adapters](/orm/overview/databases/database-drivers#driver-adapters) are required if you want to use Prisma ORM without Rust engines. - -When using Prisma ORM without Rust, the `binaryTargets` field is obsolete and not needed. - -You can [read about the performance and DX improvements](https://www.prisma.io/blog/prisma-orm-without-rust-latest-performance-benchmarks) of this change on our blog. - -::: - -The `prisma-client-js` generator uses several [engines](https://github.com/prisma/prisma-engines). Engines are implemented in Rust and are used by Prisma Client in the form of executable, platform-dependent engine files. Depending on which platform you are executing your code on, you need the correct file. "Binary targets" are used to define which files should be present for the target platform(s). - -The correct file is particularly important when [deploying](/orm/prisma-client/deployment/deploy-prisma) your application to production, which often differs from your local development environment. - -#### The `native` binary target - -The `native` binary target is special. It doesn't map to a concrete operating system. Instead, when `native` is specified in `binaryTargets`, Prisma Client detects the _current_ operating system and automatically specifies the correct binary target for it. - -As an example, assume you're running **macOS** and you specify the following generator: - -```prisma file=prisma/schema.prisma -generator client { - provider = "prisma-client-js" - binaryTargets = ["native"] -} -``` - -In that case, Prisma Client detects your operating system and finds the right binary file for it based on the [list of supported operating systems](/orm/reference/prisma-schema-reference#binarytargets-options) . -If you use macOS Intel x86 (`darwin`), then the binary file that was compiled for `darwin` will be selected. -If you use macOS ARM64 (`darwin-arm64`), then the binary file that was compiled for `darwin-arm64` will be selected. - -> **Note**: The `native` binary target is the default. You can set it explicitly if you wish to include additional [binary targets](/orm/reference/prisma-schema-reference#binarytargets-options) for deployment to different environments. - ## `prisma-client` The new `prisma-client` generator offers greater control and flexibility when using Prisma ORM across different JavaScript environments (such as ESM, Bun, Deno, ...). @@ -104,7 +35,7 @@ Here are the main differences compared to `prisma-client-js`: - More flexible thanks to additional [fields](#field-reference) - Outputs plain TypeScript that's bundled just like the rest of your application code -The `prisma-client` generator has been Generally Available since [v6.16.0](https://pris.ly/releases/6.16.0) will become the new default with Prisma ORM v7. +The `prisma-client` generator has been Generally Available since [v6.16.0](https://pris.ly/releases/6.16.0) and is the default generator as of Prisma ORM v7. ### Getting started @@ -396,6 +327,78 @@ To see what the new `prisma-client` generator looks like in practice, check out | [`bun`](https://github.com/prisma/prisma-examples/tree/latest/generator-prisma-client/deno-deploy) | None | None | Deno 2 | n/a | | [`deno`](https://github.com/prisma/prisma-examples/tree/latest/generator-prisma-client/deno-deploy) | None | None | Deno 2 | n/a | +## `prisma-client-js` (Deprecated) + +:::warning Deprecated + +The `prisma-client-js` generator is **deprecated as of Prisma 7**. It was the default generator for Prisma ORM 6.X and earlier versions. We recommend migrating to [`prisma-client`](#prisma-client) for new projects and updating existing projects when possible. + +::: + +The `prisma-client-js` generator requires the `@prisma/client` npm package and generates Prisma Client into `node_modules`. + +### Field reference + +The generator for Prisma's JavaScript Client accepts multiple additional properties: + +- `previewFeatures`: [Preview features](/orm/reference/preview-features) to include +- `binaryTargets`: Engine binary targets for `prisma-client-js` (for example, `debian-openssl-1.1.x` if you are deploying to Ubuntu 18+, or `native` if you are working locally) + +```prisma +generator client { + provider = "prisma-client-js" + previewFeatures = ["sample-preview-feature"] + binaryTargets = ["debian-openssl-1.1.x"] // defaults to `"native"` +} +``` + +### Binary targets + +:::note + +As of [v6.16.0](https://pris.ly/release/6.16.0), Prisma ORM can be used without Rust engines in production applications. Learn more [here](/orm/prisma-client/setup-and-configuration/no-rust-engine). + +**When enabled, your Prisma Client will be generated without a Rust-based query engine binary**: + +```prisma +generator client { + provider = "prisma-client-js" // or "prisma-client" + output = "../src/generated/prisma" + engineType = "client" // no Rust engine +} +``` + +Note that [driver adapters](/orm/overview/databases/database-drivers#driver-adapters) are required if you want to use Prisma ORM without Rust engines. + +When using Prisma ORM without Rust, the `binaryTargets` field is obsolete and not needed. + +You can [read about the performance and DX improvements](https://www.prisma.io/blog/prisma-orm-without-rust-latest-performance-benchmarks) of this change on our blog. + +::: + +The `prisma-client-js` generator uses several [engines](https://github.com/prisma/prisma-engines). Engines are implemented in Rust and are used by Prisma Client in the form of executable, platform-dependent engine files. Depending on which platform you are executing your code on, you need the correct file. "Binary targets" are used to define which files should be present for the target platform(s). + +The correct file is particularly important when [deploying](/orm/prisma-client/deployment/deploy-prisma) your application to production, which often differs from your local development environment. + +#### The `native` binary target + +The `native` binary target is special. It doesn't map to a concrete operating system. Instead, when `native` is specified in `binaryTargets`, Prisma Client detects the _current_ operating system and automatically specifies the correct binary target for it. + +As an example, assume you're running **macOS** and you specify the following generator: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client-js" + binaryTargets = ["native"] +} +``` + +In that case, Prisma Client detects your operating system and finds the right binary file for it based on the [list of supported operating systems](/orm/reference/prisma-schema-reference#binarytargets-options) . +If you use macOS Intel x86 (`darwin`), then the binary file that was compiled for `darwin` will be selected. +If you use macOS ARM64 (`darwin-arm64`), then the binary file that was compiled for `darwin-arm64` will be selected. + +> **Note**: The `native` binary target is the default. You can set it explicitly if you wish to include additional [binary targets](/orm/reference/prisma-schema-reference#binarytargets-options) for deployment to different environments. + ## Community generators :::note diff --git a/content/200-orm/500-reference/100-prisma-schema-reference.mdx b/content/200-orm/500-reference/100-prisma-schema-reference.mdx index 4170e7843e..2ec6a8f533 100644 --- a/content/200-orm/500-reference/100-prisma-schema-reference.mdx +++ b/content/200-orm/500-reference/100-prisma-schema-reference.mdx @@ -161,7 +161,7 @@ Defines a [generator](/orm/prisma-schema/overview/generators) in the Prisma sche ### Fields for `prisma-client-js` provider -This is the default generator for Prisma ORM 6.x and earlier versions. Learn more about [generators](/orm/prisma-schema/overview/generators#prisma-client-js). +This is the default generator for Prisma ORM 6.x and earlier versions. Learn more about [generators](/orm/prisma-schema/overview/generators#prisma-client-js-deprecated). A `generator` block accepts the following fields: From f8c32d118f4002b6f93ada0fa00a23189462234c Mon Sep 17 00:00:00 2001 From: Aidan McAlister <105178005+aidankmcalister@users.noreply.github.com> Date: Wed, 5 Nov 2025 13:42:13 -0500 Subject: [PATCH 02/23] DC-5040 Env Vars via Config (#7227) * added env vars section to various pages * minor coderabbit updates * verbose removed * test removed redirect list * removed quickstart addition * converted quickstarts back --- .coderabbit.yaml | 2 ++ .github/workflows/lychee.yml | 8 ++--- .../010-generating-prisma-client.mdx | 29 +++++++++++++++++ .../325-prisma-config-reference.mdx | 31 ++++++++++++++++++- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 32aff8c11a..873a29ff16 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -1,6 +1,7 @@ # 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" +tone_instructions: "You are a principal engineer with natural teaching abilities. You detect issues and clearly explain why." reviews: collapse_walkthrough: false profile: "chill" @@ -14,6 +15,7 @@ reviews: auto_review: enabled: true drafts: false + base_branches: [".*"] finishing_touches: docstrings: enabled: false diff --git a/.github/workflows/lychee.yml b/.github/workflows/lychee.yml index 72cf3fa499..0b705f533c 100644 --- a/.github/workflows/lychee.yml +++ b/.github/workflows/lychee.yml @@ -25,7 +25,6 @@ jobs: --cache --cache-exclude-status 429,500,502,503,504 --max-cache-age 5m - --verbose --no-progress --accept 200,201,204,304,403,429 --timeout 20 @@ -50,7 +49,6 @@ jobs: args: > --cache --max-cache-age 5m - --verbose --no-progress --accept 200,201,204,304,403,429 --cache-exclude-status 429,500,502,503,504 @@ -79,8 +77,8 @@ jobs: fi if [ -n "$REPORT_FILE" ]; then - # Read the original output - ORIGINAL=$(cat "$REPORT_FILE") + # Read the original output and remove everything after 'Redirects per input' + ORIGINAL=$(cat "$REPORT_FILE" | sed '/^##* Redirects per input/,$d') # Create formatted output cat > lychee/formatted.md << EOF @@ -92,7 +90,7 @@ jobs: EOF - # Append the original content with title replacement + # Append the cleaned content with title replacement echo "$ORIGINAL" | sed 's/^# Summary$//' | sed 's/^## Summary$//' >> lychee/formatted.md fi diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx index fa86ed9fa5..8e7d257bf2 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx @@ -124,6 +124,35 @@ For improved compatibility with ECMAScript modules (ESM) and to ensure consisten ::: +## Loading environment variables + +To load environment variables in your Prisma application, you can use the `prisma.config.ts` file along with the `env` helper from `prisma/config`. This approach provides better type safety and configuration management. + +1. First, install the required dependency: + + ```bash + npm install dotenv --save-dev + ``` + +2. Create a `.env` file in your project root (if it doesn't exist) and add your database connection string: + + ```env + DATABASE_URL="your_database_connection_string_here" + ``` + +3. Update your `prisma.config.ts` file in your project root: + + ```ts + import "dotenv/config"; + import { defineConfig, env } from "prisma/config"; + + export default defineConfig({ + datasource: { + url: env("DATABASE_URL"), + }, + }); + ``` + ## The `@prisma/client` npm package The `@prisma/client` npm package consists of two key parts: diff --git a/content/200-orm/500-reference/325-prisma-config-reference.mdx b/content/200-orm/500-reference/325-prisma-config-reference.mdx index 2ecf7bfdaf..d7a5492238 100644 --- a/content/200-orm/500-reference/325-prisma-config-reference.mdx +++ b/content/200-orm/500-reference/325-prisma-config-reference.mdx @@ -597,4 +597,33 @@ You can specify a custom location for your config file when running Prisma CLI c ```terminal prisma validate --config ./path/to/myconfig.ts -``` \ No newline at end of file +``` + +## Loading environment variables + +To load environment variables in your Prisma application, you can use the `prisma.config.ts` file along with the `env` helper from `prisma/config`. This approach provides better type safety and configuration management. + +1. First, install the required dependency: + + ```bash + npm install dotenv --save-dev + ``` + +2. Create a `.env` file in your project root (if it doesn't exist) and add your database connection string: + + ```env + DATABASE_URL="your_database_connection_string_here" + ``` + +3. Update your `prisma.config.ts` file in your project root: + + ```ts + import "dotenv/config"; + import { defineConfig, env } from "prisma/config"; + + export default defineConfig({ + datasource: { + url: env("DATABASE_URL"), + }, + }); + ``` \ No newline at end of file From 87eba65abc71b017703b6d0ef0e16076578db5c8 Mon Sep 17 00:00:00 2001 From: Aidan McAlister <105178005+aidankmcalister@users.noreply.github.com> Date: Wed, 5 Nov 2025 13:42:19 -0500 Subject: [PATCH 03/23] urls deprecated (#7226) --- .../10-overview/02-data-sources.mdx | 4 ++++ .../500-reference/100-prisma-schema-reference.mdx | 10 +++++++--- .../500-reference/325-prisma-config-reference.mdx | 14 ++++++++++++-- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/content/200-orm/100-prisma-schema/10-overview/02-data-sources.mdx b/content/200-orm/100-prisma-schema/10-overview/02-data-sources.mdx index 862dea32ac..efbb38773b 100644 --- a/content/200-orm/100-prisma-schema/10-overview/02-data-sources.mdx +++ b/content/200-orm/100-prisma-schema/10-overview/02-data-sources.mdx @@ -6,6 +6,10 @@ metaDescription: 'Data sources enable Prisma to connect to your database. This p A data source determines how Prisma ORM connects to your database, and is represented by the [`datasource`](/orm/reference/prisma-schema-reference#datasource) block in the Prisma schema. The following data source uses the `postgresql` provider and includes a connection URL: +::::note +As of Prisma ORM v7, the `url`, `directUrl`, and `shadowDatabaseUrl` fields in the Prisma schema `datasource` block are deprecated. Configure these fields in [Prisma Config](/orm/reference/prisma-config-reference) instead. +:::: + ```prisma datasource db { provider = "postgresql" diff --git a/content/200-orm/500-reference/100-prisma-schema-reference.mdx b/content/200-orm/500-reference/100-prisma-schema-reference.mdx index 2ec6a8f533..ec555ae819 100644 --- a/content/200-orm/500-reference/100-prisma-schema-reference.mdx +++ b/content/200-orm/500-reference/100-prisma-schema-reference.mdx @@ -18,12 +18,16 @@ A `datasource` block accepts the following fields: | Name | Required | Type | Description | | ------------------- | -------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `provider` | **Yes** | String (`postgresql`, `mysql`, `sqlite`, `sqlserver`, `mongodb`, `cockroachdb`) | Describes which data source connectors to use. | -| `url` | **Yes** | String (URL) | Connection URL including authentication info. Most connectors use [the syntax provided by the database](/orm/reference/connection-urls#format). | -| `shadowDatabaseUrl` | No | String (URL) | Connection URL to the shadow database used by Prisma Migrate. Allows you to use a cloud-hosted database as the shadow database. | -| `directUrl` | No | String (URL) | Connection URL for direct connection to the database.

If you use a connection pooler URL in the `url` argument (for example, if you use [Prisma Accelerate](/accelerate) or pgBouncer), Prisma CLI commands that require a direct connection to the database use the URL in the `directUrl` argument.

The `directUrl` property is supported by Prisma Studio from version 5.1.0 upwards.

The `directUrl` property is not needed when using [Prisma Postgres](/postgres) database. | +| `url` | **Yes** | String (URL) | **Deprecated in Prisma ORM v7.** Configure the connection URL in Prisma Config instead: see [`datasource.url`](/orm/reference/prisma-config-reference#datasourceurl). Existing schemas continue to work, but you should migrate to Prisma Config. | +| `shadowDatabaseUrl` | No | String (URL) | **Deprecated in Prisma ORM v7.** Configure the shadow database URL in Prisma Config instead: see [`datasource.shadowDatabaseUrl`](/orm/reference/prisma-config-reference#datasourceshadowdatabaseurl). | +| `directUrl` | No | String (URL) | **Deprecated in Prisma ORM v7.** Configure the direct connection URL in Prisma Config instead: see [`datasource.directUrl`](/orm/reference/prisma-config-reference#datasourcedirecturl). | | `relationMode` | No | String (`foreignKeys`, `prisma`) | Sets whether [referential integrity](/orm/prisma-schema/data-model/relations/relation-mode) is enforced by foreign keys in the database or emulated in the Prisma Client.

In preview in versions 3.1.1 and later. The field is named `relationMode` in versions 4.5.0 and later, and was previously named `referentialIntegrity`. | | `extensions` | No | List of strings (PostgreSQL extension names) | Allows you to [represent PostgreSQL extensions in your schema](/orm/prisma-schema/postgresql-extensions). Available in preview for PostgreSQL only in Prisma ORM versions 4.5.0 and later. | +::::note +As of Prisma ORM v7, the `url`, `directUrl`, and `shadowDatabaseUrl` fields in the Prisma schema `datasource` block are deprecated. Configure these fields in [Prisma Config](/orm/reference/prisma-config-reference) instead. +:::: + The following providers are available: - [`sqlite`](/orm/overview/databases/sqlite) diff --git a/content/200-orm/500-reference/325-prisma-config-reference.mdx b/content/200-orm/500-reference/325-prisma-config-reference.mdx index d7a5492238..c81cd8e241 100644 --- a/content/200-orm/500-reference/325-prisma-config-reference.mdx +++ b/content/200-orm/500-reference/325-prisma-config-reference.mdx @@ -374,6 +374,10 @@ export default defineConfig({ Connection URL including authentication info. Most connectors use [the syntax provided by the database](/orm/reference/connection-urls#format). +:::note +Replaces the deprecated `url` field in the Prisma schema `datasource` block (Prisma ORM v7 and later). +::: + | Property | Type | Required | Default | | -------- | ------------------ | -------- | ----------------- | | `datasource.url` | `string` | Yes | `''` | @@ -381,9 +385,12 @@ Connection URL including authentication info. Most connectors use [the syntax pr ### `datasource.shadowDatabaseUrl` - Connection URL to the shadow database used by Prisma Migrate. Allows you to use a cloud-hosted database as the shadow database +:::note +Replaces the deprecated `shadowDatabaseUrl` field in the Prisma schema `datasource` block (Prisma ORM v7 and later). +::: + | Property | Type | Required | Default | | -------- | ------------------ | -------- | ----------------- | | `datasource.shadowDatabaseUrl` | `string` | No | `''` | @@ -391,9 +398,12 @@ Connection URL to the shadow database used by Prisma Migrate. Allows you to use ### `datasource.directUrl` - Connection URL for direct connection to the database. +:::note +Replaces the deprecated `directUrl` field in the Prisma schema `datasource` block (Prisma ORM v7 and later). +::: + If you use a connection pooler URL in the `url` argument (for example, if you use [Prisma Accelerate](/accelerate) or pgBouncer), Prisma CLI commands that require a direct connection to the database use the URL in the `directUrl` argument.

The `directUrl` property is supported by Prisma Studio from version 5.1.0 upwards.

The `directUrl` property is not needed when using [Prisma Postgres](/postgres) database. | Property | Type | Required | Default | From ac89f6aee1a5054eb923551e2268528444d34980 Mon Sep 17 00:00:00 2001 From: Aidan McAlister <105178005+aidankmcalister@users.noreply.github.com> Date: Fri, 7 Nov 2025 09:00:11 -0500 Subject: [PATCH 04/23] minimum version uodated (#7234) --- .../200-orm/500-reference/400-system-requirements.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content/200-orm/500-reference/400-system-requirements.mdx b/content/200-orm/500-reference/400-system-requirements.mdx index 6226c4d734..fcc713e2d2 100644 --- a/content/200-orm/500-reference/400-system-requirements.mdx +++ b/content/200-orm/500-reference/400-system-requirements.mdx @@ -17,8 +17,8 @@ The latest version of Prisma ORM requires the following software: | Tool | Minimum required version | | :-------------------- | :----------------------- | -| Node.js | 18.8 / 20.9 / 22.11 | -| TypeScript (optional) | 5.1.X | +| Node.js | 20.19.0+ | +| TypeScript (optional) | 5.4+ | | Yarn (optional) | 1.19.2 | @@ -33,14 +33,14 @@ See also: [Supported database versions](/orm/reference/supported-databases)
Expand for earlier versions -### Prisma ORM v5 +### Prisma ORM v6 -Prisma ORM v5 requires the following software: +Prisma ORM v6 requires the following software: | | Minimum required version | | :-------------------- | :----------------------- | | Node.js | 16.13 / 18.X / 20.X | -| TypeScript (optional) | 4.7.X | +| TypeScript (optional) | 4.7+ | | Yarn (optional) | 1.19.2 |
From 3bf085da615592a4a153d34bdbffeed66547dc56 Mon Sep 17 00:00:00 2001 From: Aidan McAlister <105178005+aidankmcalister@users.noreply.github.com> Date: Fri, 7 Nov 2025 09:00:22 -0500 Subject: [PATCH 05/23] DC-5043 Middleware removed from docs (#7233) * middleware deleted * more middleware removed * more middleware removed * coderabbit changes --- .../100-query-optimization-performance.mdx | 2 - .../300-client-extensions/120-query.mdx | 19 +- .../100-soft-delete-middleware.mdx | 681 ------------------ .../500-middleware/200-logging-middleware.mdx | 90 --- .../300-session-data-middleware.mdx | 72 -- .../500-middleware/index.mdx | 193 ----- .../300-client-extensions/index.mdx | 26 - .../250-opentelemetry-tracing.mdx | 18 +- .../050-prisma-client-reference.mdx | 57 -- .../050-client-preview-features.mdx | 21 +- .../800-more/350-ai-tools/100-cursor.mdx | 4 - .../800-more/350-ai-tools/300-windsurf.mdx | 4 - .../350-ai-tools/400-github-copilot.mdx | 1 - .../400-query-optimization/100-setup.mdx | 12 +- .../300-accelerate/200-getting-started.mdx | 8 +- content/700-optimize/200-getting-started.mdx | 8 +- 16 files changed, 18 insertions(+), 1198 deletions(-) delete mode 100644 content/200-orm/200-prisma-client/300-client-extensions/500-middleware/100-soft-delete-middleware.mdx delete mode 100644 content/200-orm/200-prisma-client/300-client-extensions/500-middleware/200-logging-middleware.mdx delete mode 100644 content/200-orm/200-prisma-client/300-client-extensions/500-middleware/300-session-data-middleware.mdx delete mode 100644 content/200-orm/200-prisma-client/300-client-extensions/500-middleware/index.mdx diff --git a/content/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx b/content/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx index 06593ad5e8..e4354e9313 100644 --- a/content/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx +++ b/content/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx @@ -42,8 +42,6 @@ To get started, follow the [integration guide](/optimize/getting-started) and ad You can also [log query events at the client level](/orm/prisma-client/observability-and-logging/logging#event-based-logging) to view the generated queries, their parameters, and execution times. -If you are particularly focused on monitoring query duration, consider using [logging middleware](/orm/prisma-client/client-extensions/middleware/logging-middleware). - ::: ## Using bulk queries diff --git a/content/200-orm/200-prisma-client/300-client-extensions/120-query.mdx b/content/200-orm/200-prisma-client/300-client-extensions/120-query.mdx index 733c03041b..9c408e7620 100644 --- a/content/200-orm/200-prisma-client/300-client-extensions/120-query.mdx +++ b/content/200-orm/200-prisma-client/300-client-extensions/120-query.mdx @@ -15,7 +15,7 @@ Prisma Client extensions are Generally Available from versions 4.16.0 and later. You can use the `query` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to hook into the query life-cycle and modify an incoming query or its result. -You can use Prisma Client extensions `query` component to create independent clients. This provides an alternative to [middlewares](/orm/prisma-client/client-extensions/middleware). You can bind one client to a specific filter or user, and another client to another filter or user. For example, you might do this to get [user isolation](/orm/prisma-client/client-extensions#extended-clients) in a row-level security (RLS) extension. In addition, unlike middlewares the `query` extension component gives you end-to-end type safety. [Learn more about `query` extensions versus middlewares](#query-extensions-versus-middlewares). +You can use Prisma Client extensions `query` component to create independent clients with customized behavior. You can bind one client to a specific filter or user, and another client to another filter or user. For example, you might do this to get [user isolation](/orm/prisma-client/client-extensions#extended-clients) in a row-level security (RLS) extension. The `query` extension component provides end-to-end type safety for all your custom queries. @@ -283,20 +283,3 @@ const transactionExtension = Prisma.defineExtension((prisma) => const prisma = new PrismaClient().$extends(transactionExtension) ``` -## Query extensions versus middlewares - -You can use query extensions or [middlewares](/orm/prisma-client/client-extensions/middleware) to hook into the query life-cycle and modify an incoming query or its result. Client extensions and middlewares differ in the following ways: - -- Middlewares always apply globally to the same client. Client extensions are isolated, unless you deliberately combine them. [Learn more about client extensions](/orm/prisma-client/client-extensions#about-prisma-client-extensions). - - For example, in a row-level security (RLS) scenario, you can keep each user in an entirely separate client. With middlewares, all users are active in the same client. -- During application execution, with extensions you can choose from one or more extended clients, or the standard Prisma Client. With middlewares, you cannot choose which client to use, because there is only one global client. -- Extensions benefit from end-to-end type safety and inference, but middlewares don't. - -You can use Prisma Client extensions in all scenarios where middlewares can be used. - -### If you use the `query` extension component and middlewares - -If you use the `query` extension component and middlewares in your project, then the following rules and priorities apply: - -- In your application code, you must declare all your middlewares on the main Prisma Client instance. You cannot declare them on an extended client. -- In situations where middlewares and extensions with a `query` component execute, Prisma Client executes the middlewares before it executes the extensions with the `query` component. Prisma Client executes the individual middlewares and extensions in the order in which you instantiated them with `$use` or `$extends`. diff --git a/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/100-soft-delete-middleware.mdx b/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/100-soft-delete-middleware.mdx deleted file mode 100644 index cdfe0ac784..0000000000 --- a/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/100-soft-delete-middleware.mdx +++ /dev/null @@ -1,681 +0,0 @@ ---- -title: 'Middleware sample: soft delete' -metaTitle: 'Middleware sample: soft delete (Reference)' -metaDescription: 'How to use middleware to intercept deletes and set a field value instead of deleting the record.' -toc_max_heading_level: 4 ---- - - - -The following sample uses [middleware](/orm/prisma-client/client-extensions/middleware) to perform a **soft delete**. Soft delete means that a record is **marked as deleted** by changing a field like `deleted` to `true` rather than actually being removed from the database. Reasons to use a soft delete include: - -- Regulatory requirements that mean you have to keep data for a certain amount of time -- 'Trash' / 'bin' functionality that allows users to restore content that was deleted - - - -**Note:** This page demonstrates a sample use of middleware. We do not intend the sample to be a fully functional soft delete feature and it does not cover all edge cases. For example, the middleware does not work with nested writes and therefore won't capture situations where you use `delete` or `deleteMany` as an option e.g. in an `update` query. - - - -This sample uses the following schema - note the `deleted` field on the `Post` model: - -```prisma highlight=28;normal -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} - -model User { - id Int @id @default(autoincrement()) - name String? - email String @unique - posts Post[] - followers User[] @relation("UserToUser") - user User? @relation("UserToUser", fields: [userId], references: [id]) - userId Int? -} - -model Post { - id Int @id @default(autoincrement()) - title String - content String? - user User? @relation(fields: [userId], references: [id]) - userId Int? - tags Tag[] - views Int @default(0) - //highlight-next-line - deleted Boolean @default(false) -} - -model Category { - id Int @id @default(autoincrement()) - parentCategory Category? @relation("CategoryToCategory", fields: [categoryId], references: [id]) - category Category[] @relation("CategoryToCategory") - categoryId Int? -} - -model Tag { - tagName String @id // Must be unique - posts Post[] -} -``` - - - -
-Questions answered in this page - -- How to implement soft delete middleware? -- How to block reads/updates of deleted records? -- What are trade-offs of middleware-based soft delete? - -
- -## Step 1: Store status of record - -Add a field named `deleted` to the `Post` model. You can choose between two field types depending on your requirements: - -- `Boolean` with a default value of `false`: - - ```prisma highlight=4;normal - model Post { - id Int @id @default(autoincrement()) - ... - //highlight-next-line - deleted Boolean @default(false) - } - ``` - -- Create a nullable `DateTime` field so that you know exactly _when_ a record was marked as deleted - `NULL` indicates that a record has not been deleted. In some cases, storing when a record was removed may be a regulatory requirement: - - ```prisma highlight=4;normal - model Post { - id Int @id @default(autoincrement()) - ... - //highlight-next-line - deleted DateTime? - } - ``` - -> **Note**: Using two separate fields (`isDeleted` and `deletedDate`) may result in these two fields becoming out of sync - for example, a record may be marked as deleted but have no associated date.) - -This sample uses a `Boolean` field type for simplicity. - -## Step 2: Soft delete middleware - -Add a middleware that performs the following tasks: - -- Intercepts `delete()` and `deleteMany()` queries for the `Post` model -- Changes the `params.action` to `update` and `updateMany` respectively -- Introduces a `data` argument and sets `{ deleted: true }`, preserving other filter arguments if they exist - -Run the following sample to test the soft delete middleware: - -```ts -import { PrismaClient } from '@prisma/client' - -const prisma = new PrismaClient({}) - -async function main() { - /***********************************/ - /* SOFT DELETE MIDDLEWARE */ - /***********************************/ - - prisma.$use(async (params, next) => { - // Check incoming query type - if (params.model == 'Post') { - if (params.action == 'delete') { - // Delete queries - // Change action to an update - params.action = 'update' - params.args['data'] = { deleted: true } - } - if (params.action == 'deleteMany') { - // Delete many queries - params.action = 'updateMany' - if (params.args.data != undefined) { - params.args.data['deleted'] = true - } else { - params.args['data'] = { deleted: true } - } - } - } - return next(params) - }) - - /***********************************/ - /* TEST */ - /***********************************/ - - const titles = [ - { title: 'How to create soft delete middleware' }, - { title: 'How to install Prisma' }, - { title: 'How to update a record' }, - ] - - console.log('\u001b[1;34mSTARTING SOFT DELETE TEST \u001b[0m') - console.log('\u001b[1;34m#################################### \u001b[0m') - - let i = 0 - let posts = new Array() - - // Create 3 new posts with a randomly assigned title each time - for (i == 0; i < 3; i++) { - const createPostOperation = prisma.post.create({ - data: titles[Math.floor(Math.random() * titles.length)], - }) - posts.push(createPostOperation) - } - - var postsCreated = await prisma.$transaction(posts) - - console.log( - 'Posts created with IDs: ' + - '\u001b[1;32m' + - postsCreated.map((x) => x.id) + - '\u001b[0m' - ) - - // Delete the first post from the array - const deletePost = await prisma.post.delete({ - where: { - id: postsCreated[0].id, // Random ID - }, - }) - - // Delete the 2nd two posts - const deleteManyPosts = await prisma.post.deleteMany({ - where: { - id: { - in: [postsCreated[1].id, postsCreated[2].id], - }, - }, - }) - - const getPosts = await prisma.post.findMany({ - where: { - id: { - in: postsCreated.map((x) => x.id), - }, - }, - }) - - console.log() - - console.log( - 'Deleted post with ID: ' + '\u001b[1;32m' + deletePost.id + '\u001b[0m' - ) - console.log( - 'Deleted posts with IDs: ' + - '\u001b[1;32m' + - [postsCreated[1].id + ',' + postsCreated[2].id] + - '\u001b[0m' - ) - console.log() - console.log( - 'Are the posts still available?: ' + - (getPosts.length == 3 - ? '\u001b[1;32m' + 'Yes!' + '\u001b[0m' - : '\u001b[1;31m' + 'No!' + '\u001b[0m') - ) - console.log() - console.log('\u001b[1;34m#################################### \u001b[0m') - // 4. Count ALL posts - const f = await prisma.post.findMany({}) - console.log('Number of posts: ' + '\u001b[1;32m' + f.length + '\u001b[0m') - - // 5. Count DELETED posts - const r = await prisma.post.findMany({ - where: { - deleted: true, - }, - }) - console.log( - 'Number of SOFT deleted posts: ' + '\u001b[1;32m' + r.length + '\u001b[0m' - ) -} - -main() -``` - -The sample outputs the following: - -```no-lines -STARTING SOFT DELETE TEST -#################################### -Posts created with IDs: 587,588,589 - -Deleted post with ID: 587 -Deleted posts with IDs: 588,589 - -Are the posts still available?: Yes! - -#################################### -``` - -:::tip - -Comment out the middleware to see the message change. - -::: - -✔ Pros of this approach to soft delete include: - -- Soft delete happens at data access level, which means that you cannot delete records unless you use raw SQL - -✘ Cons of this approach to soft delete include: - -- Content can still be read and updated unless you explicitly filter by `where: { deleted: false }` - in a large project with a lot of queries, there is a risk that soft deleted content will still be displayed -- You can still use raw SQL to delete records - -:::tip - -You can create rules or triggers ([MySQL](https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html) and [PostgreSQL](https://www.postgresql.org/docs/8.1/rules-update.html)) at a database level to prevent records from being deleted. - -::: - -## Step 3: Optionally prevent read/update of soft deleted records - -In step 2, we implemented middleware that prevents `Post` records from being deleted. However, you can still read and update deleted records. This step explores two ways to prevent the reading and updating of deleted records. - -> **Note**: These options are just ideas with pros and cons, you may choose to do something entirely different. - -### Option 1: Implement filters in your own application code - -In this option: - -- Prisma Client middleware is responsible for preventing records from being deleted -- Your own application code (which could be a GraphQL API, a REST API, a module) is responsible for filtering out deleted posts where necessary (`{ where: { deleted: false } }`) when reading and updating data - for example, the `getPost` GraphQL resolver never returns a deleted post - -✔ Pros of this approach to soft delete include: - -- No change to Prisma Client's create/update queries - you can easily request deleted records if you need them -- Modifying queries in middleware can have some unintended consequences, such as changing query return types (see option 2) - -✘ Cons of this approach to soft delete include: - -- Logic relating to soft delete maintained in two different places -- If your API surface is very large and maintained by multiple contributors, it may be difficult to enforce certain business rules (for example, never allow deleted records to be updated) - -### Option 2: Use middleware to determine the behavior of read/update queries for deleted records - -Option two uses Prisma Client middleware to prevent soft deleted records from being returned. The following table describes how the middleware affects each query: - -| **Query** | **Middleware logic** | **Changes to return type** | -| :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------- | -| `findUnique()` | 🔧 Change query to `findFirst` (because you cannot apply `deleted: false` filters to `findUnique()`)
🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts
🔧 From version 5.0.0, you can use `findUnique()` to apply `delete: false` filters since [non unique fields are exposed](/orm/reference/prisma-client-reference#filter-on-non-unique-fields-with-userwhereuniqueinput). | No change | | -| `findMany` | 🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts by default
🔧 Allow developers to **explicitly request** soft deleted posts by specifying `deleted: true` | No change | -| `update` | 🔧 Change query to `updateMany` (because you cannot apply `deleted: false` filters to `update`)
🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts | `{ count: n }` instead of `Post` | -| `updateMany` | 🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts | No change | - -- **Is it not possible to utilize soft delete with `findFirstOrThrow()` or `findUniqueOrThrow()`?**
- From version [5.1.0](https://github.com/prisma/prisma/releases/5.1.0), you can apply soft delete `findFirstOrThrow()` or `findUniqueOrThrow()` by using middleware. -- **Why are you making it possible to use `findMany()` with a `{ where: { deleted: true } }` filter, but not `updateMany()`?**
- This particular sample was written to support the scenario where a user can _restore_ their deleted blog post (which requires a list of soft deleted posts) - but the user should not be able to edit a deleted post. -- **Can I still `connect` or `connectOrCreate` a deleted post?**
- In this sample - yes. The middleware does not prevent you from connecting an existing, soft deleted post to a user. - -Run the following sample to see how middleware affects each query: - -```ts -import { PrismaClient, Prisma } from '@prisma/client' - -const prisma = new PrismaClient({}) - -async function main() { - /***********************************/ - /* SOFT DELETE MIDDLEWARE */ - /***********************************/ - - prisma.$use(async (params, next) => { - if (params.model == 'Post') { - if (params.action === 'findUnique' || params.action === 'findFirst') { - // Change to findFirst - you cannot filter - // by anything except ID / unique with findUnique() - params.action = 'findFirst' - // Add 'deleted' filter - // ID filter maintained - params.args.where['deleted'] = false - } - if ( - params.action === 'findFirstOrThrow' || - params.action === 'findUniqueOrThrow' - ) { - if (params.args.where) { - if (params.args.where.deleted == undefined) { - // Exclude deleted records if they have not been explicitly requested - params.args.where['deleted'] = false - } - } else { - params.args['where'] = { deleted: false } - } - } - if (params.action === 'findMany') { - // Find many queries - if (params.args.where) { - if (params.args.where.deleted == undefined) { - params.args.where['deleted'] = false - } - } else { - params.args['where'] = { deleted: false } - } - } - } - return next(params) - }) - - prisma.$use(async (params, next) => { - if (params.model == 'Post') { - if (params.action == 'update') { - // Change to updateMany - you cannot filter - // by anything except ID / unique with findUnique() - params.action = 'updateMany' - // Add 'deleted' filter - // ID filter maintained - params.args.where['deleted'] = false - } - if (params.action == 'updateMany') { - if (params.args.where != undefined) { - params.args.where['deleted'] = false - } else { - params.args['where'] = { deleted: false } - } - } - } - return next(params) - }) - - prisma.$use(async (params, next) => { - // Check incoming query type - if (params.model == 'Post') { - if (params.action == 'delete') { - // Delete queries - // Change action to an update - params.action = 'update' - params.args['data'] = { deleted: true } - } - if (params.action == 'deleteMany') { - // Delete many queries - params.action = 'updateMany' - if (params.args.data != undefined) { - params.args.data['deleted'] = true - } else { - params.args['data'] = { deleted: true } - } - } - } - return next(params) - }) - - /***********************************/ - /* TEST */ - /***********************************/ - - const titles = [ - { title: 'How to create soft delete middleware' }, - { title: 'How to install Prisma' }, - { title: 'How to update a record' }, - ] - - console.log('\u001b[1;34mSTARTING SOFT DELETE TEST \u001b[0m') - console.log('\u001b[1;34m#################################### \u001b[0m') - - let i = 0 - let posts = new Array() - - // Create 3 new posts with a randomly assigned title each time - for (i == 0; i < 3; i++) { - const createPostOperation = prisma.post.create({ - data: titles[Math.floor(Math.random() * titles.length)], - }) - posts.push(createPostOperation) - } - - var postsCreated = await prisma.$transaction(posts) - - console.log( - 'Posts created with IDs: ' + - '\u001b[1;32m' + - postsCreated.map((x) => x.id) + - '\u001b[0m' - ) - - // Delete the first post from the array - const deletePost = await prisma.post.delete({ - where: { - id: postsCreated[0].id, // Random ID - }, - }) - - // Delete the 2nd two posts - const deleteManyPosts = await prisma.post.deleteMany({ - where: { - id: { - in: [postsCreated[1].id, postsCreated[2].id], - }, - }, - }) - - const getOnePost = await prisma.post.findUnique({ - where: { - id: postsCreated[0].id, - }, - }) - - const getOneUniquePostOrThrow = async () => - await prisma.post.findUniqueOrThrow({ - where: { - id: postsCreated[0].id, - }, - }) - - const getOneFirstPostOrThrow = async () => - await prisma.post.findFirstOrThrow({ - where: { - id: postsCreated[0].id, - }, - }) - - const getPosts = await prisma.post.findMany({ - where: { - id: { - in: postsCreated.map((x) => x.id), - }, - }, - }) - - const getPostsAnDeletedPosts = await prisma.post.findMany({ - where: { - id: { - in: postsCreated.map((x) => x.id), - }, - deleted: true, - }, - }) - - const updatePost = await prisma.post.update({ - where: { - id: postsCreated[1].id, - }, - data: { - title: 'This is an updated title (update)', - }, - }) - - const updateManyDeletedPosts = await prisma.post.updateMany({ - where: { - deleted: true, - id: { - in: postsCreated.map((x) => x.id), - }, - }, - data: { - title: 'This is an updated title (updateMany)', - }, - }) - - console.log() - - console.log( - 'Deleted post (delete) with ID: ' + - '\u001b[1;32m' + - deletePost.id + - '\u001b[0m' - ) - console.log( - 'Deleted posts (deleteMany) with IDs: ' + - '\u001b[1;32m' + - [postsCreated[1].id + ',' + postsCreated[2].id] + - '\u001b[0m' - ) - console.log() - console.log( - 'findUnique: ' + - (getOnePost?.id != undefined - ? '\u001b[1;32m' + 'Posts returned!' + '\u001b[0m' - : '\u001b[1;31m' + - 'Post not returned!' + - '(Value is: ' + - JSON.stringify(getOnePost) + - ')' + - '\u001b[0m') - ) - try { - console.log('findUniqueOrThrow: ') - await getOneUniquePostOrThrow() - } catch (error) { - if ( - error instanceof Prisma.PrismaClientKnownRequestError && - error.code == 'P2025' - ) - console.log( - '\u001b[1;31m' + - 'PrismaClientKnownRequestError is catched' + - '(Error name: ' + - error.name + - ')' + - '\u001b[0m' - ) - } - try { - console.log('findFirstOrThrow: ') - await getOneFirstPostOrThrow() - } catch (error) { - if ( - error instanceof Prisma.PrismaClientKnownRequestError && - error.code == 'P2025' - ) - console.log( - '\u001b[1;31m' + - 'PrismaClientKnownRequestError is catched' + - '(Error name: ' + - error.name + - ')' + - '\u001b[0m' - ) - } - console.log() - console.log( - 'findMany: ' + - (getPosts.length == 3 - ? '\u001b[1;32m' + 'Posts returned!' + '\u001b[0m' - : '\u001b[1;31m' + 'Posts not returned!' + '\u001b[0m') - ) - console.log( - 'findMany ( delete: true ): ' + - (getPostsAnDeletedPosts.length == 3 - ? '\u001b[1;32m' + 'Posts returned!' + '\u001b[0m' - : '\u001b[1;31m' + 'Posts not returned!' + '\u001b[0m') - ) - console.log() - console.log( - 'update: ' + - (updatePost.id != undefined - ? '\u001b[1;32m' + 'Post updated!' + '\u001b[0m' - : '\u001b[1;31m' + - 'Post not updated!' + - '(Value is: ' + - JSON.stringify(updatePost) + - ')' + - '\u001b[0m') - ) - console.log( - 'updateMany ( delete: true ): ' + - (updateManyDeletedPosts.count == 3 - ? '\u001b[1;32m' + 'Posts updated!' + '\u001b[0m' - : '\u001b[1;31m' + 'Posts not updated!' + '\u001b[0m') - ) - console.log() - console.log('\u001b[1;34m#################################### \u001b[0m') - // 4. Count ALL posts - const f = await prisma.post.findMany({}) - console.log( - 'Number of active posts: ' + '\u001b[1;32m' + f.length + '\u001b[0m' - ) - - // 5. Count DELETED posts - const r = await prisma.post.findMany({ - where: { - deleted: true, - }, - }) - console.log( - 'Number of SOFT deleted posts: ' + '\u001b[1;32m' + r.length + '\u001b[0m' - ) -} - -main() -``` - -The sample outputs the following: - -``` -STARTING SOFT DELETE TEST -#################################### -Posts created with IDs: 680,681,682 - -Deleted post (delete) with ID: 680 -Deleted posts (deleteMany) with IDs: 681,682 - -findUnique: Post not returned!(Value is: []) -findMany: Posts not returned! -findMany ( delete: true ): Posts returned! - -update: Post not updated!(Value is: {"count":0}) -updateMany ( delete: true ): Posts not updated! - -#################################### -Number of active posts: 0 -Number of SOFT deleted posts: 95 -``` - -✔ Pros of this approach: - -- A developer can make a conscious choice to include deleted records in `findMany` -- You cannot accidentally read or update a deleted record - -✖ Cons of this approach: - -- Not obvious from API that you aren't getting all records and that `{ where: { deleted: false } }` is part of the default query -- Return type `update` affected because middleware changes the query to `updateMany` -- Doesn't handle complex queries with `AND`, `OR`, `every`, etc... -- Doesn't handle filtering when using `include` from another model. - -## FAQ - -### Can I add a global `includeDeleted` to the `Post` model? - -You may be tempted to 'hack' your API by adding a `includeDeleted` property to the `Post` model and make the following query possible: - -```ts -prisma.post.findMany({ where: { includeDeleted: true } }) -``` - -> **Note**: You would still need to write middleware. - -We **✘ do not** recommend this approach as it pollutes the schema with fields that do not represent real data. diff --git a/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/200-logging-middleware.mdx b/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/200-logging-middleware.mdx deleted file mode 100644 index b13eda09f9..0000000000 --- a/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/200-logging-middleware.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: 'Middleware sample: logging' -metaTitle: 'Middleware sample: logging (Reference)' -metaDescription: 'How to use middleware to log the time taken to perform any query.' ---- - - - -The following example logs the time taken for a Prisma Client query to run: - -```ts -const prisma = new PrismaClient() - -prisma.$use(async (params, next) => { - const before = Date.now() - - const result = await next(params) - - const after = Date.now() - - console.log(`Query ${params.model}.${params.action} took ${after - before}ms`) - - return result -}) - -const create = await prisma.post.create({ - data: { - title: 'Welcome to Prisma Day 2020', - }, -}) - -const createAgain = await prisma.post.create({ - data: { - title: 'All about database collation', - }, -}) -``` - -Example output: - -```no-lines -Query Post.create took 92ms -Query Post.create took 15ms -``` - -The example is based on the following sample schema: - -```prisma -generator client { - provider = "prisma-client-js" -} - -datasource db { - provider = "mysql" - url = env("DATABASE_URL") -} - -model Post { - authorId Int? - content String? - id Int @id @default(autoincrement()) - published Boolean @default(false) - title String - user User? @relation(fields: [authorId], references: [id]) - language String? - - @@index([authorId], name: "authorId") -} - -model User { - email String @unique - id Int @id @default(autoincrement()) - name String? - posts Post[] - extendedProfile Json? - role Role @default(USER) -} - -enum Role { - ADMIN - USER - MODERATOR -} -``` - - - -## Going further - -You can also use [Prisma Client extensions](/orm/prisma-client/client-extensions) to log the time it takes to perform a query. A functional example can be found in [this GitHub repository](https://github.com/prisma/prisma-client-extensions/tree/main/query-logging). diff --git a/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/300-session-data-middleware.mdx b/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/300-session-data-middleware.mdx deleted file mode 100644 index 6893713396..0000000000 --- a/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/300-session-data-middleware.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: 'Middleware sample: session data' -metaTitle: 'Middleware sample: session data (Reference)' -metaDescription: 'How to use middleware to set the value taken from session state.' -hide_table_of_contents: true ---- - - - -The following example sets the `language` field of each `Post` to the context language (taken, for example, from session state): - -```ts -const prisma = new PrismaClient() - -const contextLanguage = 'en-us' // Session state - -prisma.$use(async (params, next) => { - if (params.model == 'Post' && params.action == 'create') { - params.args.data.language = contextLanguage - } - - return next(params) -}) - -const create = await prisma.post.create({ - data: { - title: 'My post in English', - }, -}) -``` - -The example is based on the following sample schema: - -```prisma -generator client { - provider = "prisma-client-js" -} - -datasource db { - provider = "mysql" - url = env("DATABASE_URL") -} - -model Post { - authorId Int? - content String? - id Int @id @default(autoincrement()) - published Boolean @default(false) - title String - user User? @relation(fields: [authorId], references: [id]) - language String? - - @@index([authorId], name: "authorId") -} - -model User { - email String @unique - id Int @id @default(autoincrement()) - name String? - posts Post[] - extendedProfile Json? - role Role @default(USER) -} - -enum Role { - ADMIN - USER - MODERATOR -} -``` - - diff --git a/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/index.mdx b/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/index.mdx deleted file mode 100644 index 9ce688e592..0000000000 --- a/content/200-orm/200-prisma-client/300-client-extensions/500-middleware/index.mdx +++ /dev/null @@ -1,193 +0,0 @@ ---- -title: 'Middleware' -metaTitle: 'Middleware (Reference)' -metaDescription: 'Prisma Client middleware allows you to perform actions before or after any query on any model with the prisma.$use method.' ---- - - - - - -**Middleware has been removed in [v6.14.0](https://pris.ly/release/6.14.0)** and had been deprecated since [v4.16.0](https://github.com/prisma/prisma/releases/tag/4.16.0). - -We recommend using the [Prisma Client extensions `query` component type](/orm/prisma-client/client-extensions/query) as an alternative to middleware. Prisma Client extensions were first introduced into Preview in version 4.7.0 and made Generally Available in 4.16.0. - -Prisma Client extensions allow you to create independent Prisma Client instances and bind each client to a specific filter or user. For example, you could bind clients to specific users to provide user isolation. Prisma Client extensions also provide end-to-end type safety. - - - -Middlewares act as query-level lifecycle hooks, which allow you to perform an action before or after a query runs. Use the [`prisma.$use`](/orm/reference/prisma-client-reference#use) method to add middleware, as follows: - -```ts highlight=4-9,12-17;normal -const prisma = new PrismaClient() - -// Middleware 1 -//highlight-start -prisma.$use(async (params, next) => { - // Manipulate params here - const result = await next(params) - // See results here - return result -}) -//highlight-end - -// Middleware 2 -//highlight-start -prisma.$use(async (params, next) => { - // Manipulate params here - const result = await next(params) - // See results here - return result -}) -//highlight-end - -// Queries here -``` - - - -Do not invoke `next` multiple times within a middleware when using [batch transactions](/orm/prisma-client/queries/transactions#sequential-prisma-client-operations). This will cause you to break out of the transaction and lead to unexpected results. - - - -[`params`](/orm/reference/prisma-client-reference#params) represent parameters available in the middleware, such as the name of the query, and [`next`](/orm/reference/prisma-client-reference#next) represents [the next middleware in the stack _or_ the original Prisma Client query](#running-order-and-the-middleware-stack). - -Possible use cases for middleware include: - -- Setting or overwriting a field value - for example, [setting the context language of a blog post comment](/orm/prisma-client/client-extensions/middleware/session-data-middleware) -- Validating input data - for example, check user input for inappropriate language via an external service -- Intercept a `delete` query and change it to an `update` in order to perform a [soft delete](/orm/prisma-client/client-extensions/middleware/soft-delete-middleware) -- [Log the time taken to perform a query](/orm/prisma-client/client-extensions/middleware/logging-middleware) - -There are many more use cases for middleware - this list serves as inspiration for the types of problems that middleware is designed to address. - - - -## Samples - -The following sample scenarios show how to use middleware in practice: - - - -## Where to add middleware - -Add Prisma Client middleware **outside the context of the request handler**, otherwise each request adds a new _instance_ of the middleware to the stack. The following example demonstrates where to add Prisma Client middleware in the context of an Express app: - -```ts highlight=6-11;normal -import express from 'express' -import { PrismaClient } from '@prisma/client' - -const prisma = new PrismaClient() - -//highlight-start -prisma.$use(async (params, next) => { - // Manipulate params here - const result = await next(params) - // See results here - return result -}) -//highlight-end - -const app = express() -app.get('/feed', async (req, res) => { - // NO MIDDLEWARE HERE - const posts = await prisma.post.findMany({ - where: { published: true }, - include: { author: true }, - }) - res.json(posts) -}) -``` - -## Running order and the middleware stack - -If you have multiple middlewares, the running order for **each separate query** is: - -1. All logic **before** `await next(params)` in each middleware, in descending order -2. All logic **after** `await next(params)` in each middleware, in ascending order - -Depending on where you are in the stack, `await next(params)` either: - -- Runs the next middleware (in middlewares #1 and #2 in the example) _or_ -- Runs the original Prisma Client query (in middleware #3) - -```ts -const prisma = new PrismaClient() - -// Middleware 1 -prisma.$use(async (params, next) => { - console.log(params.args.data.title) - console.log('1') - const result = await next(params) - console.log('6') - return result -}) - -// Middleware 2 -prisma.$use(async (params, next) => { - console.log('2') - const result = await next(params) - console.log('5') - return result -}) - -// Middleware 3 -prisma.$use(async (params, next) => { - console.log('3') - const result = await next(params) - console.log('4') - return result -}) - -const create = await prisma.post.create({ - data: { - title: 'Welcome to Prisma Day 2020', - }, -}) - -const create2 = await prisma.post.create({ - data: { - title: 'How to Prisma!', - }, -}) -``` - -Output: - -```no-lines -Welcome to Prisma Day 2020 -1 -2 -3 -4 -5 -6 -How to Prisma! -1 -2 -3 -4 -5 -6 -``` - -## Performance and appropriate use cases - -Middleware executes for **every** query, which means that overuse has the potential to negatively impact performance. To avoid adding performance overheads: - -- Check the `params.model` and `params.action` properties early in your middleware to avoid running logic unnecessarily: - - ```ts - prisma.$use(async (params, next) => { - if (params.model == 'Post' && params.action == 'delete') { - // Logic only runs for delete action and Post model - } - return next(params) - }) - ``` - -- Consider whether middleware is the appropriate solution for your scenario. For example: - - - If you need to populate a field, can you use the [`@default`](/orm/reference/prisma-schema-reference#default) attribute? - - If you need to set the value of a `DateTime` field, can you use the `now()` function or the `@updatedAt` attribute? - - If you need to perform more complex validation, can you use a `CHECK` constraint in the database itself? diff --git a/content/200-orm/200-prisma-client/300-client-extensions/index.mdx b/content/200-orm/200-prisma-client/300-client-extensions/index.mdx index cfcf31b5e2..d0bb657074 100644 --- a/content/200-orm/200-prisma-client/300-client-extensions/index.mdx +++ b/content/200-orm/200-prisma-client/300-client-extensions/index.mdx @@ -230,32 +230,6 @@ The `Prisma.Result` type utility is used to infer the type of the extended `User ## Limitations -### Usage of `$on` and `$use` with extended clients - -`$on` and `$use` are not available in extended clients. If you would like to continue using these [client-level methods](/orm/reference/prisma-client-reference#client-methods) with an extended client, you will need to hook them up before extending the client. - -```ts -const prisma = new PrismaClient() - -prisma.$use(async (params, next) => { - console.log('This is middleware!') - return next(params) -}) - -const xPrisma = prisma.$extends({ - name: 'myExtension', - model: { - user: { - async signUp(email: string) { - await prisma.user.create({ data: { email } }) - }, - }, - }, -}) -``` - -To learn more, see our documentation on [`$on`](/orm/reference/prisma-client-reference#on) and [`$use`](/orm/reference/prisma-client-reference#use) - ### Usage of client-level methods in extended clients [Client-level methods](/orm/reference/prisma-client-reference#client-methods) do not necessarily exist on extended clients. For these clients you will need to first check for existence before using. diff --git a/content/200-orm/200-prisma-client/600-observability-and-logging/250-opentelemetry-tracing.mdx b/content/200-orm/200-prisma-client/600-observability-and-logging/250-opentelemetry-tracing.mdx index 87230c0b81..f1b866c7d3 100644 --- a/content/200-orm/200-prisma-client/600-observability-and-logging/250-opentelemetry-tracing.mdx +++ b/content/200-orm/200-prisma-client/600-observability-and-logging/250-opentelemetry-tracing.mdx @@ -181,9 +181,7 @@ const sdk = new NodeSDK({ serviceName: 'my-service-name', // Replace with your service name traceExporter, instrumentations: [ - new PrismaInstrumentation({ - middleware: true, // Enable middleware tracing if needed - }), + new PrismaInstrumentation(), ], }) @@ -285,20 +283,6 @@ export function otelSetup() { } ``` -### Trace Prisma Client middleware - -By default, tracing does not output spans for [Prisma Client middleware](/orm/prisma-client/client-extensions/middleware). To include your middleware in your traces, set `middleware` to `true` in your `registerInstrumentations` statement, as follows: - -```ts -registerInstrumentations({ - instrumentations: [new PrismaInstrumentation({ middleware: true })], -}) -``` - -This will add the following span type to your traces: - -- `prisma:client:middleware`: Represents how long the operation spent in your [middleware](/orm/prisma-client/client-extensions/middleware). - ### Trace interactive transactions When you perform an interactive transaction, you'll see the following spans in addition to the [standard spans](#trace-output): diff --git a/content/200-orm/500-reference/050-prisma-client-reference.mdx b/content/200-orm/500-reference/050-prisma-client-reference.mdx index a9fe8c5afd..cc31ef781c 100644 --- a/content/200-orm/500-reference/050-prisma-client-reference.mdx +++ b/content/200-orm/500-reference/050-prisma-client-reference.mdx @@ -5514,63 +5514,6 @@ The `$connect()` method establishes a physical connection to the database via Pr The `$on()` method allows you to subscribe to [logging events](#log) or the [exit hook](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management#exit-hooks). -### `$use()` - - - -`$use` is not available in [extended clients](/orm/prisma-client/client-extensions). Please [either migrate to query extensions](/orm/prisma-client/client-extensions/query) or use the `$use` method prior to extending your client. - - - -The `$use()` method adds [middleware](/orm/prisma-client/client-extensions/middleware) : - -```ts -prisma.$use(async (params, next) => { - console.log('This is middleware!'); - // Modify or interrogate params here - - return next(params); -}); -``` - -#### `next` - -`next` represents the "next level" in the middleware stack, which could be the next middleware or the Prisma Query, depending on [where in the stack you are](/orm/prisma-client/client-extensions/middleware#running-order-and-the-middleware-stack). - -#### `params` - -`params` is an object with information to use in your middleware. - -| Parameter | Description | -| :----------------- | :--------------------------------------------------------------------------------------------- | -| `action` | The query type - for example, `create` or `findMany`. | -| `args` | Arguments that were passed into the query - for example, `where`, `data`, or `orderBy` | -| `dataPath` | Populated if you use the [fluent API](/orm/prisma-client/queries/relation-queries#fluent-api). | -| `model` | The model type - for example, `Post` or `User`. | -| `runInTransaction` | Returns `true` if the query ran in the context of a [transaction](#transaction). | - -:::tip - -If you need the `model` property as a string, use: `String(params.model)` - -::: - -Example parameter values: - -```js -{ - args: { where: { id: 15 } }, - dataPath: [ 'select', 'author', 'select', 'posts' ], - runInTransaction: false, - action: 'findMany', - model: 'Post' -} -``` - -#### Examples - -See [middleware examples](/orm/prisma-client/client-extensions/middleware#samples). - ### `$queryRawTyped` See: [Using Raw SQL (`$queryRawTyped`)](/orm/prisma-client/using-raw-sql/typedsql). diff --git a/content/200-orm/500-reference/500-preview-features/050-client-preview-features.mdx b/content/200-orm/500-reference/500-preview-features/050-client-preview-features.mdx index 469421c32c..1ea24923c5 100644 --- a/content/200-orm/500-reference/500-preview-features/050-client-preview-features.mdx +++ b/content/200-orm/500-reference/500-preview-features/050-client-preview-features.mdx @@ -12,16 +12,16 @@ For more information, see [ORM releases and maturity levels](/orm/more/releases) The following [Preview](/orm/more/releases#preview) feature flags are available for Prisma Client and Prisma schema: -| Feature | Released into Preview | Feedback issue | -| ------------------------------------------------------------------------------- | :------------------------------------------------------------- | :-------------------------------------------------------------------: | -| [`metrics`](/orm/prisma-client/observability-and-logging/metrics) | [3.15.0](https://github.com/prisma/prisma/releases/tag/3.15.0) | [Submit feedback](https://github.com/prisma/prisma/issues/13579) | -| [`views`](/orm/prisma-schema/data-model/views) | [4.9.0](https://github.com/prisma/prisma/releases/tag/4.9.0) | [Submit feedback](https://github.com/prisma/prisma/issues/17335) | -| `relationJoins` | [5.7.0](https://github.com/prisma/prisma/releases/tag/5.7.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/22288) | -| `nativeDistinct` | [5.7.0](https://github.com/prisma/prisma/releases/tag/5.7.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/22287) | -| `typedSql` | [5.19.0](https://github.com/prisma/prisma/releases/tag/5.19.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/25106) | -| `strictUndefinedChecks` | [5.20.0](https://github.com/prisma/prisma/releases/tag/5.20.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/25271) | -| [`fullTextSearchPostgres`](/orm/prisma-client/queries/full-text-search) | [6.0.0](https://github.com/prisma/prisma/releases/tag/6.0.0) | [Submit feedback](https://github.com/prisma/prisma/issues/25773) | -| `shardKeys` | [6.10.0](https://pris.ly/release/6.10.0) | [Submit feedback](https://github.com/prisma/prisma/issues/) | +| Feature | Released into Preview | Feedback issue | +| ----------------------------------------------------------------------- | :------------------------------------------------------------- | :-------------------------------------------------------------------: | +| [`metrics`](/orm/prisma-client/observability-and-logging/metrics) | [3.15.0](https://github.com/prisma/prisma/releases/tag/3.15.0) | [Submit feedback](https://github.com/prisma/prisma/issues/13579) | +| [`views`](/orm/prisma-schema/data-model/views) | [4.9.0](https://github.com/prisma/prisma/releases/tag/4.9.0) | [Submit feedback](https://github.com/prisma/prisma/issues/17335) | +| `relationJoins` | [5.7.0](https://github.com/prisma/prisma/releases/tag/5.7.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/22288) | +| `nativeDistinct` | [5.7.0](https://github.com/prisma/prisma/releases/tag/5.7.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/22287) | +| `typedSql` | [5.19.0](https://github.com/prisma/prisma/releases/tag/5.19.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/25106) | +| `strictUndefinedChecks` | [5.20.0](https://github.com/prisma/prisma/releases/tag/5.20.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/25271) | +| [`fullTextSearchPostgres`](/orm/prisma-client/queries/full-text-search) | [6.0.0](https://github.com/prisma/prisma/releases/tag/6.0.0) | [Submit feedback](https://github.com/prisma/prisma/issues/25773) | +| `shardKeys` | [6.10.0](https://pris.ly/release/6.10.0) | [Submit feedback](https://github.com/prisma/prisma/issues/) | To enable a Preview feature, [add the feature flag to the `generator` block](#enabling-a-prisma-client-preview-feature) in your `schema.prisma` file. [Share your feedback on all Preview features on GitHub](https://github.com/prisma/prisma/issues/3108). @@ -86,6 +86,5 @@ In the list below, you can find a history of Prisma Client and Prisma schema fea | [`connectOrCreate`](/orm/reference/prisma-client-reference#connectorcreate) | [2.1.0](https://github.com/prisma/prisma/releases/tag/2.1.0) | [2.11.0](https://github.com/prisma/prisma/releases/tag/2.11.0) | | [`atomicNumberOperations`](/orm/reference/prisma-client-reference#atomic-number-operations) | [2.6.0](https://github.com/prisma/prisma/releases/tag/2.6.0) | [2.10.0](https://github.com/prisma/prisma/releases/tag/2.10.0) | | [`insensitiveFilters` (PostgreSQL)](/orm/prisma-client/queries/filtering-and-sorting#case-insensitive-filtering) | [2.5.0](https://github.com/prisma/prisma/releases/tag/2.5.0) | [2.8.0](https://github.com/prisma/prisma/releases/tag/2.8.0) | -| [`middlewares`](/orm/prisma-client/client-extensions/middleware) | [2.3.0](https://github.com/prisma/prisma/releases/tag/2.3.0) | [2.5.0](https://github.com/prisma/prisma/releases/tag/2.5.0) | | [`aggregateApi`](/orm/prisma-client/queries/aggregation-grouping-summarizing#aggregate) | [2.2.0](https://github.com/prisma/prisma/releases/tag/2.2.0) | [2.5.0](https://github.com/prisma/prisma/releases/tag/2.5.0) | | [`distinct`](/orm/reference/prisma-client-reference#distinct) | [2.3.0](https://github.com/prisma/prisma/releases/tag/2.3.0) | [2.5.0](https://github.com/prisma/prisma/releases/tag/2.5.0) | diff --git a/content/200-orm/800-more/350-ai-tools/100-cursor.mdx b/content/200-orm/800-more/350-ai-tools/100-cursor.mdx index 9d8275a356..2ab60d89ab 100644 --- a/content/200-orm/800-more/350-ai-tools/100-cursor.mdx +++ b/content/200-orm/800-more/350-ai-tools/100-cursor.mdx @@ -105,10 +105,6 @@ Schema Design Prisma Client Usage - Always use type-safe Prisma client operations. - Prefer transactions for complex, multi-step operations. -- Use Prisma middleware for cross-cutting concerns: - - Logging - - Soft delete - - Auditing - Handle optional relations explicitly. - Use Prisma's filtering and pagination capabilities. Database Migrations diff --git a/content/200-orm/800-more/350-ai-tools/300-windsurf.mdx b/content/200-orm/800-more/350-ai-tools/300-windsurf.mdx index b312ff8758..814c77f782 100644 --- a/content/200-orm/800-more/350-ai-tools/300-windsurf.mdx +++ b/content/200-orm/800-more/350-ai-tools/300-windsurf.mdx @@ -110,10 +110,6 @@ Schema Design Prisma Client Usage - Always use type-safe Prisma client operations. - Prefer transactions for complex, multi-step operations. -- Use Prisma middleware for cross-cutting concerns: - - Logging - - Soft delete - - Auditing - Handle optional relations explicitly. - Use Prisma's filtering and pagination capabilities. Database Migrations diff --git a/content/200-orm/800-more/350-ai-tools/400-github-copilot.mdx b/content/200-orm/800-more/350-ai-tools/400-github-copilot.mdx index b36b38026d..740f3b9305 100644 --- a/content/200-orm/800-more/350-ai-tools/400-github-copilot.mdx +++ b/content/200-orm/800-more/350-ai-tools/400-github-copilot.mdx @@ -206,7 +206,6 @@ You can tailor Copilot Chat's behavior in your repository by [adding a `.github/ new PrismaClient({ log: ['query', 'warn', 'error'] }); /``` * **APM integration** (Datadog, Sentry) – capture latency, errors. -* **Client extensions** for metrics: create extensions that wrap calls to emit timing and telemetry instead of middleware. ### 11. Security & Best Practices diff --git a/content/250-postgres/400-query-optimization/100-setup.mdx b/content/250-postgres/400-query-optimization/100-setup.mdx index c5d87ea33d..c4737247b1 100644 --- a/content/250-postgres/400-query-optimization/100-setup.mdx +++ b/content/250-postgres/400-query-optimization/100-setup.mdx @@ -75,18 +75,14 @@ const prisma = new PrismaClient().$extends( ).$extends(withAccelerate()); ``` -#### Using the Optimize extension with other extensions or middleware +#### Using the Optimize extension with other extensions Since [extensions are applied one after another](/orm/prisma-client/client-extensions#conflicts-in-combined-extensions), make sure you apply them in the correct order. Extensions cannot share behavior and the last extension applied takes precedence. ```ts -const prisma = new PrismaClient().$extends(withOptimize()).$extends(withAccelerate()) -``` - -If you are using [Prisma Middleware](/orm/prisma-client/client-extensions/middleware) in your application, make sure they are added before any Prisma Client extensions (like Optimize). For example: - -```ts -const prisma = new PrismaClient().$use(middleware).$extends(withOptimize()).$extends(withAccelerate()) +const prisma = new PrismaClient() + .$extends(withOptimize()) + .$extends(withAccelerate()) ``` ### 2.5. Use Prisma Optimize to generate insights diff --git a/content/300-accelerate/200-getting-started.mdx b/content/300-accelerate/200-getting-started.mdx index 3452f94539..b06abc67a4 100644 --- a/content/300-accelerate/200-getting-started.mdx +++ b/content/300-accelerate/200-getting-started.mdx @@ -148,7 +148,7 @@ const prisma = new PrismaClient().$extends(withAccelerate()) If VS Code does not recognize the `$extends` method, refer to [this section](/accelerate/faq#vs-code-does-not-recognize-the-extends-method) on how to resolve the issue. -#### Using the Accelerate extension with other extensions or middleware +#### Using the Accelerate extension with other extensions Since [extensions are applied one after another](/orm/prisma-client/client-extensions#conflicts-in-combined-extensions), make sure you apply them in the correct order. Extensions cannot share behavior and the last extension applied takes precedence. @@ -158,12 +158,6 @@ If you are using [Prisma Optimize](/optimize) in your application, make sure you const prisma = new PrismaClient().$extends(withOptimize()).$extends(withAccelerate()) ``` -If you are using [Prisma Middleware](/orm/prisma-client/client-extensions/middleware) in your application, make sure they are added before any Prisma Client extensions (like Accelerate). For example: - -```ts -const prisma = new PrismaClient().$use(middleware).$extends(withAccelerate()) -``` - ### 2.5. Use Accelerate in your database queries The `withAccelerate` extension primarily does two things: diff --git a/content/700-optimize/200-getting-started.mdx b/content/700-optimize/200-getting-started.mdx index d3e4fa9078..cb67d6a86d 100644 --- a/content/700-optimize/200-getting-started.mdx +++ b/content/700-optimize/200-getting-started.mdx @@ -70,7 +70,7 @@ const prisma = new PrismaClient().$extends( ); ``` -#### Using the Optimize extension with other extensions or middleware +#### Using the Optimize extension with other extensions Since [extensions are applied one after another](/orm/prisma-client/client-extensions#conflicts-in-combined-extensions), make sure you apply them in the correct order. Extensions cannot share behavior and the last extension applied takes precedence. @@ -80,12 +80,6 @@ If you are using [Prisma Accelerate](/accelerate) in your application, make sure const prisma = new PrismaClient().$extends(withOptimize()).$extends(withAccelerate()) ``` -If you are using [Prisma Middleware](/orm/prisma-client/client-extensions/middleware) in your application, make sure they are added before any Prisma Client extensions (like Optimize). For example: - -```ts -const prisma = new PrismaClient().$use(middleware).$extends(withOptimize()) -``` - ### 2.5. Use Prisma Optimize to generate insights Follow these steps to start generating query insights with Prisma Optimize: From a4cffaf7453d057822585554bf3be166b4b73e8a Mon Sep 17 00:00:00 2001 From: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> Date: Sat, 15 Nov 2025 14:29:31 +0600 Subject: [PATCH 06/23] DC-6174: Remove adapter, engine, directUrl, studio from config (#7256) * feat: add new features * fix: revert links * fix: broken links * fix: broken link --- .../050-overview/500-databases/900-turso.mdx | 2 +- .../500-databases/950-cloudflare-d1.mdx | 2 +- .../65-externally-managed-tables.mdx | 48 +- .../100-prisma-schema-reference.mdx | 2 +- .../325-prisma-config-reference.mdx | 528 +++++++++++------- content/800-guides/070-cloudflare-d1.mdx | 2 +- 6 files changed, 388 insertions(+), 196 deletions(-) diff --git a/content/200-orm/050-overview/500-databases/900-turso.mdx b/content/200-orm/050-overview/500-databases/900-turso.mdx index d4bdb03925..df54ae82b0 100644 --- a/content/200-orm/050-overview/500-databases/900-turso.mdx +++ b/content/200-orm/050-overview/500-databases/900-turso.mdx @@ -132,7 +132,7 @@ LIBSQL_DATABASE_TOKEN="..." ### 3. Set up Prisma Config file -Make sure that you have a [`prisma.config.ts`](/orm/reference/prisma-config-reference) file for your project. Then, set up the [migration driver adapter](/orm/reference/prisma-config-reference#adapter) to use `PrismaLibSQL`: +Make sure that you have a [`prisma.config.ts`](/orm/reference/prisma-config-reference) file for your project. Then, set up the [migration driver adapter](/orm/reference/prisma-config-reference#adapter-removed) to use `PrismaLibSQL`: ```ts file=prisma.config.ts import path from 'node:path' diff --git a/content/200-orm/050-overview/500-databases/950-cloudflare-d1.mdx b/content/200-orm/050-overview/500-databases/950-cloudflare-d1.mdx index 3f6da24c51..4ce7183a19 100644 --- a/content/200-orm/050-overview/500-databases/950-cloudflare-d1.mdx +++ b/content/200-orm/050-overview/500-databases/950-cloudflare-d1.mdx @@ -84,7 +84,7 @@ CLOUDFLARE_D1_TOKEN="F8Cg..." #### 3. Set up Prisma Config file -Make sure that you have a [`prisma.config.ts`](/orm/reference/prisma-config-reference) file for your project. Then, set up the [migration driver adapter](/orm/reference/prisma-config-reference#adapter) to reference D1: +Make sure that you have a [`prisma.config.ts`](/orm/reference/prisma-config-reference) file for your project. Then, set up the [migration driver adapter](/orm/reference/prisma-config-reference#adapter-removed) to reference D1: ```ts file=prisma.config.ts import type { PrismaConfig } from 'prisma'; diff --git a/content/200-orm/100-prisma-schema/20-data-model/65-externally-managed-tables.mdx b/content/200-orm/100-prisma-schema/20-data-model/65-externally-managed-tables.mdx index 05851a8b33..bf14f9c00f 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/65-externally-managed-tables.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/65-externally-managed-tables.mdx @@ -49,7 +49,17 @@ If you want to use external tables, here's the main workflow: You can specify externally managed tables in your [Prisma Config](/orm/reference/prisma-config-reference) file via the `tables.external` property: ```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, // required when using unstable features experimental: { // add-next-line @@ -88,7 +98,14 @@ If the external table is not referenced by any managed table—that is no manage ```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, // required when using unstable features experimental: { // add-next-line @@ -102,6 +119,7 @@ export default defineConfig({ ] }, migrations: { + path: 'prisma/migrations', // setup the users table for the shadow database initShadowDb: ` CREATE TABLE public.users (id SERIAL PRIMARY KEY); @@ -168,7 +186,17 @@ CREATE TABLE posts ( Enable use of externally managed tables via the `tables.external` property: ```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, experimental: { // add-next-line externalTables: true @@ -280,12 +308,26 @@ enum role { Then add a `migrations.initShadowDb` script so Prisma knows about the `users` table during migrations. -```ts -// prisma.config.ts +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + export default defineConfig({ - // ... + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, + experimental: { + externalTables: true + }, + tables: { + external: [ + "public.users", + ] + }, // add-start migrations: { + path: 'prisma/migrations', // setup the users table for the shadow database initShadowDb: ` CREATE TABLE public.users (id SERIAL PRIMARY KEY); diff --git a/content/200-orm/500-reference/100-prisma-schema-reference.mdx b/content/200-orm/500-reference/100-prisma-schema-reference.mdx index ec555ae819..0a113a1579 100644 --- a/content/200-orm/500-reference/100-prisma-schema-reference.mdx +++ b/content/200-orm/500-reference/100-prisma-schema-reference.mdx @@ -20,7 +20,7 @@ A `datasource` block accepts the following fields: | `provider` | **Yes** | String (`postgresql`, `mysql`, `sqlite`, `sqlserver`, `mongodb`, `cockroachdb`) | Describes which data source connectors to use. | | `url` | **Yes** | String (URL) | **Deprecated in Prisma ORM v7.** Configure the connection URL in Prisma Config instead: see [`datasource.url`](/orm/reference/prisma-config-reference#datasourceurl). Existing schemas continue to work, but you should migrate to Prisma Config. | | `shadowDatabaseUrl` | No | String (URL) | **Deprecated in Prisma ORM v7.** Configure the shadow database URL in Prisma Config instead: see [`datasource.shadowDatabaseUrl`](/orm/reference/prisma-config-reference#datasourceshadowdatabaseurl). | -| `directUrl` | No | String (URL) | **Deprecated in Prisma ORM v7.** Configure the direct connection URL in Prisma Config instead: see [`datasource.directUrl`](/orm/reference/prisma-config-reference#datasourcedirecturl). | +| `directUrl` | No | String (URL) | **Deprecated in Prisma ORM v7.** Configure the direct connection URL in Prisma Config instead: see [`datasource.directUrl`](/orm/reference/prisma-config-reference#datasourcedirecturl-removed). | | `relationMode` | No | String (`foreignKeys`, `prisma`) | Sets whether [referential integrity](/orm/prisma-schema/data-model/relations/relation-mode) is enforced by foreign keys in the database or emulated in the Prisma Client.

In preview in versions 3.1.1 and later. The field is named `relationMode` in versions 4.5.0 and later, and was previously named `referentialIntegrity`. | | `extensions` | No | List of strings (PostgreSQL extension names) | Allows you to [represent PostgreSQL extensions in your schema](/orm/prisma-schema/postgresql-extensions). Available in preview for PostgreSQL only in Prisma ORM versions 4.5.0 and later. | diff --git a/content/200-orm/500-reference/325-prisma-config-reference.mdx b/content/200-orm/500-reference/325-prisma-config-reference.mdx index c81cd8e241..713ec76d34 100644 --- a/content/200-orm/500-reference/325-prisma-config-reference.mdx +++ b/content/200-orm/500-reference/325-prisma-config-reference.mdx @@ -9,25 +9,25 @@ sidebar_label: "Prisma Config" The Prisma Config file configures the Prisma CLI, including subcommands like `migrate` and `studio`, using TypeScript. +:::info[Prisma ORM v7 changes] + +Starting with Prisma ORM v7, when you run `prisma init`, a `prisma.config.ts` file is automatically created. The database connection URL is now configured in this file instead of in the `schema.prisma` file. See [Using environment variables](#using-environment-variables) for setup details. + +::: + You can define your config in either of two ways: - Using the `defineConfig` helper: ```ts - import path from "node:path"; + import 'dotenv/config' import { defineConfig, env } from "prisma/config"; export default defineConfig({ - schema: path.join("prisma", "schema.prisma"), + schema: 'prisma/schema.prisma', migrations: { - path: path.join("db", "migrations"), - }, - views: { - path: path.join("db", "views"), - }, - typedSql: { - path: path.join("db", "queries"), + path: 'prisma/migrations', + seed: 'tsx prisma/seed.ts', }, - engine: "classic", datasource: { url: env("DATABASE_URL") } @@ -36,21 +36,16 @@ You can define your config in either of two ways: - Using TypeScript's `satisfies` operator with the `PrismaConfig` type: ```ts - import path from "node:path"; + import 'dotenv/config' import type { PrismaConfig } from "prisma"; + import { env } from "prisma/config"; export default { - schema: path.join("db", "schema.prisma"), + schema: "prisma/schema.prisma", migrations: { - path: path.join("db", "migrations"), + path: "prisma/migrations", + seed: 'tsx prisma/seed.ts', }, - views: { - path: path.join("db", "views"), - }, - typedSql: { - path: path.join("db", "queries"), - }, - engine: "classic", datasource: { url: env("DATABASE_URL") } @@ -66,22 +61,12 @@ export declare type PrismaConfig = { // Whether features with an unstable API are enabled. experimental: { - adapter: boolean; externalTables: boolean; - studio: boolean; }, // The path to the schema file, or path to a folder that shall be recursively searched for *.prisma files. schema?: string; - // The Driver Adapter used for Prisma CLI. - adapter?: () => Promise; - - // Configuration for Prisma Studio. - studio?: { - adapter: () => Promise; - }; - // Configuration for Prisma migrations. migrations?: { path: string; @@ -98,19 +83,29 @@ export declare type PrismaConfig = { typedSql?: { path: string; }; - // Depending on the choice, you must provide either a `datasource` object or driver adapter - engine: 'classic' | 'js' - // If using the classic engine, datasource sets the database url, shadowDatabaseUrl, or directURL + // Database connection configuration datasource?: { url: string; - directUrl?: string; shadowDatabaseUrl?: string; } }; ``` +:::note[Prisma ORM v6.19 and earlier] + +In Prisma ORM v6.19 and earlier, the configuration interface also included: +- `experimental.adapter` and `experimental.studio` flags +- `adapter` property for configuring driver adapters +- `studio` property for Prisma Studio configuration +- `datasource.directUrl` property for direct database connections +- `engine` property for choosing between `classic` and `js` engines + +These have been removed in Prisma ORM v7. See the individual property sections below for migration guidance. + +::: + ## Supported file extensions Prisma Config files can be named as `prisma.config.*` or `.config/prisma.*` with the extensions `js`, `ts`, `mjs`, `cjs`, `mts`, or `cts`. Other extensions are supported to ensure compatibility with different TypeScript compiler settings. @@ -133,80 +128,6 @@ Configures how Prisma ORM locates and loads your schema file(s). Can be a file o | -------- | -------- | -------- | ---------------------------------------------- | | `schema` | `string` | No | `./prisma/schema.prisma` and `./schema.prisma` | -### `adapter` - -A function that returns a Prisma driver adapter instance which is used by the Prisma CLI to run migrations. The function should return a `Promise` that resolves to a valid Prisma driver adapter. - -| Property | Type | Required | Default | -| ----------------- | -------------------------------------------------------------- | -------- | ------- | -| `adapter` | `() => Promise` | No | none | - -Example using the Prisma ORM D1 driver adapter: - -```ts -import path from "node:path"; -import type { PrismaConfig } from "prisma"; -import { PrismaD1 } from "@prisma/adapter-d1"; - -export default { - experimental: { - adapter: true - }, - schema: path.join("prisma", "schema.prisma"), - async adapter() { - return new PrismaD1({ - CLOUDFLARE_D1_TOKEN: process.env.CLOUDFLARE_D1_TOKEN, - CLOUDFLARE_ACCOUNT_ID: process.env.CLOUDFLARE_ACCOUNT_ID, - CLOUDFLARE_DATABASE_ID: process.env.CLOUDFLARE_DATABASE_ID, - }); - }, -} satisfies PrismaConfig; -``` - -:::note - -As of [Prisma ORM v6.11.0](https://github.com/prisma/prisma/releases/tag/6.11.0), the D1 adapter has been renamed from `PrismaD1HTTP` to `PrismaD1`. - -::: - -### `studio` - -Configures how Prisma Studio connects to your database. See sub-options below for details. - -| Property | Type | Required | Default | -| -------- | -------- | -------- | ------- | -| `studio` | `object` | No | none | - -#### `studio.adapter` - -A function that returns a Prisma driver adapter instance. The function receives an `env` parameter containing environment variables and should return a `Promise` that resolves to a valid Prisma driver adapter. - -| Property | Type | Required | Default | -| ----------------- | -------------------------------------------------------------- | -------- | ------- | -| `studio.adapter ` | `(env: Env) => Promise` | No | none | - -Example using the Prisma ORM LibSQL driver adapter: - -```ts -import type { PrismaConfig } from "prisma"; - -export default { - experimental: { - studio: true - }, - studio: { - adapter: async (env: Env) => { - const { PrismaLibSQL } = await import("@prisma/adapter-libsql"); - const { createClient } = await import("@libsql/client"); - - const libsql = createClient({ - url: env.DOTENV_PRISMA_STUDIO_LIBSQL_DATABASE_URL, - }); - return new PrismaLibSQL(libsql); - }, - }, -} satisfies PrismaConfig; -``` ### `tables.external` and `enums.external` @@ -220,9 +141,17 @@ These options declare tables and enums in your database that are **managed exter **Example:** ```ts -import { defineConfig } from "prisma/config"; +import 'dotenv/config' +import { defineConfig, env } from "prisma/config"; export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, experimental: { externalTables: true, }, @@ -256,11 +185,17 @@ This option allows you to define a script that Prisma runs to seed your database **Example:** ```ts -import { defineConfig } from "prisma/config"; +import 'dotenv/config' +import { defineConfig, env } from "prisma/config"; export default defineConfig({ + schema: 'prisma/schema.prisma', migrations: { - seed: `tsx db/seed.ts`, + path: 'prisma/migrations', + seed: 'tsx db/seed.ts', + }, + datasource: { + url: env('DATABASE_URL'), }, }); ``` @@ -276,20 +211,26 @@ This option allows you to define SQL statements that Prisma runs on the **shadow **Example:** ```ts -import { defineConfig } from "prisma/config"; +import 'dotenv/config' +import { defineConfig, env } from "prisma/config"; export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + initShadowDb: ` + CREATE TABLE public.users (id SERIAL PRIMARY KEY); + `, + }, + datasource: { + url: env('DATABASE_URL'), + }, experimental: { externalTables: true, }, tables: { external: ["public.users"], }, - migrations: { - initShadowDb: ` - CREATE TABLE public.users (id SERIAL PRIMARY KEY); - `, - }, }); ``` @@ -317,37 +258,178 @@ Enables specific experimental features in the Prisma CLI. | Property | Type | Required | Default | | ---------------- | --------- | -------- | ------- | -| `adapter` | `boolean` | No | `false` | | `externalTables` | `boolean` | No | `false` | -| `studio` | `boolean` | No | `false` | Example: ```ts -import { defineConfig } from "prisma/config"; +import 'dotenv/config' +import { defineConfig, env } from "prisma/config"; export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, experimental: { - adapter: true, externalTables: true, - studio: true, }, - schema: "prisma/schema.prisma", }); ``` :::note -If you use features like `adapter`, `studio` or `externalTables` without enabling the corresponding experimental flag, Prisma will throw an error: +If you use the `externalTables` feature without enabling the experimental flag, Prisma will throw an error: ```terminal -Failed to load config file "~" as a TypeScript/JavaScript module. Error: Error: The `studio` configuration requires `experimental.studio` to be set to `true`. +Failed to load config file "~" as a TypeScript/JavaScript module. Error: Error: The `externalTables` configuration requires `experimental.externalTables` to be set to `true`. +``` + +::: + +:::info[Prisma ORM v6.19 and earlier] + +In Prisma ORM v6.19 and earlier, the `experimental` object also included `adapter` and `studio` flags. These have been removed in Prisma ORM v7. See the [`adapter`](#adapter-removed) and [`studio`](#studio-removed) sections for details. + +::: + + +### `datasource.url` + +Connection URL including authentication info. Most connectors use [the syntax provided by the database](/orm/reference/connection-urls#format). + +:::info[Prisma ORM v7 changes] + +In Prisma ORM v7, the `url` field is configured in `prisma.config.ts` instead of in [the `datasource` block of your `schema.prisma`](/orm/prisma-schema/overview/data-sources) file. When you run `prisma init`, the generated `schema.prisma` file will not include a `url` property in the `datasource` block. + +For Prisma ORM v6.19 and earlier, the `url` field remains in the `schema.prisma` file's `datasource` block. + +::: + +| Property | Type | Required | Default | +| -------- | ------------------ | -------- | ----------------- | +| `datasource.url` | `string` | Yes | `''` | + +**Example:** + +```ts +import 'dotenv/config' +import { defineConfig, env } from "prisma/config"; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + + +### `datasource.shadowDatabaseUrl` + +Connection URL to the shadow database used by Prisma Migrate. Allows you to use a cloud-hosted database as the shadow database. + +:::info[Prisma ORM v7 changes] + +In Prisma ORM v7, the `shadowDatabaseUrl` field is configured in `prisma.config.ts` instead of in the `datasource` block of your `schema.prisma` file. + +For Prisma ORM v6.19 and earlier, the `shadowDatabaseUrl` field remains in the `schema.prisma` file's `datasource` block. + +::: + +| Property | Type | Required | Default | +| -------- | ------------------ | -------- | ----------------- | +| `datasource.shadowDatabaseUrl` | `string` | No | `''` | + + +### `datasource.directUrl` (Removed) + +:::warning[Removed in Prisma ORM v7] + +The `datasource.directUrl` property has been removed in Prisma ORM v7 in favor of the [`url` property](#datasourceurl). + +::: + +
+For Prisma ORM v6.19 and earlier + +Connection URL for direct connection to the database. + +If you use a connection pooler URL in the `url` argument (for example, pgBouncer), Prisma CLI commands that require a direct connection to the database use the URL in the `directUrl` argument. + +The `directUrl` property is supported by Prisma Studio from version 5.1.0 upwards. The `directUrl` property is not needed when using [Prisma Postgres](/postgres) database. + +| Property | Type | Required | Default | +| -------- | ------------------ | -------- | ----------------- | +| `datasource.directUrl` | `string` | No | `''` | + +
+ + +### `adapter` (Removed) + +:::warning[Removed in Prisma ORM v7] + +The `adapter` property has been removed in Prisma ORM v7. Migrations for driver adapters work automatically without additional configuration in `prisma.config.ts` as of Prisma ORM v7. + +::: + +
+For Prisma ORM v6.19 and earlier + +A function that returns a Prisma driver adapter instance which is used by the Prisma CLI to run migrations. The function should return a `Promise` that resolves to a valid Prisma driver adapter. + +| Property | Type | Required | Default | +| ----------------- | -------------------------------------------------------------- | -------- | ------- | +| `adapter` | `() => Promise` | No | none | + +Example using the Prisma ORM D1 driver adapter: + +```ts +import path from "node:path"; +import type { PrismaConfig } from "prisma"; +import { PrismaD1 } from "@prisma/adapter-d1"; + +export default { + experimental: { + adapter: true + }, + engine: "js", + schema: path.join("prisma", "schema.prisma"), + async adapter() { + return new PrismaD1({ + CLOUDFLARE_D1_TOKEN: process.env.CLOUDFLARE_D1_TOKEN, + CLOUDFLARE_ACCOUNT_ID: process.env.CLOUDFLARE_ACCOUNT_ID, + CLOUDFLARE_DATABASE_ID: process.env.CLOUDFLARE_DATABASE_ID, + }); + }, +} satisfies PrismaConfig; ``` +:::note + +As of [Prisma ORM v6.11.0](https://github.com/prisma/prisma/releases/tag/6.11.0), the D1 adapter has been renamed from `PrismaD1HTTP` to `PrismaD1`. + ::: +
+ +### `engine` (Removed) + +:::warning[Removed in Prisma ORM v7] + +The `engine` property has been removed in Prisma ORM v7. -### `engine` +::: + +
+For Prisma ORM v6.19 and earlier Configure the schema engine your project should use. @@ -355,8 +437,7 @@ Configure the schema engine your project should use. | -------- | ------------------ | -------- | ----------------- | | `engine` | `classic` or `js` | No | `classic` | - By default it is set to use the classic engine, which requires that `datasource` be set - in your `prisma.config.ts`. +By default it is set to use the classic engine, which requires that `datasource` be set in your `prisma.config.ts`. ```ts import path from "node:path"; @@ -370,48 +451,65 @@ export default defineConfig({ }); ``` -### `datasource.url` +
-Connection URL including authentication info. Most connectors use [the syntax provided by the database](/orm/reference/connection-urls#format). -:::note -Replaces the deprecated `url` field in the Prisma schema `datasource` block (Prisma ORM v7 and later). -::: +### `studio` (Removed) -| Property | Type | Required | Default | -| -------- | ------------------ | -------- | ----------------- | -| `datasource.url` | `string` | Yes | `''` | +:::warning[Removed in Prisma ORM v7] +The `studio` property has been removed in Prisma ORM v7. To run Prisma Studio, use: -### `datasource.shadowDatabaseUrl` +```terminal +npx prisma studio --config ./prisma.config.ts +``` -Connection URL to the shadow database used by Prisma Migrate. Allows you to use a cloud-hosted database as the shadow database +Prisma Studio now uses the connection configuration from the `datasource` property automatically. See the [Prisma Studio documentation](/orm/reference/prisma-cli-reference#studio) for more details. -:::note -Replaces the deprecated `shadowDatabaseUrl` field in the Prisma schema `datasource` block (Prisma ORM v7 and later). ::: -| Property | Type | Required | Default | -| -------- | ------------------ | -------- | ----------------- | -| `datasource.shadowDatabaseUrl` | `string` | No | `''` | +
+For Prisma ORM v6.19 and earlier +Configures how Prisma Studio connects to your database. See sub-options below for details. -### `datasource.directUrl` +| Property | Type | Required | Default | +| -------- | -------- | -------- | ------- | +| `studio` | `object` | No | none | -Connection URL for direct connection to the database. +#### `studio.adapter` (Removed) -:::note -Replaces the deprecated `directUrl` field in the Prisma schema `datasource` block (Prisma ORM v7 and later). -::: +A function that returns a Prisma driver adapter instance. The function receives an `env` parameter containing environment variables and should return a `Promise` that resolves to a valid Prisma driver adapter. -If you use a connection pooler URL in the `url` argument (for example, if you use [Prisma Accelerate](/accelerate) or pgBouncer), Prisma CLI commands that require a direct connection to the database use the URL in the `directUrl` argument.

The `directUrl` property is supported by Prisma Studio from version 5.1.0 upwards.

The `directUrl` property is not needed when using [Prisma Postgres](/postgres) database. +| Property | Type | Required | Default | +| ----------------- | -------------------------------------------------------------- | -------- | ------- | +| `studio.adapter ` | `(env: Env) => Promise` | No | none | -| Property | Type | Required | Default | -| -------- | ------------------ | -------- | ----------------- | -| `datasource.directUrl` | `string` | No | `''` | +Example using the Prisma ORM LibSQL driver adapter: +```ts +import type { PrismaConfig } from "prisma"; + +export default { + experimental: { + studio: true + }, + engine: "js", + studio: { + adapter: async (env: Env) => { + const { PrismaLibSQL } = await import("@prisma/adapter-libsql"); + const { createClient } = await import("@libsql/client"); + const libsql = createClient({ + url: env.DOTENV_PRISMA_STUDIO_LIBSQL_DATABASE_URL, + }); + return new PrismaLibSQL(libsql); + }, + }, +} satisfies PrismaConfig; +``` +
## Common patterns @@ -422,75 +520,108 @@ To get started with Prisma Config, create a `prisma.config.ts` file in your proj Using `defineConfig`: ```ts -import { defineConfig } from "prisma/config"; +import 'dotenv/config' +import { defineConfig, env } from "prisma/config"; -export default defineConfig({}); +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); ``` Using TypeScript types: ```ts +import 'dotenv/config' import type { PrismaConfig } from "prisma"; +import { env } from "prisma/config"; -export default {} satisfies PrismaConfig; +export default { + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +} satisfies PrismaConfig; ``` ### Using environment variables -When using `prisma.config.ts`, environment variables from `.env` files are not automatically loaded. Using `tsx`, you can pass a `--env-file` flag and that will automatically add those values to `process.env` +:::info[Prisma ORM v7 changes] + +In Prisma ORM v7, when you run `prisma init`, the generated `prisma.config.ts` file includes `import 'dotenv/config'` by default. You must install the `dotenv` package to use environment variables. + +::: + +When using `prisma.config.ts`, environment variables from `.env` files need to be loaded explicitly. There are several approaches depending on your runtime and Node version: -If using Node or Deno: +#### Using dotenv (Recommended for Prisma ORM v7) + +1. Install the `dotenv` package: ```terminal -tsx --env-file=.env src/index.ts -tsx watch --env-file=.env --env-file=.local.env src/index.ts -tsx --env-file=.env ./prisma/seed.ts +npm install dotenv ``` -For Bun, `.env` files are automatically loaded. +2. Import `dotenv/config` at the top of your `prisma.config.ts` file: -For accessing environment variables within `prisma.config.ts`, use the `env()` helper function to -provide a type-safe way of accessing that variable: - -```tsx -import path from "node:path"; +```ts +import 'dotenv/config' import { defineConfig, env } from "prisma/config"; -type Env = { - DATABASE_URL: string -} export default defineConfig({ - engine: "classic", + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + seed: 'tsx prisma/seed.ts', + }, datasource: { - url: env('DATABASE_URL'), + url: env('DATABASE_URL'), }, - schema: path.join("prisma", "schema.prisma"), }); ``` -For releases of Node before v20, you'll need to: +#### Using Node.js v20+ or tsx with --env-file flag -1. Install the `dotenv` package: +If using Node.js v20+ or `tsx`, you can pass a `--env-file` flag to automatically load environment variables: ```terminal -npm install dotenv +tsx --env-file=.env src/index.ts +tsx watch --env-file=.env --env-file=.local.env src/index.ts +tsx --env-file=.env ./prisma/seed.ts ``` -2. Import `dotenv/config` in your config file: +#### Using Bun + +For Bun, `.env` files are automatically loaded without additional configuration. + +#### Type-safe environment variables + +Use the `env()` helper function to provide type-safe access to environment variables: ```ts -import "dotenv/config"; +import 'dotenv/config' import { defineConfig, env } from "prisma/config"; type Env = { DATABASE_URL: string } + export default defineConfig({ - engine: "classic", + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, datasource: { - url: env('DATABASE_URL'), + url: env('DATABASE_URL'), }, - schema: path.join("prisma", "schema.prisma"), }); ``` @@ -611,12 +742,23 @@ prisma validate --config ./path/to/myconfig.ts ## Loading environment variables +:::info[Prisma ORM v7 changes] + + +In Prisma ORM v7, `prisma init` generates a `prisma.config.ts` file automatically. To load environment variables with `dotenv`, do the following: + +1. Install the `dotenv` package. +2. Add `import 'dotenv/config'` at the top of your `prisma.config.ts` file. + +This is required for Prisma to read values from your `.env` file. +::: + To load environment variables in your Prisma application, you can use the `prisma.config.ts` file along with the `env` helper from `prisma/config`. This approach provides better type safety and configuration management. -1. First, install the required dependency: +1. Install the `dotenv` package: ```bash - npm install dotenv --save-dev + npm install dotenv ``` 2. Create a `.env` file in your project root (if it doesn't exist) and add your database connection string: @@ -625,15 +767,23 @@ To load environment variables in your Prisma application, you can use the `prism DATABASE_URL="your_database_connection_string_here" ``` -3. Update your `prisma.config.ts` file in your project root: +3. Ensure your `prisma.config.ts` file imports `dotenv/config` at the top: - ```ts - import "dotenv/config"; + ```ts file=prisma.config.ts + // add-start + import 'dotenv/config' + // add-end import { defineConfig, env } from "prisma/config"; export default defineConfig({ - datasource: { - url: env("DATABASE_URL"), - }, + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + seed: 'tsx prisma/seed.ts', + }, + datasource: { + url: env("DATABASE_URL"), + }, }); - ``` \ No newline at end of file + ``` + diff --git a/content/800-guides/070-cloudflare-d1.mdx b/content/800-guides/070-cloudflare-d1.mdx index 7264a75355..5d8083a679 100644 --- a/content/800-guides/070-cloudflare-d1.mdx +++ b/content/800-guides/070-cloudflare-d1.mdx @@ -177,7 +177,7 @@ CLOUDFLARE_D1_TOKEN="F8Cg..." ### 5.2 Configure Prisma Config -Ensure that you have a `prisma.config.ts` file set up in the root of your project with a [driver adapter](/orm/reference/prisma-config-reference#adapter) defined. +Ensure that you have a `prisma.config.ts` file set up in the root of your project with a [driver adapter](/orm/reference/prisma-config-reference#adapter-removed) defined. ```ts import type { PrismaConfig } from 'prisma'; From c2671d724f4fb97d3c88f46c3594bce66dc2b010 Mon Sep 17 00:00:00 2001 From: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> Date: Sun, 16 Nov 2025 01:37:11 +0600 Subject: [PATCH 07/23] feat: restructure getting started side nav (#7245) * feat(docs): add youtube embeded link to blog post (#7220) Co-authored-by: Arthur Gamby * feat(docs): add quick section to blog after the prompt (#7221) Co-authored-by: Arthur Gamby * DC-5242 Astro Better-Auth Guide (#7215) * doc created * nextjs betterauth fixed * guide broken down into manageable steps * image added * Optimised images with calibre/image-actions * image updated * Optimised images with calibre/image-actions * lychee only comments on broken links * config updated * lychee updated based on CR comment * chore: trigger CI checks * ignore gnu * fix: update naming to better-auth DC-6120 * Optimised images with calibre/image-actions * chore: shorten word --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> * feat: restructure getting started side nav * DC-5841 Removed Linkspector (#7231) * removed linkspector * retrigger * retrigger * retrigger * Update label for Prisma Postgres tab (#7236) * fix: content changes for getting started page (#7216) * fix: content changes for getting started page * fix: add redirects * getting started checkpoint * css styles fixed * updates --------- Co-authored-by: Aidan McAlister Co-authored-by: Aidan McAlister <105178005+aidankmcalister@users.noreply.github.com> * DC-5820 AI Agents Served Markdown (#7237) * ai crawler check successful * ai crawlers checked * update * added anthropic * middleware update * improve detection --------- Co-authored-by: Mike Hartington * feat: add prisma-orm quickstarts * fix: update times and add proper links * fix: instropspect changes * feat: add get started from prisma orm page * feat: add other orms * fix: update other tools + ppg * fix: add more clarity * fix: add prisma postgres * feat: clear migrate from early access * fix: add to existing dbs sections * Remove MCP server exploration tip (#7241) Removed tip about using Cloudflare's AI Playground for MCP server exploration, as it no longer seems to reliably work. * fix: clean-up docs files * fix: typeorm missing urls * fix: broken link * fix: update titles * fix: clear redirect loop (#7250) * fix: add generate step + sqlite fixes * fix: clean-up redirects file DC-6228 * fix: clean-up unnecessary file * fix: remove unknown word * fix: add links --------- Co-authored-by: Arthur Co-authored-by: Arthur Gamby Co-authored-by: Aidan McAlister <105178005+aidankmcalister@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Petra Donka Co-authored-by: Aidan McAlister Co-authored-by: Mike Hartington --- .github/workflows/config/.linkspector.yml | 19 - .github/workflows/linkspector.yml | 18 - .github/workflows/lychee.yml | 4 +- cSpell.json | 5 +- .../01-quickstart-prismaPostgres.mdx | 159 --- .../01-quickstart-sqlite.mdx | 465 --------- .../100-quickstart/100-prisma-postgres.mdx | 276 ++++++ .../100-quickstart/200-sqlite.mdx | 278 ++++++ .../100-quickstart/300-postgresql.mdx | 292 ++++++ .../100-quickstart/400-mysql.mdx | 300 ++++++ .../100-quickstart/500-sql-server.mdx | 309 ++++++ .../100-quickstart/600-planetscale.mdx | 311 ++++++ .../100-quickstart/700-cockroachdb.mdx | 282 ++++++ .../100-quickstart/800-mongodb.mdx | 302 ++++++ .../100-prisma-postgres.mdx | 257 +++++ .../200-sqlite.mdx | 261 +++++ .../300-postgresql.mdx | 261 +++++ .../200-add-to-existing-project/400-mysql.mdx | 272 +++++ .../500-sql-server.mdx | 282 ++++++ .../600-planetscale.mdx | 249 +++++ .../700-cockroachdb.mdx | 261 +++++ .../800-mongodb.mdx | 308 ++++++ ...-relational-databases-node-cockroachdb.mdx | 52 - .../110-relational-databases-node-mysql.mdx | 58 -- ...-relational-databases-node-planetscale.mdx | 51 - ...0-relational-databases-node-postgresql.mdx | 58 -- ...10-relational-databases-node-sqlserver.mdx | 61 -- ...ional-databases-typescript-cockroachdb.mdx | 64 -- ...-relational-databases-typescript-mysql.mdx | 64 -- ...ional-databases-typescript-planetscale.mdx | 70 -- ...tional-databases-typescript-postgresql.mdx | 59 -- ...al-databases-typescript-prismaPostgres.mdx | 70 -- ...ational-databases-typescript-sqlserver.mdx | 66 -- ...connect-your-database-node-cockroachdb.mdx | 54 - .../100-connect-your-database-node-mysql.mdx | 61 -- ...connect-your-database-node-planetscale.mdx | 89 -- ...-connect-your-database-node-postgresql.mdx | 65 -- ...0-connect-your-database-node-sqlserver.mdx | 40 - ...t-your-database-typescript-cockroachdb.mdx | 54 - ...connect-your-database-typescript-mysql.mdx | 61 -- ...t-your-database-typescript-planetscale.mdx | 89 -- ...ct-your-database-typescript-postgresql.mdx | 64 -- ...our-database-typescript-prismaPostgres.mdx | 50 - ...ect-your-database-typescript-sqlserver.mdx | 41 - ...-using-prisma-migrate-node-cockroachdb.mdx | 62 -- .../150-using-prisma-migrate-node-mysql.mdx | 61 -- ...-using-prisma-migrate-node-planetscale.mdx | 59 -- ...0-using-prisma-migrate-node-postgresql.mdx | 62 -- ...50-using-prisma-migrate-node-sqlserver.mdx | 60 -- ...-prisma-migrate-typescript-cockroachdb.mdx | 62 -- ...-using-prisma-migrate-typescript-mysql.mdx | 60 -- ...-prisma-migrate-typescript-planetscale.mdx | 59 -- ...g-prisma-migrate-typescript-postgresql.mdx | 61 -- ...isma-migrate-typescript-prismaPostgres.mdx | 83 -- ...ng-prisma-migrate-typescript-sqlserver.mdx | 60 -- ...install-prisma-client-node-cockroachdb.mdx | 17 - .../200-install-prisma-client-node-mysql.mdx | 17 - ...install-prisma-client-node-planetscale.mdx | 17 - ...-install-prisma-client-node-postgresql.mdx | 17 - ...0-install-prisma-client-node-sqlserver.mdx | 17 - ...l-prisma-client-typescript-cockroachdb.mdx | 17 - ...install-prisma-client-typescript-mysql.mdx | 17 - ...l-prisma-client-typescript-planetscale.mdx | 17 - ...ll-prisma-client-typescript-postgresql.mdx | 32 - ...risma-client-typescript-prismaPostgres.mdx | 28 - ...all-prisma-client-typescript-sqlserver.mdx | 17 - ...querying-the-database-node-cockroachdb.mdx | 205 ---- .../250-querying-the-database-node-mysql.mdx | 205 ---- ...querying-the-database-node-planetscale.mdx | 206 ---- ...-querying-the-database-node-postgresql.mdx | 206 ---- ...0-querying-the-database-node-sqlserver.mdx | 205 ---- ...ng-the-database-typescript-cockroachdb.mdx | 220 ----- ...querying-the-database-typescript-mysql.mdx | 220 ----- ...ng-the-database-typescript-planetscale.mdx | 221 ----- ...ing-the-database-typescript-postgresql.mdx | 219 ----- ...the-database-typescript-prismaPostgres.mdx | 243 ----- ...ying-the-database-typescript-sqlserver.mdx | 222 ----- .../300-next-steps.mdx | 100 -- .../_install-prisma-client-partial.mdx | 25 - .../120-mongodb-node-mongodb.mdx | 54 - .../120-mongodb-typescript-mongodb.mdx | 59 -- ...100-connect-your-database-node-mongodb.mdx | 55 -- ...nnect-your-database-typescript-mongodb.mdx | 53 - ...reating-the-prisma-schema-node-mongodb.mdx | 68 -- ...g-the-prisma-schema-typescript-mongodb.mdx | 67 -- ...200-install-prisma-client-node-mongodb.mdx | 31 - ...stall-prisma-client-typescript-mongodb.mdx | 30 - ...250-querying-the-database-node-mongodb.mdx | 217 ---- ...erying-the-database-typescript-mongodb.mdx | 230 ----- .../120-mongodb/300-next-steps.mdx | 94 -- .../_prisma-init-partial.mdx | 27 - .../100-start-from-scratch/index.mdx | 16 - ...-relational-databases-node-cockroachdb.mdx | 57 -- .../110-relational-databases-node-mysql.mdx | 58 -- ...-relational-databases-node-planetscale.mdx | 57 -- ...0-relational-databases-node-postgresql.mdx | 58 -- ...10-relational-databases-node-sqlserver.mdx | 58 -- ...ional-databases-typescript-cockroachdb.mdx | 58 -- ...-relational-databases-typescript-mysql.mdx | 47 - ...ional-databases-typescript-planetscale.mdx | 57 -- ...tional-databases-typescript-postgresql.mdx | 57 -- ...ational-databases-typescript-sqlserver.mdx | 58 -- ...connect-your-database-node-cockroachdb.mdx | 59 -- .../100-connect-your-database-node-mysql.mdx | 60 -- ...connect-your-database-node-planetscale.mdx | 89 -- ...-connect-your-database-node-postgresql.mdx | 57 -- ...0-connect-your-database-node-sqlserver.mdx | 35 - ...t-your-database-typescript-cockroachdb.mdx | 59 -- ...connect-your-database-typescript-mysql.mdx | 60 -- ...t-your-database-typescript-planetscale.mdx | 86 -- ...ct-your-database-typescript-postgresql.mdx | 56 -- ...ect-your-database-typescript-sqlserver.mdx | 35 - .../150-introspection-node-cockroachdb.mdx | 217 ---- .../150-introspection-node-mysql.mdx | 220 ----- .../150-introspection-node-planetscale.mdx | 237 ----- .../150-introspection-node-postgresql.mdx | 218 ---- .../150-introspection-node-sqlserver.mdx | 225 ----- ...0-introspection-typescript-cockroachdb.mdx | 218 ---- .../150-introspection-typescript-mysql.mdx | 221 ----- ...0-introspection-typescript-planetscale.mdx | 237 ----- ...50-introspection-typescript-postgresql.mdx | 217 ---- ...150-introspection-typescript-sqlserver.mdx | 225 ----- ...aseline-your-database-node-cockroachdb.mdx | 85 -- .../170-baseline-your-database-node-mysql.mdx | 101 -- ...baseline-your-database-node-postgresql.mdx | 104 -- ...-baseline-your-database-node-sqlserver.mdx | 93 -- ...e-your-database-typescript-cockroachdb.mdx | 74 -- ...aseline-your-database-typescript-mysql.mdx | 102 -- ...ne-your-database-typescript-postgresql.mdx | 103 -- ...ine-your-database-typescript-sqlserver.mdx | 93 -- ...install-prisma-client-node-cockroachdb.mdx | 17 - .../200-install-prisma-client-node-mysql.mdx | 17 - ...install-prisma-client-node-planetscale.mdx | 17 - ...-install-prisma-client-node-postgresql.mdx | 17 - ...0-install-prisma-client-node-sqlserver.mdx | 17 - ...l-prisma-client-typescript-cockroachdb.mdx | 17 - ...install-prisma-client-typescript-mysql.mdx | 17 - ...l-prisma-client-typescript-planetscale.mdx | 17 - ...ll-prisma-client-typescript-postgresql.mdx | 16 - ...all-prisma-client-typescript-sqlserver.mdx | 17 - ...querying-the-database-node-cockroachdb.mdx | 123 --- .../250-querying-the-database-node-mysql.mdx | 125 --- ...querying-the-database-node-planetscale.mdx | 137 --- ...-querying-the-database-node-postgresql.mdx | 124 --- ...0-querying-the-database-node-sqlserver.mdx | 132 --- ...ng-the-database-typescript-cockroachdb.mdx | 139 --- ...querying-the-database-typescript-mysql.mdx | 138 --- ...ng-the-database-typescript-planetscale.mdx | 139 --- ...ing-the-database-typescript-postgresql.mdx | 137 --- ...ying-the-database-typescript-sqlserver.mdx | 138 --- ...75-evolve-your-schema-node-cockroachdb.mdx | 106 -- .../275-evolve-your-schema-node-mysql.mdx | 108 -- ...275-evolve-your-schema-node-postgresql.mdx | 107 -- .../275-evolve-your-schema-node-sqlserver.mdx | 108 -- ...lve-your-schema-typescript-cockroachdb.mdx | 109 -- ...75-evolve-your-schema-typescript-mysql.mdx | 108 -- ...olve-your-schema-typescript-postgresql.mdx | 109 -- ...volve-your-schema-typescript-sqlserver.mdx | 108 -- .../300-next-steps.mdx | 112 --- .../_install-prisma-client-partial.mdx | 25 - .../120-mongodb-node-mongodb.mdx | 58 -- .../120-mongodb-typescript-mongodb.mdx | 59 -- ...100-connect-your-database-node-mongodb.mdx | 57 -- ...nnect-your-database-typescript-mongodb.mdx | 55 -- .../125-introspection-node-mongodb.mdx | 130 --- .../125-introspection-typescript-mongodb.mdx | 129 --- ...200-install-prisma-client-node-mongodb.mdx | 28 - ...stall-prisma-client-typescript-mongodb.mdx | 26 - ...250-querying-the-database-node-mongodb.mdx | 220 ----- ...erying-the-database-typescript-mongodb.mdx | 234 ----- .../120-mongodb/300-next-steps.mdx | 94 -- .../_prisma-init-partial.mdx | 33 - .../200-add-to-existing-project/index.mdx | 16 - .../02-setup-prisma/index.mdx | 13 - .../03-prisma-postgres/100-from-the-cli.mdx | 150 ++- .../100-quickstart/100-kysely.mdx | 151 +++ .../100-quickstart/200-drizzle-orm.mdx | 193 ++++ .../100-quickstart/300-typeorm.mdx | 185 ++++ .../100-quickstart/50-prisma-orm.mdx | 301 ++++++ ...port-from-existing-database-postgresql.mdx | 134 +-- ...15-import-from-existing-database-mysql.mdx | 30 +- .../120-upgrade-from-early-access.mdx | 257 ----- .../_components/_create-prisma-client.mdx | 181 ++++ .../_components/_create-project.mdx | 14 + .../_components/_explore-data.mdx | 7 + .../_components/_install-prisma-client.mdx | 83 ++ .../_components/_next-steps.mdx | 7 + .../_components/_prerequisites.mdx | 11 + .../_components/_prisma-init.mdx | 67 ++ content/100-getting-started/index.mdx | 244 ++--- .../025-getting-started/10-quickstart.mdx | 11 + .../20-add-to-existing-project.mdx | 11 + .../025-getting-started/_category_.json | 5 + content/200-orm/025-getting-started/index.mdx | 13 + .../500-databases/600-mongodb.mdx | 6 +- .../500-databases/840-cockroachdb.mdx | 4 +- .../500-databases/850-planetscale.mdx | 8 +- .../100-prisma-schema/50-introspection.mdx | 2 +- .../005-introduction.mdx | 9 +- .../101-traditional/200-deploy-to-heroku.mdx | 2 +- .../101-traditional/250-deploy-to-koyeb.mdx | 2 +- .../20-prototyping-your-schema.mdx | 2 +- .../500-reference/380-connection-urls.mdx | 2 +- .../800-more/100-under-the-hood/index.mdx | 2 +- .../600-upgrading-to-prisma-5/index.mdx | 6 +- .../100-introduction/220-npx-create-db.mdx | 2 +- .../300-database/650-direct-connections.mdx | 8 +- .../350-integrations/400-mcp-server.mdx | 5 - .../400-query-optimization/100-setup.mdx | 2 +- .../50-getting-started/100-quickstart.mdx | 11 + .../200-import-from-existing-database.mdx | 11 + .../50-getting-started/_category_.json | 5 + .../index.mdx} | 21 +- .../140-use-prisma-in-pnpm-workspaces.mdx | 8 +- content/800-guides/230-betterauth-nextjs.mdx | 78 +- .../800-guides/380-vercel-app-deployment.mdx | 2 +- content/800-guides/400-betterauth-astro.mdx | 930 ++++++++++++++++++ content/900-ai/prompts/astro.mdx | 26 + content/900-ai/prompts/nextjs.mdx | 16 + docusaurus.config.ts | 24 +- functions/_middleware.ts | 113 +++ functions/types.d.ts | 12 + package-lock.json | 235 +++++ package.json | 3 +- sidebars.ts | 399 ++++---- src/components/GettingStarted/index.tsx | 47 + src/css/custom.css | 20 + src/css/gettingStarted.module.scss | 90 +- src/data/indexData.ts | 16 +- src/pages/index.tsx | 34 +- static/_redirects | 337 +++++-- .../guides/prisma-betterauth-astro-cover.png | Bin 0 -> 42323 bytes static/img/technologies/astro.svg | 4 + static/img/technologies/astrodark.svg | 11 + static/img/technologies/drizzle.svg | 6 + static/img/technologies/kysely.svg | 17 + static/img/technologies/remix.svg | 11 + static/img/technologies/sequelize.svg | 36 + static/img/technologies/typeorm.svg | 4 + 239 files changed, 8187 insertions(+), 15173 deletions(-) delete mode 100644 .github/workflows/config/.linkspector.yml delete mode 100644 .github/workflows/linkspector.yml delete mode 100644 content/100-getting-started/01-quickstart-prismaPostgres.mdx delete mode 100644 content/100-getting-started/01-quickstart-sqlite.mdx create mode 100644 content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx create mode 100644 content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx create mode 100644 content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx create mode 100644 content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx create mode 100644 content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx create mode 100644 content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx create mode 100644 content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx create mode 100644 content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx create mode 100644 content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx create mode 100644 content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx create mode 100644 content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx create mode 100644 content/100-getting-started/02-prisma-orm/200-add-to-existing-project/400-mysql.mdx create mode 100644 content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx create mode 100644 content/100-getting-started/02-prisma-orm/200-add-to-existing-project/600-planetscale.mdx create mode 100644 content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx create mode 100644 content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-prismaPostgres.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-prismaPostgres.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-prismaPostgres.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-prismaPostgres.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-prismaPostgres.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/300-next-steps.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/_install-prisma-client-partial.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/100-connect-your-database-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/100-connect-your-database-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/125-creating-the-prisma-schema-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/125-creating-the-prisma-schema-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/200-install-prisma-client-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/200-install-prisma-client-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/250-querying-the-database-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/250-querying-the-database-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/300-next-steps.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/_prisma-init-partial.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/100-start-from-scratch/index.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-planetscale.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-cockroachdb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-mysql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-postgresql.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-sqlserver.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/300-next-steps.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/_install-prisma-client-partial.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/100-connect-your-database-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/100-connect-your-database-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/125-introspection-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/125-introspection-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/200-install-prisma-client-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/200-install-prisma-client-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/250-querying-the-database-node-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/250-querying-the-database-typescript-mongodb.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/300-next-steps.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/_prisma-init-partial.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/200-add-to-existing-project/index.mdx delete mode 100644 content/100-getting-started/02-setup-prisma/index.mdx create mode 100644 content/100-getting-started/03-prisma-postgres/100-quickstart/100-kysely.mdx create mode 100644 content/100-getting-started/03-prisma-postgres/100-quickstart/200-drizzle-orm.mdx create mode 100644 content/100-getting-started/03-prisma-postgres/100-quickstart/300-typeorm.mdx create mode 100644 content/100-getting-started/03-prisma-postgres/100-quickstart/50-prisma-orm.mdx delete mode 100644 content/100-getting-started/03-prisma-postgres/120-upgrade-from-early-access.mdx create mode 100644 content/100-getting-started/_components/_create-prisma-client.mdx create mode 100644 content/100-getting-started/_components/_create-project.mdx create mode 100644 content/100-getting-started/_components/_explore-data.mdx create mode 100644 content/100-getting-started/_components/_install-prisma-client.mdx create mode 100644 content/100-getting-started/_components/_next-steps.mdx create mode 100644 content/100-getting-started/_components/_prerequisites.mdx create mode 100644 content/100-getting-started/_components/_prisma-init.mdx create mode 100644 content/200-orm/025-getting-started/10-quickstart.mdx create mode 100644 content/200-orm/025-getting-started/20-add-to-existing-project.mdx create mode 100644 content/200-orm/025-getting-started/_category_.json create mode 100644 content/200-orm/025-getting-started/index.mdx create mode 100644 content/250-postgres/50-getting-started/100-quickstart.mdx create mode 100644 content/250-postgres/50-getting-started/200-import-from-existing-database.mdx create mode 100644 content/250-postgres/50-getting-started/_category_.json rename content/250-postgres/{100-introduction/200-getting-started.mdx => 50-getting-started/index.mdx} (86%) create mode 100644 content/800-guides/400-betterauth-astro.mdx create mode 100644 functions/_middleware.ts create mode 100644 functions/types.d.ts create mode 100644 static/img/guides/prisma-betterauth-astro-cover.png create mode 100644 static/img/technologies/astro.svg create mode 100644 static/img/technologies/astrodark.svg create mode 100644 static/img/technologies/drizzle.svg create mode 100644 static/img/technologies/kysely.svg create mode 100644 static/img/technologies/remix.svg create mode 100644 static/img/technologies/sequelize.svg create mode 100644 static/img/technologies/typeorm.svg diff --git a/.github/workflows/config/.linkspector.yml b/.github/workflows/config/.linkspector.yml deleted file mode 100644 index 0d06293a36..0000000000 --- a/.github/workflows/config/.linkspector.yml +++ /dev/null @@ -1,19 +0,0 @@ -dirs: - - content -useGitIgnore: true -ignorePatterns: - - pattern: "^/.*" # local links are not checked - - pattern: "^http://localhost.*" # Localhost links are not checked - - pattern: "^https://packagecontrol.*" # Package control links are not checked (it was 500ing at time of writing) - - pattern: "^https://(www|dash).cloudflare.com.*" # Cloudflare links return 403 at time of writing - -fileExtensions: - - mdx - - md -modifiedFilesOnly: false -aliveStatusCodes: - - 200 - - 201 - - 204 - - 304 - - 403 diff --git a/.github/workflows/linkspector.yml b/.github/workflows/linkspector.yml deleted file mode 100644 index e428cf19b6..0000000000 --- a/.github/workflows/linkspector.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Linkspector -on: [pull_request] -jobs: - check-links: - name: runner / linkspector - runs-on: ubuntu-22.04 - permissions: - contents: write - steps: - - uses: actions/checkout@v4 - - name: Run linkspector - uses: umbrelladocs/action-linkspector@v1.3.7 - with: - github_token: ${{ secrets.github_token }} - reporter: github-pr-check - fail_on_error: true - filter_mode: nofilter - config_file: .github/workflows/config/.linkspector.yml \ No newline at end of file diff --git a/.github/workflows/lychee.yml b/.github/workflows/lychee.yml index 0b705f533c..4664852761 100644 --- a/.github/workflows/lychee.yml +++ b/.github/workflows/lychee.yml @@ -33,6 +33,7 @@ jobs: --exclude 'http://localhost.*' --exclude 'https://localhost.*' --exclude 'https://cockroachlabs.com' + --exclude 'https://www.gnu.org' --exclude '^/.*' './**/*.md' './**/*.mdx' workingDirectory: "content" @@ -58,6 +59,7 @@ jobs: --exclude 'http://localhost.*' --exclude 'https://localhost.*' --exclude 'https://cockroachlabs.com' + --exclude 'https://www.gnu.org' --exclude '^/.*' './**/*.md' './**/*.mdx' workingDirectory: "content" @@ -95,7 +97,7 @@ jobs: fi - name: 📝 Comment Broken Links - if: ${{ always() && github.event.pull_request.head.repo.fork == false }} + if: ${{ always() && github.event.pull_request.head.repo.fork == false && (steps.lychee.outputs.exit_code != 0 || (steps.lychee-retry.conclusion != 'skipped' && steps.lychee-retry.outputs.exit_code != 0)) }} uses: peter-evans/create-or-update-comment@v4 with: issue-number: ${{ github.event.pull_request.number }} diff --git a/cSpell.json b/cSpell.json index 5a422bc426..f3040ad1de 100644 --- a/cSpell.json +++ b/cSpell.json @@ -158,7 +158,8 @@ "Buildpacks", "Sevalla's", "Dataguide", - "justinellingwood" + "justinellingwood", + "Millis" ], "patterns": [ { @@ -212,4 +213,4 @@ "HTML Tags" ], "ignorePaths": [] -} \ No newline at end of file +} diff --git a/content/100-getting-started/01-quickstart-prismaPostgres.mdx b/content/100-getting-started/01-quickstart-prismaPostgres.mdx deleted file mode 100644 index 404c632267..0000000000 --- a/content/100-getting-started/01-quickstart-prismaPostgres.mdx +++ /dev/null @@ -1,159 +0,0 @@ ---- -title: 'Quickstart with Prisma Postgres' -sidebar_label: 'Quickstart' -metaTitle: 'Quickstart with TypeScript & Prisma Postgres' -metaDescription: 'Get started with Prisma ORM in 5 minutes. You will learn how to run migrations and send queries with a Prisma Postgres database.' -search: true -sidebar_class_name: hidden-sidebar -dbSwitcher: ['prismaPostgres', 'sqlite'] -slugSwitch: /getting-started/quickstart- -sidebar_custom_props: { badge: '5 min' } -community_section: true ---- - -In this Quickstart guide, you'll learn how to get started from scratch with Prisma ORM and a **Prisma Postgres** database in a plain **TypeScript** project. It covers the following workflows: - -- Creating a [Prisma Postgres](https://www.prisma.io/postgres?utm_source=docs) database -- Schema migrations and queries (via [Prisma ORM](https://www.prisma.io/orm)) -- Connection pooling and caching (via [Prisma Accelerate](https://www.prisma.io/accelerate)) - -:::note - -If you want to use Prisma Postgres with another ORM or database library (like Drizzle ORM, TypeORM or Kysely), you can follow the instructions [here](/postgres/introduction/getting-started#connect-via-any-database-library--tool). - -::: - -## Prerequisites - -To successfully complete this tutorial, you need: -- a [Prisma Data Platform](https://console.prisma.io/) (PDP) account -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - -## 1. Set up a Prisma Postgres database in the Platform Console - -Follow these steps to create your Prisma Postgres database: - -1. Log in to [Prisma Data Platform](https://console.prisma.io/) and open the Console. -1. In a [workspace](/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 for a few seconds while the status of your database changes from **`PROVISIONING`** to **`CONNECTED`**. - -Once the green **`CONNECTED`** label appears, your database is ready to use! - -## 2. Download example and install dependencies - -Copy the `try-prisma` command that's shown in the Console, paste it into your terminal and execute it. - -For reference, this is what the command looks like: - -```terminal -npx try-prisma@latest \ - --template databases/prisma-postgres \ - --name hello-prisma \ - --install npm -``` - -Once the `try-prisma` command has terminated, navigate into the project directory: - -```terminal -cd hello-prisma -``` - -## 3. Set database connection URL - -The connection to your database is configured via an environment variable in a `.env` file. - -First, rename the existing `.env.example` file to just `.env`: - -```terminal -mv .env.example .env -``` - -Then, in your project environment in the Platform console, 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 no-copy -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](/orm/prisma-schema/) 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`](https://github.com/prisma/prisma-examples/blob/latest/databases/prisma-postgres/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`](https://github.com/prisma/prisma-examples/blob/latest/databases/prisma-postgres/src/caching.ts) script contains a sample query that uses [Stale-While-Revalidate](/postgres/database/caching#stale-while-revalidate-swr) (SWR) and [Time-To-Live](/postgres/database/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.: - -```no-copy -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.: - -```no-copy -The query took 300.5655280000001ms. -``` - -## 7. Next steps - -In this Quickstart guide, you have learned how to get started with Prisma ORM in a plain TypeScript project. Feel free to explore the Prisma Client API a bit more on your own, e.g. by including filtering, sorting, and pagination options in the `findMany` query or exploring more operations like `update` and `delete` queries. - -### Explore the data in Prisma Studio - -Prisma ORM comes with a built-in GUI to view and edit the data in your database. You can open it using the following command: - -```terminal -npx prisma studio -``` - -With Prisma Postgres, you can also directly use Prisma Studio inside the [Console](https://console.prisma.io) by selecting the **Studio** tab in your project. - -### Build a fullstack app with Next.js - -Learn how to use Prisma Postgres in a fullstack app: - -- [Build a fullstack app with Next.js 15](/guides/nextjs) -- [Next.js 15 example app](https://github.com/prisma/nextjs-prisma-postgres-demo) (including authentication) - -### Explore ready-to-run Prisma ORM examples - -Check out the [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository on GitHub to see how Prisma ORM can be used with your favorite library. The repo contains examples with Express, NestJS, GraphQL as well as fullstack examples with Next.js and Vue.js, and a lot more. - -These examples use SQLite by default but you can follow the instructions in the project README to switch to Prisma Postgres in a few simple steps. \ No newline at end of file diff --git a/content/100-getting-started/01-quickstart-sqlite.mdx b/content/100-getting-started/01-quickstart-sqlite.mdx deleted file mode 100644 index 79feb9783b..0000000000 --- a/content/100-getting-started/01-quickstart-sqlite.mdx +++ /dev/null @@ -1,465 +0,0 @@ ---- -title: 'Quickstart with SQLite' -sidebar_label: 'Quickstart' -metaTitle: 'Quickstart with TypeScript & SQLite' -metaDescription: 'Get started with Prisma ORM in 5 minutes. You will learn how to send queries to a SQLite database in a plain TypeScript script using Prisma Client.' -search: true -sidebar_class_name: hidden-sidebar -dbSwitcher: ['prismaPostgres', 'sqlite'] -slugSwitch: /getting-started/quickstart- -sidebar_custom_props: { badge: '5 min' } -community_section: true ---- - -In this Quickstart guide, you'll learn how to get started with Prisma ORM from scratch using a plain **TypeScript** project and a local **SQLite** database file. It covers **data modeling**, **migrations** and **querying** a database. - -If you want to use Prisma ORM with your own PostgreSQL, MySQL, MongoDB or any other supported database, go here instead: - -- [Start with Prisma ORM from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql) -- [Add Prisma ORM to an existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql) - -## Prerequisites - -You need [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions). - -## 1. Create TypeScript project and set up Prisma ORM - -As a first step, create a project directory and navigate into it: - -```terminal -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a TypeScript project using npm: - -```terminal -npm init -y -npm install typescript tsx @types/node --save-dev -``` - -This creates a `package.json` with an initial setup for your TypeScript app. - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -Now, initialize TypeScript: - -```terminal -npx tsc --init -``` - -Then, install the Prisma CLI as a development dependency in the project: - -```terminal -npm install prisma --save-dev -``` - -Finally, set up Prisma ORM with the `init` command of the Prisma CLI: - -```terminal -npx prisma init --datasource-provider sqlite --output ../generated/prisma -``` - -This creates a new `prisma` directory with a `schema.prisma` file and configures SQLite as your database. You're now ready to model your data and create your database with some tables. - -## 2. Model your data in the Prisma schema - -The Prisma schema provides an intuitive way to model data. Add the following models to your `schema.prisma` file: - -```prisma file=prisma/schema.prisma showLineNumbers -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 -} -``` - -Models in the Prisma schema have two main purposes: - -- Represent the tables in the underlying database -- Serve as foundation for the generated Prisma Client API - -In the next section, you will map these models to database tables using Prisma Migrate. - -## 3. Run a migration to create your database tables with Prisma Migrate - -At this point, you have a Prisma schema but no database yet. Run the following command in your terminal to create the SQLite database and the `User` and `Post` tables represented by your models: - -```terminal -npx prisma migrate dev --name init -``` - -This command did three things: - -1. It created a new SQL migration file for this migration in the `prisma/migrations` directory. -2. It executed the SQL migration file against the database. -3. It ran `prisma generate` under the hood (which installed the `@prisma/client` package and generated a tailored Prisma Client API based on your models). - -Because the SQLite database file didn't exist before, the command also created it inside the `prisma` directory with the name `dev.db` as defined via the environment variable in the `.env` file. - -Congratulations, you now have your database and tables ready. Let's go and learn how you can send some queries to read and write data! - -## 4. Explore how to send queries to your database with Prisma Client - -To get started with Prisma Client, you need to install the `@prisma/client` package: - -```terminal copy -npm install @prisma/client -``` - -The install command invokes `prisma generate` for you which reads your Prisma schema and generates a version of Prisma Client that is _tailored_ to your models. - -To send queries to the database, you will need a TypeScript file to execute your Prisma Client queries. Create a new file called `script.ts` for this purpose: - -```terminal -touch script.ts -``` - -Then, paste the following boilerplate into it: - -```ts file=script.ts showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -This code contains a `main` function that's invoked at the end of the script. It also instantiates `PrismaClient` which represents the query interface to your database. - -### 4.1. Create a new `User` record - -Let's start with a small query to create a new `User` record in the database and log the resulting object to the console. Add the following code to your `script.ts` file: - -```ts file=script.ts highlight=6-12;add showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // add-start - const user = await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - }, - }) - console.log(user) - // add-end -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Instead of copying the code, you can type it out in your editor to experience the autocompletion Prisma Client provides. You can also actively invoke the autocompletion by pressing the CTRL+SPACE keys on your keyboard. - -Next, execute the script with the following command: - - - - - -```terminal -npx tsx script.ts -``` - - - - -```code no-copy -{ id: 1, email: 'alice@prisma.io', name: 'Alice' } -``` - - - - - -Great job, you just created your first database record with Prisma Client! 🎉 - -In the next section, you'll learn how to read data from the database. - -### 4.2. Retrieve all `User` records - -Prisma Client offers various queries to read data from your database. In this section, you'll use the `findMany` query that returns _all_ the records in the database for a given model. - -Delete the previous Prisma Client query and add the new `findMany` query instead: - -```ts file=script.ts highlight=6-7;add showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // add-start - const users = await prisma.user.findMany() - console.log(users) - // add-end -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Execute the script again: - - - - - -```terminal -npx tsx script.ts -``` - - - - - -```code no-copy -[{ id: 1, email: 'alice@prisma.io', name: 'Alice' }] -``` - - - - - -Notice how the single `User` object is now enclosed with square brackets in the console. That's because the `findMany` returned an array with a single object inside. - -### 4.3. Explore relation queries with Prisma Client - -One of the main features of Prisma Client is the ease of working with [relations](/orm/prisma-schema/data-model/relations). In this section, you'll learn how to create a `User` and a `Post` record in a nested write query. Afterwards, you'll see how you can retrieve the relation from the database using the `include` option. - -First, adjust your script to include the nested query: - -```ts file=script.ts highlight=6-24;add showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // add-start - const user = await prisma.user.create({ - data: { - name: 'Bob', - email: 'bob@prisma.io', - posts: { - create: [ - { - title: 'Hello World', - published: true - }, - { - title: 'My second post', - content: 'This is still a draft' - } - ], - }, - }, - }) - console.log(user) - // add-end -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Run the query by executing the script again: - - - - - -```terminal -npx tsx script.ts -``` - - - - - -```code no-copy -{ id: 2, email: 'bob@prisma.io', name: 'Bob' } -``` - - - - - -By default, Prisma Client only returns _scalar_ fields in the result objects of a query. That's why, even though you also created a new `Post` record for the new `User` record, the console only printed an object with three scalar fields: `id`, `email` and `name`. - -In order to also retrieve the `Post` records that belong to a `User`, you can use the `include` option via the `posts` relation field: - -```ts file=script.ts highlight=6-11;add showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { -// add-start - const usersWithPosts = await prisma.user.findMany({ - include: { - posts: true, - }, - }) - console.dir(usersWithPosts, { depth: null }) - // add-end -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Run the script again to see the results of the nested read query: - - - - - -```terminal -npx tsx script.ts -``` - - - - - -```code no-copy -[ - { id: 1, email: 'alice@prisma.io', name: 'Alice', posts: [] }, - { - id: 2, - email: 'bob@prisma.io', - name: 'Bob', - posts: [ - { - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 2 - }, - { - id: 2, - title: 'My second post', - content: 'This is still a draft', - published: false, - authorId: 2 - } - ] - } -] -``` - - - - - -This time, you're seeing two `User` objects being printed. Both of them have a `posts` field (which is empty for `"Alice"` and populated with two `Post` objects for `"Bob"`) that represents the `Post` records associated with them. - -Notice that the objects in the `usersWithPosts` array are fully typed as well. This means you will get autocompletion and the TypeScript compiler will prevent you from accidentally typing them. - -## 5. Next steps - -In this Quickstart guide, you have learned how to get started with Prisma ORM in a plain TypeScript project. Feel free to explore the Prisma Client API a bit more on your own, e.g. by including filtering, sorting, and pagination options in the `findMany` query or exploring more operations like `update` and `delete` queries. - -### Explore the data in Prisma Studio - -Prisma ORM comes with a built-in GUI to view and edit the data in your database. You can open it using the following command: - -```terminal -npx prisma studio -``` - -### Set up Prisma ORM with your own database - -If you want to move forward with Prisma ORM using your own PostgreSQL, MySQL, MongoDB or any other supported database, follow the Set Up Prisma ORM guides: - -- [Start with Prisma ORM from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql) -- [Add Prisma ORM to an existing project](/getting-started/setup-prisma/add-to-existing-project) - -### Get query insights and analytics with Prisma Optimize - -[Prisma Optimize](/optimize) helps you generate insights and provides recommendations that can help you make your database queries faster. - -Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. - -### Explore ready-to-run Prisma ORM examples - -Check out the [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository on GitHub to see how Prisma ORM can be used with your favorite library. The repo contains examples with Express, NestJS, GraphQL as well as fullstack examples with Next.js and Vue.js, and a lot more. - -### Speed up your database queries with Prisma Accelerate - -[Prisma Accelerate](/accelerate) is a connection pooler and global database cache that can drastically speed up your database queries. Check out the [Speed Test](https://accelerate-speed-test.prisma.io/) or try Accelerate with your favorite framework: - -| Demo | Description | -| ----------------------------------------------- | -------------------------------------------------------------------------- | -| [`nextjs-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/nextjs-starter) | A Next.js project using Prisma Accelerate's caching and connection pooling | -| [`svelte-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/svelte-starter) | A SvelteKit project using Prisma Accelerate's caching and connection pooling | -| [`solidstart-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/solidstart-starter) | A Solidstart project using Prisma Accelerate's caching and connection pooling | -| [`remix-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/remix-starter) | A Remix project using Prisma Accelerate's caching and connection pooling | -| [`nuxt-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/nuxtjs-starter) | A Nuxt.js project using Prisma Accelerate's caching and connection pooling | -| [`astro-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/astro-starter) | An Astro project using Prisma Accelerate's caching and connection pooling | - - -### Build an app with Prisma ORM - -The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - -- [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) -- [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) -- [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) \ No newline at end of file diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx new file mode 100644 index 0000000000..c73c259d73 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx @@ -0,0 +1,276 @@ +--- +title: 'Quickstart with Prisma ORM and Prisma Postgres' +sidebar_label: 'Prisma Postgres' +metaTitle: 'Quickstart: Prisma ORM with Prisma Postgres (5 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to Prisma Postgres and generating a Prisma Client for database access.' +sidebar_custom_props: { badge: '5 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import CreateProject from '../../_components/_create-project.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[Prisma Postgres](/postgres) is a fully managed PostgreSQL database that scales to zero and integrates smoothly with both Prisma ORM and Prisma Studio. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to Prisma Postgres using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. + +## Prerequisites + + + +## 1. Create a new project + + + +## 2. Install required dependencies + +Install the packages needed for this quickstart: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-pg dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 3. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +## 4. Initialize Prisma ORM and create a Prisma Postgres database + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --db --output ../generated/prisma +``` + +:::info + +You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database. + +::: + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a new Prisma Postgres database (when using `--db` flag) +- Creates a `.env` file in the root directory for environment variables +- Generates the Prisma Client in the `generated/prisma/` directory +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +} +``` + +## 5. Define your data model + +Open `prisma/schema.prisma` and add the following models: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +} + +//add-start +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 +} +//add-end +``` + +## 6. Create and apply your first migration + +Create your first migration to set up the database tables: + +```terminal +npx prisma migrate dev --name init +``` + +This command creates the database tables based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + +## 7. Instantiate Prisma Client + +Now that you have all the dependencies installed, you can instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPg } from '@prisma/adapter-pg' +import { PrismaClient } from '../generated/prisma/client' + +const connectionString = `${process.env.DATABASE_URL}` + +const adapter = new PrismaPg({ connectionString }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +## 8. Write your first query + +Create a `script.ts` file to test your setup: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Create a new user with a post + const user = await prisma.user.create({ + data: { + name: 'Alice', + email: 'alice@prisma.io', + posts: { + create: { + title: 'Hello World', + content: 'This is my first post!', + published: true, + }, + }, + }, + include: { + posts: true, + }, + }) + console.log('Created user:', user) + + // Fetch all users with their posts + const allUsers = await prisma.user.findMany({ + include: { + posts: true, + }, + }) + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +You should see the created user and all users printed to the console! + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [Prisma Postgres documentation](/postgres) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database connection management](/orm/prisma-client/setup-and-configuration/databases-connections) diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx new file mode 100644 index 0000000000..b4dcb6abf4 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx @@ -0,0 +1,278 @@ +--- +title: 'Quickstart with Prisma ORM and SQLite' +sidebar_label: 'SQLite' +metaTitle: 'Quickstart: Prisma ORM with SQLite (5 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to SQLite and generating a Prisma Client for database access.' +sidebar_custom_props: { badge: '5 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import CreateProject from '../../_components/_create-project.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[SQLite](https://sqlite.org) is a lightweight, file-based database that's perfect for development, prototyping, and small applications. It requires no setup and stores data in a local file. + +In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to SQLite using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. + +## Prerequisites + + + +## 1. Create a new project + + + +## 2. Install required dependencies + +Install the packages needed for this quickstart: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-better-sqlite3 dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-better-sqlite3`** - The SQLite driver adapter that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 3. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +## 4. Initialize Prisma ORM + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider sqlite --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a `.env` file in the root directory for environment variables +- Generates the Prisma Client in the `generated/prisma/` directory +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "sqlite" +} +``` + +A `.env` file should be created with the following value: + +```env file=.env +DATABASE_URL="file:./dev.db" +``` + +## 5. Define your data model + +Open `prisma/schema.prisma` and add the following models: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +//add-start +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 +} +//add-end +``` + +## 6. Create and apply your first migration + +Create your first migration to set up the database tables: + +```terminal +npx prisma migrate dev --name init +``` + +This command creates the database tables based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + +## 7. Instantiate Prisma Client + +Now that you have all the dependencies installed, you can instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3"; +import { PrismaClient } from "../generated/prisma/client"; + +const connectionString = `${process.env.DATABASE_URL}`; + +const adapter = new PrismaBetterSqlite3({ url: connectionString }); +const prisma = new PrismaClient({ adapter }); + +export { prisma }; +``` + +## 8. Write your first query + +Create a `script.ts` file to test your setup: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Create a new user with a post + const user = await prisma.user.create({ + data: { + name: 'Alice', + email: 'alice@prisma.io', + posts: { + create: { + title: 'Hello World', + content: 'This is my first post!', + published: true, + }, + }, + }, + include: { + posts: true, + }, + }) + console.log('Created user:', user) + + // Fetch all users with their posts + const allUsers = await prisma.user.findMany({ + include: { + posts: true, + }, + }) + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +You should see the created user and all users printed to the console! + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [SQLite database connector](/orm/overview/databases/sqlite) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database connection management](/orm/prisma-client/setup-and-configuration/databases-connections) diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx new file mode 100644 index 0000000000..53f3352521 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx @@ -0,0 +1,292 @@ +--- +title: 'Quickstart with Prisma ORM and PostgreSQL' +sidebar_label: 'PostgreSQL' +metaTitle: 'Quickstart: Prisma ORM with PostgreSQL (10 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to PostgreSQL and generating a Prisma Client for database access.' +sidebar_custom_props: { badge: '10 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import CreateProject from '../../_components/_create-project.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[PostgreSQL](https://www.postgresql.org) is a powerful, open-source relational database. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to PostgreSQL using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. + +## Prerequisites + + + +You also need: + +- A [PostgreSQL](https://www.postgresql.org/) database server running and accessible +- Database connection details (host, port, username, password, database name) + +:::tip Need a PostgreSQL database? + +If you don't already have a PostgreSQL database, follow the quickstart to set up a production-ready [Prisma Postgres](/getting-started/prisma-orm/quickstart/prisma-postgres) database with Prisma ORM in a new project. + +::: + +## 1. Create a new project + + + +## 2. Install required dependencies + +Install the packages needed for this quickstart: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-pg dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 3. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +## 4. Initialize Prisma ORM + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider postgresql --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a `.env` file in the root directory for environment variables +- Generates the Prisma Client in the `generated/prisma/` directory +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +} +``` + +Update your `.env` file with your PostgreSQL connection string: + +```env file=.env +DATABASE_URL="postgresql://username:password@localhost:5432/mydb?schema=public" +``` + +Replace the placeholders with your actual database credentials: +- `username`: Your PostgreSQL username +- `password`: Your PostgreSQL password +- `localhost:5432`: Your PostgreSQL host and port +- `mydb`: Your database name + +## 5. Define your data model + +Open `prisma/schema.prisma` and add the following models: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +} + +//add-start +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 +} +//add-end +``` + +## 6. Create and apply your first migration + +Create your first migration to set up the database tables: + +```terminal +npx prisma migrate dev --name init +``` + +This command creates the database tables based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + +## 7. Instantiate Prisma Client + +Now that you have all the dependencies installed, you can instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPg } from '@prisma/adapter-pg' +import { PrismaClient } from '../generated/prisma/client' + +const connectionString = `${process.env.DATABASE_URL}` + +const adapter = new PrismaPg({ connectionString }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +## 8. Write your first query + +Create a `script.ts` file to test your setup: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Create a new user with a post + const user = await prisma.user.create({ + data: { + name: 'Alice', + email: 'alice@prisma.io', + posts: { + create: { + title: 'Hello World', + content: 'This is my first post!', + published: true, + }, + }, + }, + include: { + posts: true, + }, + }) + console.log('Created user:', user) + + // Fetch all users with their posts + const allUsers = await prisma.user.findMany({ + include: { + posts: true, + }, + }) + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +You should see the created user and all users printed to the console! + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [PostgreSQL database connector](/orm/overview/databases/postgresql) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database connection management](/orm/prisma-client/setup-and-configuration/databases-connections) diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx new file mode 100644 index 0000000000..8edc3e72df --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx @@ -0,0 +1,300 @@ +--- +title: 'Quickstart with Prisma ORM and MySQL' +sidebar_label: 'MySQL' +metaTitle: 'Quickstart: Prisma ORM with MySQL (10 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to MySQL and generating a Prisma Client for database access.' +sidebar_custom_props: { badge: '10 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import CreateProject from '../../_components/_create-project.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[MySQL](https://www.mysql.com) is a popular open-source relational database. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to MySQL using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. + +:::note + +This guide also applies to **MariaDB**, which is MySQL-compatible. + +::: + +## Prerequisites + + + +You also need: + +- A [MySQL](https://www.mysql.com/) database server running and accessible +- Database connection details (host, port, username, password, database name) + + + +## 2. Install required dependencies + +Install the packages needed for this quickstart: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-mariadb dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-mariadb`** - The MySQL/MariaDB driver adapter that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 3. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +## 4. Initialize Prisma ORM + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider mysql --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a `.env` file in the root directory for environment variables +- Generates the Prisma Client in the `generated/prisma/` directory +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mysql" +} +``` + +Update your `.env` file with your MySQL connection string details: + +```env file=.env +DATABASE_URL="mysql://username:password@localhost:3306/mydb" +//add-start +DATABASE_USER="username" +DATABASE_PASSWORD="password" +DATABASE_NAME="mydb" +DATABASE_HOST="localhost" +DATABASE_PORT=3306 +//add-end +``` + +Replace the placeholders with your actual database credentials: +- `username`: Your MySQL username +- `password`: Your MySQL password +- `localhost:3306`: Your MySQL host and port +- `mydb`: Your database name + +## 5. Define your data model + +Open `prisma/schema.prisma` and add the following models: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mysql" +} + +//add-start +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? @db.Text + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id]) + authorId Int +} +//add-end +``` + +## 6. Create and apply your first migration + +Create your first migration to set up the database tables: + +```terminal +npx prisma migrate dev --name init +``` + +This command creates the database tables based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + +## 7. Instantiate Prisma Client + +Now that you have all the dependencies installed, you can instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaMariaDb } from '@prisma/adapter-mariadb'; +import { PrismaClient } from '../generated/prisma/client'; + +const adapter = new PrismaMariaDb({ + host: process.env.DATABASE_HOST, + user: process.env.DATABASE_USER, + password: process.env.DATABASE_PASSWORD, + database: process.env.DATABASE_NAME, + connectionLimit: 5 +}); +const prisma = new PrismaClient({ adapter }); + +export { prisma } +``` + +## 8. Write your first query + +Create a `script.ts` file to test your setup: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + const user = await prisma.user.create({ + data: { + name: 'Alice', + email: 'alice@prisma.io', + posts: { + create: { + title: 'Hello World', + content: 'This is my first post!', + published: true, + }, + }, + }, + include: { + posts: true, + }, + }) + console.log('Created user:', user) + + // Fetch all users with their posts + const allUsers = await prisma.user.findMany({ + include: { + posts: true, + }, + }) + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +You should see the created user and all users printed to the console! + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [MySQL database connector](/orm/overview/databases/mysql) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database connection management](/orm/prisma-client/setup-and-configuration/databases-connections) diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx new file mode 100644 index 0000000000..f78be99bca --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx @@ -0,0 +1,309 @@ +--- +title: 'Quickstart with Prisma ORM and SQL Server' +sidebar_label: 'SQL Server' +metaTitle: 'Quickstart: Prisma ORM with SQL Server (10 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to SQL Server and generating a Prisma Client for database access.' +sidebar_custom_props: { badge: '10 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import CreateProject from '../../_components/_create-project.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[Microsoft SQL Server](https://www.microsoft.com/en-us/sql-server) is an enterprise-grade relational database. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to SQL Server using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. + +## Prerequisites + + + +You also need: + +- A [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/?view=sql-server-ver16) database + - [Microsoft SQL Server on Linux for Docker](/orm/overview/databases/sql-server/sql-server-docker) + - [Microsoft SQL Server on Windows (local)](/orm/overview/databases/sql-server/sql-server-local) +- Database connection details (host, port, username, password, database name) + +## 1. Create a new project + + + +## 2. Install required dependencies + +Install the packages needed for this quickstart: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-mssql dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-mssql`** - The SQL Server driver adapter that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 3. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +## 4. Initialize Prisma ORM + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider sqlserver --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a `.env` file in the root directory for environment variables +- Generates the Prisma Client in the `generated/prisma/` directory +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "sqlserver" +} +``` + +Update your `.env` file with your SQL Server connection string details: + +```env file=.env +DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=username;password=password;encrypt=true" +//add-start +DB_USER="username" +DB_PASSWORD="password" +DB_NAME="mydb" +HOST="localhost" +//add-end +``` + +Replace the placeholders with your actual database credentials: + +- `localhost:1433`: Your SQL Server host and port +- `mydb`: Your database name +- `username`: Your SQL Server username +- `password`: Your SQL Server password + +## 5. Define your data model + +Open `prisma/schema.prisma` and add the following models: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "sqlserver" +} + +//add-start +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 +} +//add-end +``` + +## 6. Create and apply your first migration + +Create your first migration to set up the database tables: + +```terminal +npx prisma migrate dev --name init +``` + +This command creates the database tables based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + +## 7. Instantiate Prisma Client + +Now that you have all the dependencies installed, you can instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaMSSQL } from '@prisma/adapter-mssql'; +import { PrismaClient } from '../generated/prisma/client'; + +const sqlConfig = { + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + server: process.env.HOST, + pool: { + max: 10, + min: 0, + idleTimeoutMillis: 30000 + }, + options: { + encrypt: true, // for azure + trustServerCertificate: false // change to true for local dev / self-signed certs + } +} + +const adapter = new PrismaMSSQL(sqlConfig) +const prisma = new PrismaClient({ adapter }); + +export { prisma } +``` + +## 8. Write your first query + +Create a `script.ts` file to test your setup: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Create a new user with a post + const user = await prisma.user.create({ + data: { + name: 'Alice', + email: 'alice@prisma.io', + posts: { + create: { + title: 'Hello World', + content: 'This is my first post!', + published: true, + }, + }, + }, + include: { + posts: true, + }, + }) + console.log('Created user:', user) + + // Fetch all users with their posts + const allUsers = await prisma.user.findMany({ + include: { + posts: true, + }, + }) + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +You should see the created user and all users printed to the console! + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [SQL Server database connector](/orm/overview/databases/sql-server) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database connection management](/orm/prisma-client/setup-and-configuration/databases-connections) diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx new file mode 100644 index 0000000000..d6c4752fb5 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx @@ -0,0 +1,311 @@ +--- +title: 'Quickstart with Prisma ORM and PlanetScale' +sidebar_label: 'PlanetScale' +metaTitle: 'Quickstart: Prisma ORM with PlanetScale MySQL (10 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to PlanetScale MySQL and generating a Prisma Client for database access.' +sidebar_custom_props: { badge: '10 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import CreateProject from '../../_components/_create-project.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[PlanetScale](https://planetscale.com) is a serverless database platform. This guide covers **PlanetScale MySQL**. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to PlanetScale MySQL using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. + +:::note + +PlanetScale also offers PostgreSQL databases. If you're using **PlanetScale PostgreSQL**, follow the [PostgreSQL quickstart guide](/getting-started/prisma-orm/quickstart/postgresql) instead. + +::: + +## Prerequisites + + + +You also need: + +- A [PlanetScale](https://planetscale.com) database +- Database connection string from PlanetScale + +## 1. Create a new project + + + +## 2. Install required dependencies + +Install the packages needed for this quickstart: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-planetscale undici dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-planetscale`** - The PlanetScale driver adapter that connects Prisma Client to your database +- **`undici`** - A fast HTTP/1.1 client required by the PlanetScale adapter +- **`dotenv`** - Loads environment variables from your `.env` file + +## 3. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +## 4. Initialize Prisma ORM + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider mysql --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a `.env` file in the root directory for environment variables +- Generates the Prisma Client in the `generated/prisma/` directory +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mysql" +} +``` + +Update your schema to include `relationMode = "prisma"` for PlanetScale: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mysql" + relationMode = "prisma" +} +``` + +Update your `.env` file with your PlanetScale connection string: + +```env file=.env +DATABASE_URL="mysql://username:password@host.connect.psdb.cloud/mydb?sslaccept=strict" +``` + +Replace with your actual PlanetScale connection string from your database dashboard. + +## 5. Define your data model + +Open `prisma/schema.prisma` and add the following models: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mysql" + relationMode = "prisma" +} + +//add-start +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? @db.Text + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id]) + authorId Int + + @@index([authorId]) +} +//add-end +``` + +:::note + +Note the `@@index([authorId])` on the `Post` model. PlanetScale requires indexes on foreign keys when using `relationMode = "prisma"`. + +::: + +## 6. Push your schema to PlanetScale + +PlanetScale uses a branching workflow instead of traditional migrations. Push your schema directly: + +```terminal +npx prisma db push +``` + +This command creates the database tables based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + +## 7. Instantiate Prisma Client + +Now that you have all the dependencies installed, you can instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPlanetScale } from '@prisma/adapter-planetscale' +import { PrismaClient } from '../generated/prisma/client' +import { fetch as undiciFetch } from 'undici' + +const adapter = new PrismaPlanetScale({ url: process.env.DATABASE_URL, fetch: undiciFetch }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +## 8. Write your first query + +Create a `script.ts` file to test your setup: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Create a new user with a post + const user = await prisma.user.create({ + data: { + name: 'Alice', + email: 'alice@prisma.io', + posts: { + create: { + title: 'Hello World', + content: 'This is my first post!', + published: true, + }, + }, + }, + include: { + posts: true, + }, + }) + console.log('Created user:', user) + + // Fetch all users with their posts + const allUsers = await prisma.user.findMany({ + include: { + posts: true, + }, + }) + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +You should see the created user and all users printed to the console! + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [PlanetScale database connector](/orm/overview/databases/planetscale) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database connection management](/orm/prisma-client/setup-and-configuration/databases-connections) diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx new file mode 100644 index 0000000000..8768122e43 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx @@ -0,0 +1,282 @@ +--- +title: 'Quickstart with Prisma ORM and CockroachDB' +sidebar_label: 'CockroachDB' +metaTitle: 'Quickstart: Prisma ORM with CockroachDB (10 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to CockroachDB and generating a Prisma Client for database access.' +sidebar_custom_props: { badge: '10 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import CreateProject from '../../_components/_create-project.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[CockroachDB](https://www.cockroachlabs.com) is a distributed SQL database built for cloud applications. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to CockroachDB using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. + +## Prerequisites + + + +You also need: + +- A [CockroachDB](https://www.cockroachlabs.com/) database +- Database connection string from CockroachDB + +## 1. Create a new project + + + +## 2. Install required dependencies + +Install the packages needed for this quickstart: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-pg dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database (CockroachDB is PostgreSQL-compatible) +- **`dotenv`** - Loads environment variables from your `.env` file + +## 3. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +## 4. Initialize Prisma ORM + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider cockroachdb --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a `.env` file in the root directory for environment variables +- Generates the Prisma Client in the `generated/prisma/` directory +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "cockroachdb" +} +``` + +Update your `.env` file with your CockroachDB connection string: + +```env file=.env +DATABASE_URL="postgresql://username:password@host:26257/mydb?sslmode=require" +``` + +Replace with your actual CockroachDB connection string from your cluster dashboard. + +## 5. Define your data model + +Open `prisma/schema.prisma` and add the following models: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "cockroachdb" +} + +//add-start +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 +} +//add-end +``` + +## 6. Create and apply your first migration + +Create your first migration to set up the database tables: + +```terminal +npx prisma migrate dev --name init +``` + +This command creates the database tables based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + +## 7. Instantiate Prisma Client + +Now that you have all the dependencies installed, you can instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPg } from '@prisma/adapter-pg' +import { PrismaClient } from '../generated/prisma/client' + +const connectionString = `${process.env.DATABASE_URL}` + +const adapter = new PrismaPg({ connectionString }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +## 8. Write your first query + +Create a `script.ts` file to test your setup: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Create a new user with a post + const user = await prisma.user.create({ + data: { + name: 'Alice', + email: 'alice@prisma.io', + posts: { + create: { + title: 'Hello World', + content: 'This is my first post!', + published: true, + }, + }, + }, + include: { + posts: true, + }, + }) + console.log('Created user:', user) + + // Fetch all users with their posts + const allUsers = await prisma.user.findMany({ + include: { + posts: true, + }, + }) + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +You should see the created user and all users printed to the console! + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [CockroachDB database connector](/orm/overview/databases/cockroachdb) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database connection management](/orm/prisma-client/setup-and-configuration/databases-connections) diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx new file mode 100644 index 0000000000..a3594ba48e --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx @@ -0,0 +1,302 @@ +--- +title: 'Quickstart with Prisma ORM and MongoDB' +sidebar_label: 'MongoDB' +metaTitle: 'Quickstart: Prisma ORM with MongoDB (10 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to MongoDB and generating a Prisma Client for database access.' +sidebar_custom_props: { badge: '10 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import CreateProject from '../../_components/_create-project.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[MongoDB](https://www.mongodb.com) is a popular NoSQL document database. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to MongoDB using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. + +:::warning[Do not upgrade to Prisma ORM v7 if you are using MongoDB] + +Prisma ORM v7 is not yet compatible with MongoDB. Please use Prisma ORM v6 instead. Support for MongoDB is coming in a future release. + +::: + +## Prerequisites + + + +You also need: + +- A [MongoDB](https://www.mongodb.com/) database accessible via connection string + +## 1. Create a new project + + + +## 2. Install required dependencies + +Install the packages needed for this quickstart: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db push`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`dotenv`** - Loads environment variables from your `.env` file + +:::note + +MongoDB doesn't require driver adapters since Prisma ORM connects directly to MongoDB. + +::: + +## 3. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +## 4. Initialize Prisma ORM + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider mongodb --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a `.env` file in the root directory for environment variables +- Generates the Prisma Client in the `generated/prisma/` directory +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + engine: "classic", + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + engine: "classic", + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mongodb" + url = env("DATABASE_URL") +} +``` + +Update your `.env` file with your MongoDB connection string: + +```env file=.env +DATABASE_URL="mongodb+srv://username:password@cluster.mongodb.net/mydb" +``` + +Replace with your actual MongoDB connection string. + +## 5. Define your data model + +Open `prisma/schema.prisma` and add the following models: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mongodb" + url = env("DATABASE_URL") +} + +//add-start +model User { + id String @id @default(auto()) @map("_id") @db.ObjectId + email String @unique + name String? + posts Post[] +} + +model Post { + id String @id @default(auto()) @map("_id") @db.ObjectId + title String + content String? + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id]) + authorId String @db.ObjectId +} +//add-end +``` + +## 6. Push your schema to MongoDB + +Since MongoDB doesn't use migrations, push your schema directly: + +```terminal +npx prisma db push +``` + +This command creates the collections based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + +## 7. Instantiate Prisma Client + +Now that you have all the dependencies installed, you can instantiate Prisma Client: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaClient } from '../generated/prisma/client' + +const prisma = new PrismaClient() + +export { prisma } +``` + +## 8. Write your first query + +Create a `script.ts` file to test your setup: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Create a new user with a post + const user = await prisma.user.create({ + data: { + name: 'Alice', + email: 'alice@prisma.io', + posts: { + create: { + title: 'Hello World', + content: 'This is my first post!', + published: true, + }, + }, + }, + include: { + posts: true, + }, + }) + console.log('Created user:', user) + + // Fetch all users with their posts + const allUsers = await prisma.user.findMany({ + include: { + posts: true, + }, + }) + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +You should see the created user and all users printed to the console! + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## Troubleshooting + +### `Error in connector: SCRAM failure: Authentication failed.` + +If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. + +### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` + +If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). + +## More info + +- [MongoDB database connector](/orm/overview/databases/mongodb) +- [MongoDB data modeling patterns](/orm/overview/databases/mongodb#type-mapping-between-mongodb-and-the-prisma-schema) +- [MongoDB deployment considerations](/orm/overview/databases/mongodb#differences-to-connectors-for-relational-databases) diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx new file mode 100644 index 0000000000..e6585e83b8 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx @@ -0,0 +1,257 @@ +--- +title: 'Add Prisma ORM to an existing Prisma Postgres project' +sidebar_title: 'Prisma Postgres' +metaTitle: 'How to add Prisma ORM to an existing project using Prisma Postgres (15 min)' +metaDescription: 'Add Prisma ORM to an existing TypeScript project with Prisma Postgres and learn database introspection, baselining, and querying.' +sidebar_custom_props: { badge: '15 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[Prisma Postgres](/postgres) is a fully managed PostgreSQL database that scales to zero and integrates smoothly with both Prisma ORM and Prisma Studio. In this guide, you will learn how to add Prisma ORM to an existing TypeScript project, connect it to Prisma Postgres, introspect your existing database schema, and start querying with type-safe Prisma Client. + +## Prerequisites + + + +## 1. Set up Prisma ORM + +Navigate to your existing project directory and install the required dependencies: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-pg dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 2. Initialize Prisma ORM + +Set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider postgresql --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection configuration +- Creates a `.env` file in the root directory for environment variables +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +} +``` + +## 3. Connect your database + +Update the `.env` file with your Prisma Postgres connection URL: + +```bash file=.env +DATABASE_URL="postgresql://user:password@host:5432/database?schema=public" +``` + +Replace the placeholder values with your actual Prisma Postgres connection details. + +## 4. Introspect your database + +Run the following command to introspect your existing database: + +```terminal +npx prisma db pull +``` + +This command reads the `DATABASE_URL` environment variable, connects to your database, and introspects the database schema. It then translates the database schema from SQL into a data model in your Prisma schema. + +![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) + +After introspection, your Prisma schema will contain models that represent your existing database tables. + +## 5. Baseline your database + +To use Prisma Migrate with your existing database, you need to [baseline your database](/orm/prisma-migrate/getting-started). + +First, create a `migrations` directory: + +```terminal +mkdir -p prisma/migrations/0_init +``` + +Next, generate the migration file with `prisma migrate diff`: + +```terminal +npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql +``` + +Review the generated migration file to ensure it matches your database schema. + +Then, mark the migration as applied: + +```terminal +npx prisma migrate resolve --applied 0_init +``` + +You now have a baseline for your current database schema. + +## 6. Generate Prisma ORM types + +Generate Prisma Client based on your introspected schema: + +```terminal +npx prisma generate +``` + +This creates a type-safe Prisma Client tailored to your database schema in the `generated/prisma` directory. + +## 7. Instantiate Prisma Client + +Create a utility file to instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPg } from '@prisma/adapter-pg' +import { PrismaClient } from '../generated/prisma/client' + +const connectionString = `${process.env.DATABASE_URL}` + +const adapter = new PrismaPg({ connectionString }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +## 8. Query your database + +Now you can use Prisma Client to query your database. Create a `script.ts` file: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Example: Fetch all records from a table + // Replace 'user' with your actual model name + const allUsers = await prisma.user.findMany() + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +## 9. Evolve your schema + +To make changes to your database schema: + +### 9.1. Update your Prisma schema file + +Update your Prisma schema file to reflect the changes you want to make to your database schema. For example, add a new model: + +```prisma file=prisma/schema.prisma +// add-start +model Post { + id Int @id @default(autoincrement()) + title String + content String? + published Boolean @default(false) + authorId Int + author User @relation(fields: [authorId], references: [id]) +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + name String? + posts Post[] +} +// add-end +``` + +### 9.2. Create and apply a migration: + +```terminal +npx prisma migrate dev --name your_migration_name +``` + +This command will: +- Create a new SQL migration file +- Apply the migration to your database +- Regenerate Prisma Client + +## 10. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [Prisma Postgres documentation](/postgres) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database introspection](/orm/prisma-schema/introspection) +- [Prisma Migrate](/orm/prisma-migrate) diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx new file mode 100644 index 0000000000..e9d5d66134 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx @@ -0,0 +1,261 @@ +--- +title: 'Add Prisma ORM to an existing SQLite project' +sidebar_title: 'SQLite' +metaTitle: 'How to add Prisma ORM to an existing project using SQLite (15 min)' +metaDescription: 'Add Prisma ORM to an existing TypeScript project with SQLite and learn database introspection, baselining, and querying.' +sidebar_custom_props: { badge: '15 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[SQLite](https://sqlite.org) is a lightweight, file-based database that's perfect for development, prototyping, and small applications. It requires no setup and stores data in a local file. In this guide, you will learn how to add Prisma ORM to an existing TypeScript project, connect it to SQLite, introspect your existing database schema, and start querying with type-safe Prisma Client. + +## Prerequisites + + + +## 1. Set up Prisma ORM + +Navigate to your existing project directory and install the required dependencies: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-better-sqlite3 dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-better-sqlite3`** - The SQLite driver adapter that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 2. Initialize Prisma ORM + +Set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider sqlite --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection configuration +- Creates a `.env` file in the root directory for environment variables +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "sqlite" +} +``` + +A `.env` file should be created with the following value: + +```env file=.env +DATABASE_URL="file:./dev.db" +``` + +## 3. Connect your database + +Update the `.env` file to point to your existing SQLite database file: + +```bash file=.env +DATABASE_URL="file:./path/to/your/database.db" +``` + +## 4. Introspect your database + +Run the following command to introspect your existing database: + +```terminal +npx prisma db pull +``` + +This command reads the `DATABASE_URL` environment variable, connects to your database, and introspects the database schema. It then translates the database schema from SQL into a data model in your Prisma schema. + +![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) + +After introspection, your Prisma schema will contain models that represent your existing database tables. + +## 5. Baseline your database + +To use Prisma Migrate with your existing database, you need to [baseline your database](/orm/prisma-migrate/getting-started). + +First, create a `migrations` directory: + +```terminal +mkdir -p prisma/migrations/0_init +``` + +Next, generate the migration file with `prisma migrate diff`: + +```terminal +npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql +``` + +Review the generated migration file to ensure it matches your database schema. + +Then, mark the migration as applied: + +```terminal +npx prisma migrate resolve --applied 0_init +``` + +You now have a baseline for your current database schema. + +## 6. Generate Prisma ORM types + +Generate Prisma Client based on your introspected schema: + +```terminal +npx prisma generate +``` + +This creates a type-safe Prisma Client tailored to your database schema in the `generated/prisma` directory. + +## 7. Instantiate Prisma Client + +Create a utility file to instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3"; +import { PrismaClient } from "../generated/prisma/client"; + +const connectionString = `${process.env.DATABASE_URL}`; + +const adapter = new PrismaBetterSqlite3({ url: connectionString }); +const prisma = new PrismaClient({ adapter }); + +export { prisma }; +``` + +## 8. Query your database + +Now you can use Prisma Client to query your database. Create a `script.ts` file: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Example: Fetch all records from a table + // Replace 'user' with your actual model name + const allUsers = await prisma.user.findMany() + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +## 9. Evolve your schema + +To make changes to your database schema: + +### 9.1. Update your Prisma schema file + +Update your Prisma schema file to reflect the changes you want to make to your database schema. For example, add a new model: + +```prisma file=prisma/schema.prisma +// add-start +model Post { + id Int @id @default(autoincrement()) + title String + content String? + published Boolean @default(false) + authorId Int + author User @relation(fields: [authorId], references: [id]) +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + name String? + posts Post[] +} +// add-end +``` + +### 9.2. Create and apply a migration: + +```terminal +npx prisma migrate dev --name your_migration_name +``` + +This command will: +- Create a new SQL migration file +- Apply the migration to your database +- Regenerate Prisma Client + +## 10. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [SQLite database connector](/orm/overview/databases/sqlite) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database introspection](/orm/prisma-schema/introspection) +- [Prisma Migrate](/orm/prisma-migrate) diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx new file mode 100644 index 0000000000..46deacf6c4 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx @@ -0,0 +1,261 @@ +--- +title: 'Add Prisma ORM to an existing PostgreSQL project' +sidebar_title: 'PostgreSQL' +metaTitle: 'How to add Prisma ORM to an existing project using PostgreSQL (15 min)' +metaDescription: 'Add Prisma ORM to an existing TypeScript project with PostgreSQL and learn database introspection, baselining, and querying.' +sidebar_custom_props: { badge: '15 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[PostgreSQL](https://www.postgresql.org/) is a popular open-source relational database known for its reliability, feature robustness, and performance. In this guide, you will learn how to add Prisma ORM to an existing TypeScript project, connect it to PostgreSQL, introspect your existing database schema, and start querying with type-safe Prisma Client. + +## Prerequisites + + + +## 1. Set up Prisma ORM + +Navigate to your existing project directory and install the required dependencies: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-pg dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 2. Initialize Prisma ORM + +Set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider postgresql --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection configuration +- Creates a `.env` file in the root directory for environment variables +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +} +``` + +## 3. Connect your database + +Update the `.env` file with your PostgreSQL connection URL: + +```bash file=.env +DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public" +``` + +The [format of the connection URL](/orm/reference/connection-urls) for PostgreSQL looks as follows: + +``` +postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA +``` + +## 4. Introspect your database + +Run the following command to introspect your existing database: + +```terminal +npx prisma db pull +``` + +This command reads the `DATABASE_URL` environment variable, connects to your database, and introspects the database schema. It then translates the database schema from SQL into a data model in your Prisma schema. + +![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) + +After introspection, your Prisma schema will contain models that represent your existing database tables. + +## 5. Baseline your database + +To use Prisma Migrate with your existing database, you need to [baseline your database](/orm/prisma-migrate/getting-started). + +First, create a `migrations` directory: + +```terminal +mkdir -p prisma/migrations/0_init +``` + +Next, generate the migration file with `prisma migrate diff`: + +```terminal +npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql +``` + +Review the generated migration file to ensure it matches your database schema. + +Then, mark the migration as applied: + +```terminal +npx prisma migrate resolve --applied 0_init +``` + +You now have a baseline for your current database schema. + +## 6. Generate Prisma ORM types + +Generate Prisma Client based on your introspected schema: + +```terminal +npx prisma generate +``` + +This creates a type-safe Prisma Client tailored to your database schema in the `generated/prisma` directory. + +## 7. Instantiate Prisma Client + +Create a utility file to instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPg } from '@prisma/adapter-pg' +import { PrismaClient } from '../generated/prisma/client' + +const connectionString = `${process.env.DATABASE_URL}` + +const adapter = new PrismaPg({ connectionString }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +## 8. Query your database + +Now you can use Prisma Client to query your database. Create a `script.ts` file: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Example: Fetch all records from a table + // Replace 'user' with your actual model name + const allUsers = await prisma.user.findMany() + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +## 9. Evolve your schema + +To make changes to your database schema: + +### 9.1. Update your Prisma schema file + +Update your Prisma schema file to reflect the changes you want to make to your database schema. For example, add a new model: + +```prisma file=prisma/schema.prisma +// add-start +model Post { + id Int @id @default(autoincrement()) + title String + content String? + published Boolean @default(false) + authorId Int + author User @relation(fields: [authorId], references: [id]) +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + name String? + posts Post[] +} +// add-end +``` + +### 9.2. Create and apply a migration: + +```terminal +npx prisma migrate dev --name your_migration_name +``` + +This command will: +- Create a new SQL migration file +- Apply the migration to your database +- Regenerate Prisma Client + +## 10. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [PostgreSQL database connector](/orm/overview/databases/postgresql) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database introspection](/orm/prisma-schema/introspection) +- [Prisma Migrate](/orm/prisma-migrate) diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/400-mysql.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/400-mysql.mdx new file mode 100644 index 0000000000..6830a8aa8c --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/400-mysql.mdx @@ -0,0 +1,272 @@ +--- +title: 'Add Prisma ORM to an existing MySQL project' +sidebar_title: 'MySQL' +metaTitle: 'How to add Prisma ORM to an existing project using MySQL (15 min)' +metaDescription: 'Add Prisma ORM to an existing TypeScript project with MySQL and learn database introspection, baselining, and querying.' +sidebar_custom_props: { badge: '15 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[MySQL](https://www.mysql.com/) is a widely-used open-source relational database management system known for its speed, reliability, and ease of use. In this guide, you will learn how to add Prisma ORM to an existing TypeScript project, connect it to MySQL, introspect your existing database schema, and start querying with type-safe Prisma Client. + +## Prerequisites + + + +## 1. Set up Prisma ORM + +Navigate to your existing project directory and install the required dependencies: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-mariadb dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-mariadb`** - The MySQL/MariaDB driver adapter that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 2. Initialize Prisma ORM + +Set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider mysql --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection configuration +- Creates a `.env` file in the root directory for environment variables +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mysql" +} +``` + +## 3. Connect your database + +Update the `.env` file with your MySQL connection string details: + +```bash file=.env +DATABASE_URL="mysql://username:password@localhost:3306/mydb" +//add-start +DATABASE_USER="username" +DATABASE_PASSWORD="password" +DATABASE_NAME="mydb" +DATABASE_HOST="localhost" +DATABASE_PORT=3306 +//add-end +``` + +Replace the placeholders with your actual database credentials: +- `username`: Your MySQL username +- `password`: Your MySQL password +- `localhost:3306`: Your MySQL host and port +- `mydb`: Your database name + +## 4. Introspect your database + +Run the following command to introspect your existing database: + +```terminal +npx prisma db pull +``` + +This command reads the `DATABASE_URL` environment variable, connects to your database, and introspects the database schema. It then translates the database schema from SQL into a data model in your Prisma schema. + +![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) + +After introspection, your Prisma schema will contain models that represent your existing database tables. + +## 5. Baseline your database + +To use Prisma Migrate with your existing database, you need to [baseline your database](/orm/prisma-migrate/getting-started). + +First, create a `migrations` directory: + +```terminal +mkdir -p prisma/migrations/0_init +``` + +Next, generate the migration file with `prisma migrate diff`: + +```terminal +npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql +``` + +Review the generated migration file to ensure it matches your database schema. + +Then, mark the migration as applied: + +```terminal +npx prisma migrate resolve --applied 0_init +``` + +You now have a baseline for your current database schema. + +## 6. Generate Prisma ORM types + +Generate Prisma Client based on your introspected schema: + +```terminal +npx prisma generate +``` + +This creates a type-safe Prisma Client tailored to your database schema in the `generated/prisma` directory. + +## 7. Instantiate Prisma Client + +Create a utility file to instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaMariaDb } from '@prisma/adapter-mariadb'; +import { PrismaClient } from '../generated/prisma/client'; + +const adapter = new PrismaMariaDb({ + host: process.env.DATABASE_HOST, + user: process.env.DATABASE_USER, + password: process.env.DATABASE_PASSWORD, + database: process.env.DATABASE_NAME, + connectionLimit: 5 +}); +const prisma = new PrismaClient({ adapter }); + +export { prisma } +``` + +## 8. Query your database + +Now you can use Prisma Client to query your database. Create a `script.ts` file: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Example: Fetch all records from a table + // Replace 'user' with your actual model name + const allUsers = await prisma.user.findMany() + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +## 9. Evolve your schema + +To make changes to your database schema: + +### 9.1. Update your Prisma schema file + +Update your Prisma schema file to reflect the changes you want to make to your database schema. For example, add a new model: + +```prisma file=prisma/schema.prisma +// add-start +model Post { + id Int @id @default(autoincrement()) + title String + content String? + published Boolean @default(false) + authorId Int + author User @relation(fields: [authorId], references: [id]) +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + name String? + posts Post[] +} +// add-end +``` + +### 9.2. Create and apply a migration: + +```terminal +npx prisma migrate dev --name your_migration_name +``` + +This command will: +- Create a new SQL migration file +- Apply the migration to your database +- Regenerate Prisma Client + +## 10. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [MySQL database connector](/orm/overview/databases/mysql) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database introspection](/orm/prisma-schema/introspection) +- [Prisma Migrate](/orm/prisma-migrate) diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx new file mode 100644 index 0000000000..ca420d5d2b --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx @@ -0,0 +1,282 @@ +--- +title: 'Add Prisma ORM to an existing SQL Server project' +sidebar_title: 'SQL Server' +metaTitle: 'How to add Prisma ORM to an existing project using SQL Server (15 min)' +metaDescription: 'Add Prisma ORM to an existing TypeScript project with SQL Server and learn database introspection, baselining, and querying.' +sidebar_custom_props: { badge: '15 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[SQL Server](https://www.microsoft.com/en-us/sql-server) is Microsoft's enterprise relational database management system known for its performance, security, and integration with Microsoft tools. In this guide, you will learn how to add Prisma ORM to an existing TypeScript project, connect it to SQL Server, introspect your existing database schema, and start querying with type-safe Prisma Client. + +## Prerequisites + + + +## 1. Set up Prisma ORM + +Navigate to your existing project directory and install the required dependencies: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-mssql dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-mssql`** - The SQL Server driver adapter that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 2. Initialize Prisma ORM + +Set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider sqlserver --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection configuration +- Creates a `.env` file in the root directory for environment variables +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "sqlserver" +} +``` + +## 3. Connect your database + +Update the `.env` file with your SQL Server connection string details: + +```bash file=.env +DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=username;password=password;encrypt=true" +//add-start +DB_USER="username" +DB_PASSWORD="password" +DB_NAME="mydb" +HOST="localhost" +//add-end +``` + +Replace the placeholders with your actual database credentials: + +- `localhost:1433`: Your SQL Server host and port +- `mydb`: Your database name +- `username`: Your SQL Server username +- `password`: Your SQL Server password + +## 4. Introspect your database + +Run the following command to introspect your existing database: + +```terminal +npx prisma db pull +``` + +This command reads the `DATABASE_URL` environment variable, connects to your database, and introspects the database schema. It then translates the database schema from SQL into a data model in your Prisma schema. + +![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) + +After introspection, your Prisma schema will contain models that represent your existing database tables. + +## 5. Baseline your database + +To use Prisma Migrate with your existing database, you need to [baseline your database](/orm/prisma-migrate/getting-started). + +First, create a `migrations` directory: + +```terminal +mkdir -p prisma/migrations/0_init +``` + +Next, generate the migration file with `prisma migrate diff`: + +```terminal +npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql +``` + +Review the generated migration file to ensure it matches your database schema. + +Then, mark the migration as applied: + +```terminal +npx prisma migrate resolve --applied 0_init +``` + +You now have a baseline for your current database schema. + +## 6. Generate Prisma ORM types + +Generate Prisma Client based on your introspected schema: + +```terminal +npx prisma generate +``` + +This creates a type-safe Prisma Client tailored to your database schema in the `generated/prisma` directory. + +## 7. Instantiate Prisma Client + +Create a utility file to instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaMSSQL } from '@prisma/adapter-mssql'; +import { PrismaClient } from '../generated/prisma/client'; + +const sqlConfig = { + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + server: process.env.HOST, + pool: { + max: 10, + min: 0, + idleTimeoutMillis: 30000 + }, + options: { + encrypt: true, // for azure + trustServerCertificate: false // change to true for local dev / self-signed certs + } +} + +const adapter = new PrismaMSSQL(sqlConfig) +const prisma = new PrismaClient({ adapter }); + +export { prisma } +``` + +## 8. Query your database + +Now you can use Prisma Client to query your database. Create a `script.ts` file: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Example: Fetch all records from a table + // Replace 'user' with your actual model name + const allUsers = await prisma.user.findMany() + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +## 9. Evolve your schema + +To make changes to your database schema: + +### 9.1. Update your Prisma schema file + +Update your Prisma schema file to reflect the changes you want to make to your database schema. For example, add a new model: + +```prisma file=prisma/schema.prisma +// add-start +model Post { + id Int @id @default(autoincrement()) + title String + content String? + published Boolean @default(false) + authorId Int + author User @relation(fields: [authorId], references: [id]) +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + name String? + posts Post[] +} +// add-end +``` + +### 9.2. Create and apply a migration: + +```terminal +npx prisma migrate dev --name your_migration_name +``` + +This command will: +- Create a new SQL migration file +- Apply the migration to your database +- Regenerate Prisma Client + +## 10. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [SQL Server database connector](/orm/overview/databases/sql-server) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database introspection](/orm/prisma-schema/introspection) +- [Prisma Migrate](/orm/prisma-migrate) diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/600-planetscale.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/600-planetscale.mdx new file mode 100644 index 0000000000..66bf9be2f2 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/600-planetscale.mdx @@ -0,0 +1,249 @@ +--- +title: 'Add Prisma ORM to an existing PlanetScale project' +sidebar_title: 'PlanetScale' +metaTitle: 'How to add Prisma ORM to an existing project using PlanetScale MySQL (15 min)' +metaDescription: 'Add Prisma ORM to an existing TypeScript project with PlanetScale MySQL and learn database introspection and querying.' +sidebar_custom_props: { badge: '15 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[PlanetScale](https://planetscale.com) is a serverless database platform. This guide covers **PlanetScale MySQL**, which is built on Vitess and offers database branching, non-blocking schema changes, and automatic backups. In this guide, you will learn how to add Prisma ORM to an existing TypeScript project, connect it to PlanetScale MySQL, introspect your existing database schema, and start querying with type-safe Prisma Client. + +:::note + +PlanetScale also offers PostgreSQL databases. If you're using **PlanetScale PostgreSQL**, follow the [Add to existing PostgreSQL project guide](/getting-started/prisma-orm/add-to-existing-project/postgresql) instead. + +::: + +## Prerequisites + + + +## 1. Set up Prisma ORM + +Navigate to your existing project directory and install the required dependencies: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-planetscale undici dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-planetscale`** - The PlanetScale driver adapter that connects Prisma Client to your database +- **`undici`** - A fast HTTP/1.1 client required by the PlanetScale adapter +- **`dotenv`** - Loads environment variables from your `.env` file + +## 2. Initialize Prisma ORM + +Set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider mysql --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection configuration +- Creates a `.env` file in the root directory for environment variables +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mysql" + relationMode = "prisma" +} +``` + +:::info + +PlanetScale requires `relationMode = "prisma"` because it doesn't support foreign key constraints. + +::: + +## 3. Connect your database + +Update the `.env` file with your PlanetScale connection URL: + +```bash file=.env +DATABASE_URL="mysql://username:password@host.connect.psdb.cloud/mydb?sslaccept=strict" +``` + +You can find your connection string in the PlanetScale dashboard. + +## 4. Introspect your database + +Run the following command to introspect your existing database: + +```terminal +npx prisma db pull +``` + +This command reads the `DATABASE_URL` environment variable, connects to your database, and introspects the database schema. It then translates the database schema from SQL into a data model in your Prisma schema. + +![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) + +After introspection, your Prisma schema will contain models that represent your existing database tables. + +## 5. Generate Prisma ORM types + +Generate Prisma Client based on your introspected schema: + +```terminal +npx prisma generate +``` + +This creates a type-safe Prisma Client tailored to your database schema in the `generated/prisma` directory. + +## 6. Instantiate Prisma Client + +Create a utility file to instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPlanetScale } from '@prisma/adapter-planetscale' +import { PrismaClient } from '../generated/prisma/client' +import { fetch as undiciFetch } from 'undici' + +const adapter = new PrismaPlanetScale({ url: process.env.DATABASE_URL, fetch: undiciFetch }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +## 7. Query your database + +Now you can use Prisma Client to query your database. Create a `script.ts` file: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Example: Fetch all records from a table + // Replace 'user' with your actual model name + const allUsers = await prisma.user.findMany() + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +## 8. Evolve your schema + +PlanetScale uses a branching workflow instead of traditional migrations. To make changes to your database schema: + +### 8.1. Update your Prisma schema file + +Update your Prisma schema file to reflect the changes you want to make to your database schema. For example, add a new model: + +```prisma file=prisma/schema.prisma +// add-start +model Post { + id Int @id @default(autoincrement()) + title String + content String? + published Boolean @default(false) + authorId Int + author User @relation(fields: [authorId], references: [id]) +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + name String? + posts Post[] +} +// add-end +``` + +### 8.2. Push the changes to your development branch: + +```terminal +npx prisma db push +``` + +This command will: +- Apply the schema changes to your PlanetScale database +- Regenerate Prisma Client + +:::info + +For production deployments, use PlanetScale's [branching workflow](https://planetscale.com/docs/concepts/branching) to create deploy requests. + +::: + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [PlanetScale database connector](/orm/overview/databases/planetscale) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database introspection](/orm/prisma-schema/introspection) +- [PlanetScale branching workflow](https://planetscale.com/docs/concepts/branching) diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx new file mode 100644 index 0000000000..8e6215d96a --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx @@ -0,0 +1,261 @@ +--- +title: 'Add Prisma ORM to an existing CockroachDB project' +sidebar_title: 'CockroachDB' +metaTitle: 'How to add Prisma ORM to an existing project using CockroachDB (15 min)' +metaDescription: 'Add Prisma ORM to an existing TypeScript project with CockroachDB and learn database introspection, baselining, and querying.' +sidebar_custom_props: { badge: '15 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[CockroachDB](https://www.cockroachlabs.com/) is a distributed SQL database designed for cloud applications, offering horizontal scalability, strong consistency, and high availability. In this guide, you will learn how to add Prisma ORM to an existing TypeScript project, connect it to CockroachDB, introspect your existing database schema, and start querying with type-safe Prisma Client. + +## Prerequisites + + + +## 1. Set up Prisma ORM + +Navigate to your existing project directory and install the required dependencies: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-pg dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database (CockroachDB is PostgreSQL-compatible) +- **`dotenv`** - Loads environment variables from your `.env` file + +## 2. Initialize Prisma ORM + +Set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider cockroachdb --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection configuration +- Creates a `.env` file in the root directory for environment variables +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "cockroachdb" +} +``` + +## 3. Connect your database + +Update the `.env` file with your CockroachDB connection URL: + +```bash file=.env +DATABASE_URL="postgresql://user:password@host:26257/mydb?sslmode=require" +``` + +The [format of the connection URL](/orm/reference/connection-urls) for CockroachDB looks as follows: + +``` +postgresql://USER:PASSWORD@HOST:PORT/DATABASE?sslmode=require +``` + +## 4. Introspect your database + +Run the following command to introspect your existing database: + +```terminal +npx prisma db pull +``` + +This command reads the `DATABASE_URL` environment variable, connects to your database, and introspects the database schema. It then translates the database schema from SQL into a data model in your Prisma schema. + +![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) + +After introspection, your Prisma schema will contain models that represent your existing database tables. + +## 5. Baseline your database + +To use Prisma Migrate with your existing database, you need to [baseline your database](/orm/prisma-migrate/getting-started). + +First, create a `migrations` directory: + +```terminal +mkdir -p prisma/migrations/0_init +``` + +Next, generate the migration file with `prisma migrate diff`: + +```terminal +npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql +``` + +Review the generated migration file to ensure it matches your database schema. + +Then, mark the migration as applied: + +```terminal +npx prisma migrate resolve --applied 0_init +``` + +You now have a baseline for your current database schema. + +## 6. Generate Prisma ORM types + +Generate Prisma Client based on your introspected schema: + +```terminal +npx prisma generate +``` + +This creates a type-safe Prisma Client tailored to your database schema in the `generated/prisma` directory. + +## 7. Instantiate Prisma Client + +Create a utility file to instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPg } from '@prisma/adapter-pg' +import { PrismaClient } from '../generated/prisma/client' + +const connectionString = `${process.env.DATABASE_URL}` + +const adapter = new PrismaPg({ connectionString }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +## 8. Query your database + +Now you can use Prisma Client to query your database. Create a `script.ts` file: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Example: Fetch all records from a table + // Replace 'user' with your actual model name + const allUsers = await prisma.user.findMany() + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +## 9. Evolve your schema + +To make changes to your database schema: + +### 9.1. Update your Prisma schema file + +Update your Prisma schema file to reflect the changes you want to make to your database schema. For example, add a new model: + +```prisma file=prisma/schema.prisma +// add-start +model Post { + id Int @id @default(autoincrement()) + title String + content String? + published Boolean @default(false) + authorId Int + author User @relation(fields: [authorId], references: [id]) +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + name String? + posts Post[] +} +// add-end +``` + +### 9.2. Create and apply a migration: + +```terminal +npx prisma migrate dev --name your_migration_name +``` + +This command will: +- Create a new SQL migration file +- Apply the migration to your database +- Regenerate Prisma Client + +## 10. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [CockroachDB database connector](/orm/overview/databases/cockroachdb) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database introspection](/orm/prisma-schema/introspection) +- [Prisma Migrate](/orm/prisma-migrate) diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx new file mode 100644 index 0000000000..7fc993a4c7 --- /dev/null +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx @@ -0,0 +1,308 @@ +--- +title: 'Add Prisma ORM to an existing MongoDB project' +sidebar_title: 'MongoDB' +metaTitle: 'How to add Prisma ORM to an existing project using MongoDB (15 min)' +metaDescription: 'Add Prisma ORM to an existing TypeScript project with MongoDB and learn database introspection and querying.' +sidebar_custom_props: { badge: '15 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[MongoDB](https://www.mongodb.com/) is a popular document-based NoSQL database known for its flexibility, scalability, and developer-friendly features. In this guide, you will learn how to add Prisma ORM to an existing TypeScript project, connect it to MongoDB, introspect your existing database schema, and start querying with type-safe Prisma Client. + +:::tip + +If you're migrating to Prisma ORM from Mongoose, see our [Migrate from Mongoose guide](/guides/migrate-from-mongoose). + +::: + +## Prerequisites + +In order to successfully complete this guide, you need: + +- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) +- An existing TypeScript project with a `package.json` file +- Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). + +:::warning + +The MongoDB database connector uses transactions to support nested writes. Transactions **requires** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. + +::: + +Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! + +:::note + +If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. + +::: + +## 1. Set up Prisma ORM + +Navigate to your existing project directory and install the required dependencies: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`dotenv`** - Loads environment variables from your `.env` file + +:::info + +MongoDB does not require a driver adapter like relational databases. Prisma Client connects directly to MongoDB. + +::: + +## 2. Initialize Prisma ORM + +Set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --datasource-provider mongodb --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection configuration +- Creates a `.env` file in the root directory for environment variables +- Creates a `prisma.config.ts` file for Prisma configuration + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + engine: "classic", + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + engine: "classic", + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "mongodb" +} +``` + +## 3. Connect your database + +Update the `.env` file with your MongoDB connection URL: + +```bash file=.env +DATABASE_URL="mongodb+srv://username:password@cluster.mongodb.net/mydb" +``` + +For MongoDB Atlas, the connection URL format is: + +``` +mongodb+srv://USERNAME:PASSWORD@CLUSTER.mongodb.net/DATABASE +``` + +The [format of the connection URL](/orm/reference/connection-urls) for MongoDB looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): + +``` +mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE +``` + +Here's a short explanation of each component: + +- **`USERNAME`**: The name of your database user +- **`PASSWORD`**: The password for your database user +- **`HOST`**: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running +- **`PORT`**: The port where your database server is running (typically `27017` for MongoDB) +- **`DATABASE`**: The name of the database + +:::tip + +If you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. + +::: + +### Troubleshooting connection issues + +#### `Error in connector: SCRAM failure: Authentication failed.` + +If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. + +#### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` + +If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). + +## 4. Introspect your database + +Run the following command to introspect your existing database: + +```terminal +npx prisma db pull +``` + +This command reads the `DATABASE_URL` environment variable, connects to your database, and introspects the database schema. Prisma ORM introspects a MongoDB schema by sampling the data stored in the database and inferring the schema. + +![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) + +After introspection, your Prisma schema will contain models that represent your existing MongoDB collections. + +:::info + +MongoDB introspection works by sampling documents in your collections. You may need to manually add relation fields using the `@relation` attribute to enable relational queries. + +::: + +## 5. Generate Prisma ORM types + +Generate Prisma Client based on your introspected schema: + +```terminal +npx prisma generate +``` + +This creates a type-safe Prisma Client tailored to your database schema in the `generated/prisma` directory. + +## 6. Instantiate Prisma Client + +Create a utility file to instantiate Prisma Client: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaClient } from '../generated/prisma/client' + +const prisma = new PrismaClient() + +export { prisma } +``` + +## 7. Query your database + +Now you can use Prisma Client to query your database. Create a `script.ts` file: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Example: Fetch all records from a collection + // Replace 'user' with your actual model name + const allUsers = await prisma.user.findMany() + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +## 8. Evolve your schema + +MongoDB does not use migrations. To make changes to your database schema: + +### 8.1. Update your Prisma schema file + +Update your Prisma schema file to reflect the changes you want to make to your database schema. For example, add a new model: + +```prisma file=prisma/schema.prisma +// add-start +model Post { + id String @id @default(auto()) @map("_id") @db.ObjectId + title String + content String? + published Boolean @default(false) + authorId String @db.ObjectId + author User @relation(fields: [authorId], references: [id]) +} + +model User { + id String @id @default(auto()) @map("_id") @db.ObjectId + email String @unique + name String? + posts Post[] +} +// add-end +``` + +:::info + +In MongoDB, the `id` field is mapped to `_id` and uses `@db.ObjectId` type. Relations use `String` type with `@db.ObjectId` annotation. + +::: + +### 8.2. Push the changes to your database: + +```terminal +npx prisma db push +``` + +This command will: +- Apply the schema changes to your MongoDB database +- Regenerate Prisma Client + +:::info + +Prisma Migrate is not supported for MongoDB. Use `prisma db push` to sync your schema changes. + +::: + +## 9. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [MongoDB database connector](/orm/overview/databases/mongodb) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database introspection](/orm/prisma-schema/introspection) diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-cockroachdb.mdx deleted file mode 100644 index c9b8a135e3..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-cockroachdb.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: 'Relational databases (JavaScript and CockroachDB)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using JavaScript and CockroachDB (15 min)' -metaDescription: 'Learn how to create a new Node.js project from scratch by connecting Prisma ORM to your CockroachDB database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - - - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [CockroachDB](https://www.cockroachlabs.com/) database server running - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma --save-dev -``` - -This creates a `package.json` with an initial setup for a Node.js app. - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-mysql.mdx deleted file mode 100644 index b0397ccd45..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-mysql.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: 'Relational databases (JavaScript and MySQL)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using JavaScript and MySQL (15 min)' -metaDescription: 'Learn how to create a new Node.js project from scratch by connecting Prisma ORM to your MySQL database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-mysql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - - - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [MySQL](https://www.mysql.com/) database server running - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma --save-dev -``` - -This creates a `package.json` with an initial setup for a Node.js app. - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-planetscale.mdx deleted file mode 100644 index ec9ef078fe..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-planetscale.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: 'Relational databases (JavaScript and PlanetScale)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using JavaScript and PlanetScale (15 min)' -metaDescription: 'Learn how to create a new Node.js project from scratch by connecting Prisma ORM to your PlanetScale database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-planetscale -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - - - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [PlanetScale](https://planetscale.com/) database server running - - - -This tutorial will also assume that you can push to the `main` branch of your database. Do not do this if your `main` branch has been promoted to production. - - - -Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma --save-dev -``` - -This creates a `package.json` with an initial setup for a Node.js app. - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-postgresql.mdx deleted file mode 100644 index 81fe5d9135..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-postgresql.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: 'Relational databases (JavaScript and PostgreSQL)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using JavaScript and PostgreSQL (15 min)' -metaDescription: 'Learn how to create a new Node.js project from scratch by connecting Prisma ORM to your PostgreSQL database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-postgresql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - - - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [PostgreSQL](https://www.postgresql.org/) database server running - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma --save-dev -``` - -This creates a `package.json` with an initial setup for a Node.js app. - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-sqlserver.mdx deleted file mode 100644 index 92f8f25f9a..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-node-sqlserver.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: 'Relational databases (JavaScript and SQL Server)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using JavaScript and SQL Server (15 min)' -metaDescription: 'Learn how to create a new Node.js project from scratch by connecting Prisma ORM to your SQL Server database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-sqlserver -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - - - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- A [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/?view=sql-server-ver16) database - - [Microsoft SQL Server on Linux for Docker](/orm/overview/databases/sql-server/sql-server-docker) - - [Microsoft SQL Server on Windows (local)](/orm/overview/databases/sql-server/sql-server-local) - - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma --save-dev -``` - -This creates a `package.json` with an initial setup for a Node.js app. - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-cockroachdb.mdx deleted file mode 100644 index ca1f6a19f2..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-cockroachdb.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: 'Relational databases (TypeScript and CockroachDB)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using TypeScript and CockroachDB (15 min)' -metaDescription: 'Learn how to create a new TypeScript project from scratch by connecting Prisma ORM to your CockroachDB database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - - - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [CockroachDB](https://www.cockroachlabs.com/) database server running - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma typescript tsx @types/node --save-dev -``` - -This creates a `package.json` with an initial setup for your TypeScript app. - -Next, initialize TypeScript: - -```terminal copy -npx tsc --init -``` - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-mysql.mdx deleted file mode 100644 index 1c61373522..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-mysql.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: 'Relational databases (TypeScript and MySQL)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using TypeScript and MySQL (15 min)' -metaDescription: 'Learn how to create a new TypeScript project from scratch by connecting Prisma ORM to your MySQL database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-mysql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - - - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [MySQL](https://www.mysql.com/) database server running - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma typescript tsx @types/node --save-dev -``` - -This creates a `package.json` with an initial setup for your TypeScript app. - -Next, initialize TypeScript: - -```terminal copy -npx tsc --init -``` - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-planetscale.mdx deleted file mode 100644 index 5243330350..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-planetscale.mdx +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: 'Relational databases (TypeScript and PlanetScale)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using TypeScript and PlanetScale (15 min)' -metaDescription: 'Learn how to create a new TypeScript project from scratch by connecting Prisma ORM to your PlanetScale database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - - - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [PlanetScale](https://planetscale.com/) database server running - - - -This tutorial will also assume that you can push to the `main` branch of your database. Do not do this if your `main` branch has been promoted to production. - - - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma typescript tsx @types/node --save-dev -``` - -This creates a `package.json` with an initial setup for your TypeScript app. - -Next, initialize TypeScript: - -```terminal copy -npx tsc --init -``` - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-postgresql.mdx deleted file mode 100644 index 18e56a42b5..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-postgresql.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Relational databases (TypeScript and PostgreSQL)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using TypeScript and PostgreSQL (15 min)' -metaDescription: 'Learn how to create a new TypeScript project from scratch by connecting Prisma ORM to your PostgreSQL database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_custom_props: { badge: '15 min' } -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [PostgreSQL](https://www.postgresql.org/) database server running - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma typescript tsx @types/node --save-dev -``` - -This creates a `package.json` with an initial setup for your TypeScript app. - -Next, initialize TypeScript: - -```terminal copy -npx tsc --init -``` - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-prismaPostgres.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-prismaPostgres.mdx deleted file mode 100644 index ed8342b018..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-prismaPostgres.mdx +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: 'Relational databases (TypeScript and Prisma Postgres)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using TypeScript and Prisma Postgres (15 min)' -metaDescription: 'Learn how to create a new TypeScript project from scratch by connecting Prisma ORM to your Prisma Postgres database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-prismaPostgres -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - -Learn how to create a new TypeScript project with a Prisma Postgres database from scratch. This tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate) and covers the following workflows: - -- Creating a TypeScript project on your local machine from scratch -- Creating a [Prisma Postgres](https://www.prisma.io/postgres?utm_source=docs) database -- Schema migrations and queries (via [Prisma ORM](https://www.prisma.io/orm)) -- Connection pooling and caching (via [Prisma Accelerate](https://www.prisma.io/accelerate)) - -## Prerequisites - -To successfully complete this tutorial, you need: -- a [Prisma Data Platform](https://console.prisma.io/) (PDP) account -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - -## Create project setup - -Create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma typescript tsx @types/node --save-dev -``` - -This creates a `package.json` with an initial setup for your TypeScript app. - -Next, initialize TypeScript: - -```terminal copy -npx tsc --init -``` - -You can now invoke the Prisma CLI by prefixing it with `npx`: - -```terminal -npx prisma -``` - -Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: - -```terminal copy -npx prisma init --db --output ../generated/prisma -``` - -This command does a few things: - -- Creates a new directory called `prisma` that contains a file called `schema.prisma`, which contains the Prisma Schema with your database connection variable and schema models. -- Sets the `output` to a custom location. -- Creates a [`.env`](/orm/more/development-environment/environment-variables) file in the root directory of the project, which is used for defining environment variables (such as your database connection and API keys). - -In the next section, you'll learn how to connect your Prisma Postgres database to the project you just created on your file system. \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-sqlserver.mdx deleted file mode 100644 index 2459fa217c..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases-typescript-sqlserver.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: 'Relational databases (TypeScript and SQL Server)' -sidebar_label: 'Relational databases' -metaTitle: 'Start from scratch with Prisma ORM using TypeScript and SQL Server (15 min)' -metaDescription: 'Learn how to create a new TypeScript project from scratch by connecting Prisma ORM to your SQL Server database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases- ---- - - - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- A [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/?view=sql-server-ver16) database - - [Microsoft SQL Server on Linux for Docker](/orm/overview/databases/sql-server/sql-server-docker) - - [Microsoft SQL Server on Windows (local)](/orm/overview/databases/sql-server/sql-server-local) - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma typescript tsx @types/node --save-dev -``` - -This creates a `package.json` with an initial setup for your TypeScript app. - -Next, initialize TypeScript: - -```terminal copy -npx tsc --init -``` - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-cockroachdb.mdx deleted file mode 100644 index de67fb16a7..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-cockroachdb.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: 'Connect your database using JavaScript and CockroachDB' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using JavaScript and CockroachDB' -metaDescription: 'Connect your database to your project using JavaScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-node-cockroachdb -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -The `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`. You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. CockroachDB uses the PostgreSQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -postgresql://USER:PASSWORD@HOST:PORT/DATABASE?PARAMETERS -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running. The default for CockroachDB is `26257`. -- `DATABASE`: The name of the database -- `PARAMETERS`: Any additional connection parameters. See the CockroachDB documentation [here](https://www.cockroachlabs.com/docs/stable/connection-parameters.html#additional-connection-parameters). - -For a [CockroachDB Serverless](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart.html) or [Cockroach Dedicated](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart-trial-cluster) database hosted on [CockroachDB Cloud](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart/), the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="postgresql://:@..cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full&sslrootcert=$HOME/.postgresql/root.crt&options=--" -``` - -To find your connection string on CockroachDB Cloud, click the 'Connect' button on the overview page for your database cluster, and select the 'Connection string' tab. - -For a [CockroachDB database hosted locally](https://www.cockroachlabs.com/docs/stable/secure-a-cluster.html), the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="postgresql://root@localhost:26257?sslmode=disable" -``` - -Your connection string is displayed as part of the welcome text when starting CockroachDB from the command line. diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-mysql.mdx deleted file mode 100644 index 4a01cb0314..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-mysql.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: 'Connect your database using JavaScript and MySQL' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using JavaScript and MySQL' -metaDescription: 'Connect your database to your project using JavaScript and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-node-mysql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-mysql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mysql" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" -``` - - - -We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. - - - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. For MySQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mysql://USER:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running (typically `3306` for MySQL) -- `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) - -As an example, for a MySQL database hosted on AWS RDS, the [connection URL](/orm/reference/connection-urls) might look similar to this: - -```bash file=.env -DATABASE_URL="mysql://johndoe:XXX@mysql–instance1.123456789012.us-east-1.rds.amazonaws.com:3306/mydb" -``` - -When running MySQL locally, your connection URL typically looks similar to this: - -```bash file=.env -DATABASE_URL="mysql://root:randompassword@localhost:3306/mydb" -``` diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-planetscale.mdx deleted file mode 100644 index 85aa2f3447..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-planetscale.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: 'Connect your database using JavaScript and PlanetScale' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using JavaScript and PlanetScale' -metaDescription: 'Connect your database to your project using JavaScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-node-planetscale -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-planetscale -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -You will also need to set the relation mode type to `prisma` in order to [emulate foreign key constraints](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client) in the `datasource` block: - -```prisma file=schema.prisma highlight=4;add showLineNumbers -datasource db { - provider = "mysql" - url = env("DATABASE_URL") - //add-next-line - relationMode = "prisma" -} -``` - -> **Note**: Since February 2024, you can alternatively [use foreign key constraints on a database-level in PlanetScale](/orm/overview/databases/planetscale#option-2-enable-foreign-key-constraints-in-the-planetscale-database-settings), which omits the need for setting `relationMode = "prisma"`. - -The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="mysql://janedoe:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" -``` - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. PlanetScale uses the MySQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mysql://USER:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running (typically `3306` for MySQL) -- `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) - -For a database hosted with PlanetScale, the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="mysql://myusername:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" -``` - -The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' to get the Prisma format for the connection URL. - -
-Alternative method: connecting using the PlanetScale CLI - -Alternatively, you can connect to your PlanetScale database server using the [PlanetScale CLI](https://planetscale.com/docs/concepts/planetscale-environment-setup), and use a local connection URL. In this case the connection URL will look like this: - -```bash file=.env -DATABASE_URL="mysql://root@localhost:PORT/mydb" -``` - - - -We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. - - - -To connect to your branch, use the following command: - -```terminal -pscale connect prisma-test branchname --port PORT -``` - -The `--port` flag can be omitted if you are using the default port `3306`. - -
diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-postgresql.mdx deleted file mode 100644 index 0ca802e8ae..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-postgresql.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: 'Connect your database using JavaScript and PostgreSQL' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using JavaScript and PostgreSQL' -metaDescription: 'Connect your database to your project using JavaScript and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgresql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-postgresql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" -``` - - - -We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. - - - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For PostgreSQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `HOST`: The name of your host name (for the local environment, it is `localhost`) -- `PORT`: The port where your database server is running (typically `5432` for PostgreSQL) -- `DATABASE`: The name of the [database](https://www.postgresql.org/docs/12/manage-ag-overview.html) -- `SCHEMA`: The name of the [schema](https://www.postgresql.org/docs/12/ddl-schemas.html) inside the database - -If you're unsure what to provide for the `schema` parameter for a PostgreSQL connection URL, you can probably omit it. In that case, the default schema name `public` will be used. - -As an example, for a PostgreSQL database hosted on Heroku, the [connection URL](/orm/reference/connection-urls) might look similar to this: - -```bash file=.env -DATABASE_URL="postgresql://opnmyfngbknppm:XXX@ec2-46-137-91-216.eu-west-1.compute.amazonaws.com:5432/d50rgmkqi2ipus?schema=hello-prisma" -``` - -When running PostgreSQL locally on macOS, your user and password as well as the database name _typically_ correspond to the current _user_ of your OS, e.g. assuming the user is called `janedoe`: - -```bash file=.env -DATABASE_URL="postgresql://janedoe:janedoe@localhost:5432/janedoe?schema=hello-prisma" -``` diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-sqlserver.mdx deleted file mode 100644 index 56115cd142..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-node-sqlserver.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: 'Connect your database using JavaScript and SQL Server' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using JavaScript and SQL Server' -metaDescription: 'Connect your database to your project using JavaScript and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-node-sqlserver -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-sqlserver -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "sqlserver" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -The following example connection URL [uses SQL authentication](/orm/overview/databases/sql-server), but there are [other ways to format your connection URL](/orm/overview/databases/sql-server) - -```bash file=.env - DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=r@ndomP@$$w0rd;trustServerCertificate=true" -``` - - - -We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. - - - -Adjust the connection URL to match your setup - see [Microsoft SQL Server connection URL](/orm/overview/databases/sql-server) for more information. - -> Make sure TCP/IP connections are enabled via [SQL Server Configuration Manager](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver16&viewFallbackFrom=sql-server-ver16) to avoid `No connection could be made because the target machine actively refused it. (os error 10061)` - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-cockroachdb.mdx deleted file mode 100644 index f8f76a1f3d..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-cockroachdb.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: 'Connect your database using TypeScript and CockroachDB' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using TypeScript and CockroachDB' -metaDescription: 'Connect your database to your project using TypeScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_class_name: 'hidden-sidebar tech-switch' -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -The `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`. You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. CockroachDB uses the PostgreSQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -postgresql://USER:PASSWORD@HOST:PORT/DATABASE?PARAMETERS -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running. The default for CockroachDB is `26257`. -- `DATABASE`: The name of the database -- `PARAMETERS`: Any additional connection parameters. See the CockroachDB documentation [here](https://www.cockroachlabs.com/docs/stable/connection-parameters.html#additional-connection-parameters). - -For a [CockroachDB Serverless](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart.html) or [Cockroach Dedicated](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart-trial-cluster) database hosted on [CockroachDB Cloud](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart/), the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="postgresql://:@..cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full&sslrootcert=$HOME/.postgresql/root.crt&options=--" -``` - -To find your connection string on CockroachDB Cloud, click the 'Connect' button on the overview page for your database cluster, and select the 'Connection string' tab. - -For a [CockroachDB database hosted locally](https://www.cockroachlabs.com/docs/stable/secure-a-cluster.html), the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="postgresql://root@localhost:26257?sslmode=disable" -``` - -Your connection string is displayed as part of the welcome text when starting CockroachDB from the command line. diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-mysql.mdx deleted file mode 100644 index 9b8f5ae7f6..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-mysql.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: 'Connect your database using TypeScript and MySQL' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using TypeScript and MySQL' -metaDescription: 'Connect your database to your project using TypeScript and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-mysql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-mysql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mysql" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" -``` - - - -We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. - - - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. For MySQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mysql://USER:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running (typically `3306` for MySQL) -- `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) - -As an example, for a MySQL database hosted on AWS RDS, the [connection URL](/orm/reference/connection-urls) might look similar to this: - -```bash file=.env -DATABASE_URL="mysql://johndoe:XXX@mysql–instance1.123456789012.us-east-1.rds.amazonaws.com:3306/mydb" -``` - -When running MySQL locally, your connection URL typically looks similar to this: - -```bash file=.env -DATABASE_URL="mysql://root:randompassword@localhost:3306/mydb" -``` diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-planetscale.mdx deleted file mode 100644 index 408d02ba82..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-planetscale.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: 'Connect your database using TypeScript and PlanetScale' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using TypeScript and PlanetScale' -metaDescription: 'Connect your database to your project using TypeScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-planetscale -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-planetscale -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -You will also need to set the relation mode type to `prisma` in order to [emulate foreign key constraints](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client) in the `datasource` block: - -```prisma file=schema.prisma highlight=4;add showLineNumbers -datasource db { - provider = "mysql" - url = env("DATABASE_URL") - //add-next-line - relationMode = "prisma" -} -``` - -> **Note**: Since February 2024, you can alternatively [use foreign key constraints on a database-level in PlanetScale](/orm/overview/databases/planetscale#option-2-enable-foreign-key-constraints-in-the-planetscale-database-settings), which omits the need for setting `relationMode = "prisma"`. - -The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="mysql://janedoe:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" -``` - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. PlanetScale uses the MySQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mysql://USER:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running (typically `3306` for MySQL) -- `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) - -For a database hosted with PlanetScale, the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="mysql://myusername:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" -``` - -The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' to get the Prisma format for the connection URL. - -
-Alternative method: connecting using the PlanetScale CLI - -Alternatively, you can connect to your PlanetScale database server using the [PlanetScale CLI](https://planetscale.com/docs/concepts/planetscale-environment-setup), and use a local connection URL. In this case the connection URL will look like this: - -```bash file=.env -DATABASE_URL="mysql://root@localhost:PORT/mydb" -``` - - - -We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. - - - -To connect to your branch, use the following command: - -```terminal -pscale connect prisma-test branchname --port PORT -``` - -The `--port` flag can be omitted if you are using the default port `3306`. - -
diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-postgresql.mdx deleted file mode 100644 index 82703b7c19..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-postgresql.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: 'Connect your database using TypeScript and PostgreSQL' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using TypeScript and PostgreSQL' -metaDescription: 'Connect your database to your project using TypeScript and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" -``` - - - -We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. - - - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For PostgreSQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `HOST`: The name of your host name (for the local environment, it is `localhost`) -- `PORT`: The port where your database server is running (typically `5432` for PostgreSQL) -- `DATABASE`: The name of the [database](https://www.postgresql.org/docs/12/manage-ag-overview.html) -- `SCHEMA`: The name of the [schema](https://www.postgresql.org/docs/12/ddl-schemas.html) inside the database - -If you're unsure what to provide for the `schema` parameter for a PostgreSQL connection URL, you can probably omit it. In that case, the default schema name `public` will be used. - -As an example, for a PostgreSQL database hosted on Heroku, the [connection URL](/orm/reference/connection-urls) might look similar to this: - -```bash file=.env -DATABASE_URL="postgresql://opnmyfngbknppm:XXX@ec2-46-137-91-216.eu-west-1.compute.amazonaws.com:5432/d50rgmkqi2ipus?schema=hello-prisma" -``` - -When running PostgreSQL locally on macOS, your user and password as well as the database name _typically_ correspond to the current _user_ of your OS, e.g. assuming the user is called `janedoe`: - -```bash file=.env -DATABASE_URL="postgresql://janedoe:janedoe@localhost:5432/janedoe?schema=hello-prisma" -``` diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-prismaPostgres.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-prismaPostgres.mdx deleted file mode 100644 index cb0fe2f5b5..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-prismaPostgres.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: 'Connect your database using TypeScript and Prisma Postgres' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using TypeScript and Prisma Postgres' -metaDescription: 'Connect your database to your project using TypeScript and Prisma Postgres' -langSwitcher: ['typescript'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_class_name: 'hidden-sidebar tech-switch' -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-prismaPostgres -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-prismaPostgres -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -## Set up a Prisma Postgres database in the PDP Console - -Follow these steps to create your Prisma Postgres database: - -1. Log in to [PDP Console](https://console.prisma.io/). -1. In a [workspace](/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 **Dashboard** where you will need to wait for 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. - -In the Console UI, you'll see a code snippet for a `.env` file with two environment variables defined. - -## Set environment variables in your local project - -Copy the `DATABASE_URL` environment variable from the Console UI and paste it into your `.env` file. Your `.env` file should look similar to this: - -```bash file=.env no-copy -DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=ey..." -``` - -By setting the `DATABASE_URL` in the `.env` file, you're ensuring that Prisma ORM can connect to your database. The `DATABASE_URL` is used in the `datasource` block in your Prisma schema: - -```prisma file=prisma/schema.prisma -datasource db { - provider = "postgresql" - // highlight-next-line - url = env("DATABASE_URL") -} -``` - -That's it! You can now start using the Prisma CLI to interact with your Prisma Postgres database. In the next section, you'll learn how to use the Prisma CLI to create and run migrations against your database to update its schema. \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-sqlserver.mdx deleted file mode 100644 index 2ef9848ae4..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/100-connect-your-database-typescript-sqlserver.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: 'Connect your database using TypeScript and SQL Server' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your database using TypeScript and SQL Server' -metaDescription: 'Connect your database to your project using TypeScript and SQL Server' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-sqlserver -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "sqlserver" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -The following example connection URL [uses SQL authentication](/orm/overview/databases/sql-server), but there are [other ways to format your connection URL](/orm/overview/databases/sql-server) - -```bash file=.env - DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=r@ndomP@$$w0rd;trustServerCertificate=true" -``` - - - -We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. - - - -Adjust the connection URL to match your setup - see [Microsoft SQL Server connection URL](/orm/overview/databases/sql-server) for more information. - -> Make sure TCP/IP connections are enabled via [SQL Server Configuration Manager](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver16&viewFallbackFrom=sql-server-ver16) to avoid `No connection could be made because the target machine actively refused it. (os error 10061)` - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-cockroachdb.mdx deleted file mode 100644 index f39fe32418..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-cockroachdb.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: 'Using Prisma Migrate with JavaScript and CockroachDB' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with JavaScript and CockroachDB' -metaDescription: 'Create database tables with Prisma Migrate using JavaScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-cockroachdb -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma copy showLineNumbers -model Post { - id BigInt @id @default(sequence()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId BigInt -} - -model Profile { - id BigInt @id @default(sequence()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId BigInt @unique -} - -model User { - id BigInt @id @default(sequence()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: - -```terminal -npx prisma migrate dev --name init -``` - -This command does two things: - -1. It creates a new SQL migration file for this migration -1. It runs the SQL migration file against the database - -:::note -`generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. -::: - -Great, you now created three tables in your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-mysql.mdx deleted file mode 100644 index 4d95269b0a..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-mysql.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: 'Using Prisma Migrate with JavaScript and MySQL' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with JavaScript and MySQL' -metaDescription: 'Create database tables with Prisma Migrate using JavaScript and MySQL' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-mysql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-mysql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - - -In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma copy showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String @db.VarChar(255) - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId Int -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId Int @unique -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: - -```terminal -npx prisma migrate dev --name init -``` - -This command does two things: - -1. It creates a new SQL migration file for this migration -1. It runs the SQL migration file against the database - -> **Note**: `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. - -Great, you now created three tables in your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-planetscale.mdx deleted file mode 100644 index d583dd3b63..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-planetscale.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Using Prisma Migrate with JavaScript and PlanetScale' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with JavaScript and PlanetScale' -metaDescription: 'Create database tables with Prisma Migrate using JavaScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-planetscale -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-planetscale -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use Prisma's [`db push` command](/orm/prisma-migrate/workflows/prototyping-your-schema) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma copy showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String @db.VarChar(255) - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId Int - - @@index(authorId) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId Int @unique - - @@index(userId) -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -You are now ready to push your new schema to your database. Connect to your `main` branch using the instructions in [Connect your database](/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale). - -Now use the `db push` CLI command to push to the `main` branch: - -```terminal -npx prisma db push -``` - -Great, you now created three tables in your database with Prisma's `db push` command 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-postgresql.mdx deleted file mode 100644 index 3a5db8a0df..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-postgresql.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: 'Using Prisma Migrate with JavaScript and PostgreSQL' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with JavaScript and PostgreSQL' -metaDescription: 'Create database tables with Prisma Migrate using JavaScript and PostgreSQL' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-postgresql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-postgresql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following data model to your [Prisma schema](/orm/prisma-schema) in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String @db.VarChar(255) - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId Int -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId Int @unique -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: - -```terminal -npx prisma migrate dev --name init -``` - -This command does two things: - -1. It creates a new SQL migration file for this migration -1. It runs the SQL migration file against the database - -:::note -`generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. -::: - -Great, you now created three tables in your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-sqlserver.mdx deleted file mode 100644 index a7446e5dd0..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-node-sqlserver.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 'Using Prisma Migrate with JavaScript and SQL Server' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with JavaScript and SQL Server' -metaDescription: 'Create database tables with Prisma Migrate using JavaScript and SQL Server' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-sqlserver -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-sqlserver -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma copy showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String @db.VarChar(255) - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId Int -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId Int @unique -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: - -```terminal -npx prisma migrate dev --name init -``` - -This command does two things: - -1. It creates a new SQL migration file for this migration -1. It runs the SQL migration file against the database - -> **Note**: `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. - -Great, you now created three tables in your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-cockroachdb.mdx deleted file mode 100644 index 8afec9807f..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-cockroachdb.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: 'Using Prisma Migrate with TypeScript and CockroachDB' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with TypeScript and CockroachDB' -metaDescription: 'Create database tables with Prisma Migrate using TypeScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma copy showLineNumbers -model Post { - id BigInt @id @default(sequence()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId BigInt -} - -model Profile { - id BigInt @id @default(sequence()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId BigInt @unique -} - -model User { - id BigInt @id @default(sequence()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: - -```terminal -npx prisma migrate dev --name init -``` - -This command does two things: - -1. It creates a new SQL migration file for this migration -1. It runs the SQL migration file against the database - -:::note -`generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. -::: - -Great, you now created three tables in your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-mysql.mdx deleted file mode 100644 index c7081afe43..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-mysql.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 'Using Prisma Migrate with TypeScript and MySQL' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with TypeScript and MySQL' -metaDescription: 'Create database tables with Prisma Migrate using TypeScript and MySQL' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-mysql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-mysql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma copy showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String @db.VarChar(255) - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId Int -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId Int @unique -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: - -```terminal -npx prisma migrate dev --name init -``` - -This command does two things: - -1. It creates a new SQL migration file for this migration -1. It runs the SQL migration file against the database - -> **Note**: `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. - -Great, you now created three tables in your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-planetscale.mdx deleted file mode 100644 index 14af90d1ee..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-planetscale.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Using Prisma Migrate with TypeScript and PlanetScale' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with TypeScript and PlanetScale' -metaDescription: 'Create database tables with Prisma Migrate using TypeScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-planetscale -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use Prisma's [`db push` command](/orm/prisma-migrate/workflows/prototyping-your-schema) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma copy showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String @db.VarChar(255) - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId Int - - @@index(authorId) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId Int @unique - - @@index(userId) -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -You are now ready to push your new schema to your database. Connect to your `main` branch using the instructions in [Connect your database](/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale). - -Now use the `db push` CLI command to push to the `main` branch: - -```terminal -npx prisma db push -``` - -Great, you now created three tables in your database with Prisma's `db push` command 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-postgresql.mdx deleted file mode 100644 index 9591d0517e..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-postgresql.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: 'Using Prisma Migrate with TypeScript and PostgreSQL' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with TypeScript and PostgreSQL' -metaDescription: 'Create database tables with Prisma Migrate using TypeScript and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-postgresql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following data model to your [Prisma schema](/orm/prisma-schema) in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String @db.VarChar(255) - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId Int -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId Int @unique -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: - -```terminal -npx prisma migrate dev --name init -``` - -This command does two things: - -1. It creates a new SQL migration file for this migration -1. It runs the SQL migration file against the database - -:::note -`generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. -::: - -Great, you now created three tables in your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-prismaPostgres.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-prismaPostgres.mdx deleted file mode 100644 index 350b89cfdb..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-prismaPostgres.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: 'Using Prisma Migrate with TypeScript and Prisma Postgres' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with TypeScript and Prisma Postgres' -metaDescription: 'Create database tables with Prisma Migrate using TypeScript and Prisma Postgres' -langSwitcher: ['typescript'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-prismaPostgres -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-prismaPostgres -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. - -To do so, first add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma copy -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 -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId Int @unique -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -This data model defines three [models](/orm/prisma-schema/data-model/models) (which will be mapped to _tables_ in the underlying database): -- `Post` -- `Profile` -- `User` - -It also defines two [relations](/orm/prisma-schema/data-model/relations): -- A one-to-many relation between `User` and `Post` (i.e. "_one_ user can have _many_ posts") -- A one-to-one relation between `User` and `Profile` (i.e. "_one_ user can have _one_ profile") - -To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: - -```terminal -npx prisma migrate dev --name init -``` - -This command did two things: - -1. It generated a new SQL migration file for this migration -1. It ran the SQL migration file against the database - -You can inspect the generated SQL migration file in the newly created `prisma/migrations` directory. - -:::tip Explore your database in Prisma Studio - -[Prisma Studio](/orm/tools/prisma-studio) is a visual editor for your database. You can open it with the following command in your terminal: - -``` -npx prisma studio -``` - -Since you just created the database, you won't see any records but you can take a look at the empty `User`, `Post` and `Profile` tables. - -::: - -Great, you now created three tables in your database with Prisma Migrate. In the next section, you'll learn how to install Prisma Client which lets you send queries to your database from your TypeScript app. diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-sqlserver.mdx deleted file mode 100644 index ee06eeffae..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/150-using-prisma-migrate-typescript-sqlserver.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 'Using Prisma Migrate with TypeScript and SQL Server' -sidebar_label: 'Using Prisma Migrate' -metaTitle: 'Using Prisma Migrate with TypeScript and SQL Server' -metaDescription: 'Create database tables with Prisma Migrate using TypeScript and SQL Server' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-sqlserver -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate- ---- - -## Creating the database schema - -In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: - -```prisma file=prisma/schema.prisma copy showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String @db.VarChar(255) - content String? - published Boolean @default(false) - author User @relation(fields: [authorId], references: [id]) - authorId Int -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - user User @relation(fields: [userId], references: [id]) - userId Int @unique -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] - profile Profile? -} -``` - -To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: - -```terminal -npx prisma migrate dev --name init -``` - -This command does two things: - -1. It creates a new SQL migration file for this migration -1. It runs the SQL migration file against the database - -> **Note**: `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. - -Great, you now created three tables in your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-cockroachdb.mdx deleted file mode 100644 index 751ae30729..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-cockroachdb.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client (JavaScript and CockroachDB)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: JavaScript and CockroachDB' -metaDescription: 'Install and generate Prisma Client in your project using JavaScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-cockroachdb -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-mysql.mdx deleted file mode 100644 index 2de9870bd7..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-mysql.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client (JavaScript and MySQL)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: JavaScript and MySQL' -metaDescription: 'Install and generate Prisma Client in your project using JavaScript and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-mysql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-mysql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-planetscale.mdx deleted file mode 100644 index 5caaba1e29..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-planetscale.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client (JavaScript and PlanetScale)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: JavaScript and PlanetScale' -metaDescription: 'Install and generate Prisma Client in your project using JavaScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-planetscale -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-planetscale -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-postgresql.mdx deleted file mode 100644 index 8be8bd1b6a..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-postgresql.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client (JavaScript and PostgreSQL)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: JavaScript and PostgreSQL' -metaDescription: 'Install and generate Prisma Client in your project using JavaScript and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-postgresql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-postgresql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-sqlserver.mdx deleted file mode 100644 index f68348bd8e..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-node-sqlserver.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client (JavaScript and SQL Server)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: JavaScript and SQL Server' -metaDescription: 'Install and generate Prisma Client in your project using JavaScript and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-sqlserver -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-sqlserver -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-cockroachdb.mdx deleted file mode 100644 index ee8904442b..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-cockroachdb.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client (TypeScript and CockroachDB)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: TypeScript and CockroachDB' -metaDescription: 'Install and generate Prisma Client in your project using TypeScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-mysql.mdx deleted file mode 100644 index 9f4f57e82e..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-mysql.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client (TypeScript and MySQL)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: TypeScript and MySQL' -metaDescription: 'Install and generate Prisma Client in your project using TypeScript and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-mysql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-mysql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-planetscale.mdx deleted file mode 100644 index cc8361c41b..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-planetscale.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client (TypeScript and PlanetScale)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: TypeScript and PlanetScale' -metaDescription: 'Install and generate Prisma Client in your project using TypeScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-planetscale -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-planetscale -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-postgresql.mdx deleted file mode 100644 index a8b37611ee..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-postgresql.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: 'Install Prisma Client (TypeScript and PostgreSQL)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: TypeScript and PostgreSQL' -metaDescription: 'Install and generate Prisma Client in your project using TypeScript and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgresql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - - -These commands serve different purposes in managing your database schema with Prisma. Here’s a breakdown of when and why to use each: - -#### `npx prisma migrate dev` - -- **Purpose:** This command generates and applies a new migration based on your Prisma schema changes. It creates migration files that keep a history of changes. -- **Use Case:** Use this when you want to maintain a record of database changes, which is essential for production environments or when working in teams. It allows for version control of your database schema. -- **Benefits:** This command also includes checks for applying migrations in a controlled manner, ensuring data integrity. - - -#### `npx prisma db push` - -- **Purpose:** This command is used to push your current Prisma schema to the database directly. It applies any changes you've made to your schema without creating migration files. -- **Use Case:** It’s particularly useful during the development phase when you want to quickly sync your database schema with your Prisma schema without worrying about migration history. -- **Caution:** It can overwrite data if your schema changes affect existing tables or columns, so it’s best for early-stage development or prototyping. - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-prismaPostgres.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-prismaPostgres.mdx deleted file mode 100644 index cd152cec57..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-prismaPostgres.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: 'Install Prisma Client (TypeScript and Prisma Postgres)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: TypeScript and Prisma Postgres' -metaDescription: 'Install and generate Prisma Client in your project using TypeScript and Prisma Postgres' -langSwitcher: ['typescript'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-prismaPostgres -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-prismaPostgres -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - - -## Install the Prisma Accelerate extension - -Since Prisma Postgres provides a connection pool and (optional) caching layer with Prisma Accelerate, you need to install the Accelerate [Client extension](/orm/prisma-client/client-extensions) in your project as well: - -``` -npm install @prisma/extension-accelerate -``` - -With that you're all set to read and write data in your database. Move on to the next page to start querying your Prisma Postgres database using Prisma Client. - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-sqlserver.mdx deleted file mode 100644 index c92dbcf171..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/200-install-prisma-client-typescript-sqlserver.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client (TypeScript and SQL Server)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: TypeScript and SQL Server' -metaDescription: 'Install and generate Prisma Client in your project using TypeScript and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-sqlserver -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-cockroachdb.mdx deleted file mode 100644 index da47ee46b7..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-cockroachdb.mdx +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: 'Querying the database using JavaScript and CockroachDB' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using JavaScript and CockroachDB' -metaDescription: 'Write data to and query the database using JavaScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-cockroachdb -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js copy showLineNumbers -const { PrismaClient } = require('./generated/prisma') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```js file=index.js highlight=2;delete|3,4;add showLineNumbers -async function main() { - //delete-next-line - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-mysql.mdx deleted file mode 100644 index 93e81725bc..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-mysql.mdx +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: 'Querying the database using JavaScript and MySQL' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using JavaScript and MySQL' -metaDescription: 'Write data to and query the database using JavaScript and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-mysql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js copy showLineNumbers -const { PrismaClient } = require('./generated/prisma') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```js file=index.js highlight=2;delete|3,4; showLineNumbers -async function main() { - //delete-next-line - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-planetscale.mdx deleted file mode 100644 index 6a8bec5c58..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-planetscale.mdx +++ /dev/null @@ -1,206 +0,0 @@ ---- -title: 'Querying the database using JavaScript and PlanetScale' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using JavaScript and PlanetScale' -metaDescription: 'Write data to and query the database using JavaScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-planetscale -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js copy showLineNumbers -const { PrismaClient } = require('./generated/prisma') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```js file=index.js highlight=2;delete|3,4;add showLineNumbers -async function main() { - //delete-next-line - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - - -```js file=index.js copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-postgresql.mdx deleted file mode 100644 index 5f16c8481c..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-postgresql.mdx +++ /dev/null @@ -1,206 +0,0 @@ ---- -title: 'Querying the database using JavaScript and PostgreSQL' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using JavaScript and PostgreSQL' -metaDescription: 'Write data to and query the database using JavaScript and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-postgresql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js copy showLineNumbers -const { PrismaClient } = require('./generated/prisma') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import `PrismaClient` from the `output` directory specified in the `prisma init` command. -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - - -```js file=index.js highlight=2;delete|3,4;add showLineNumbers -async function main() { - //delete-next-line - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-sqlserver.mdx deleted file mode 100644 index 1fe0350537..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-node-sqlserver.mdx +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: 'Querying the database using JavaScript and SQL Server' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using JavaScript and SQL Server' -metaDescription: 'Write data to and query the database using JavaScript and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-sqlserver -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js copy showLineNumbers -const { PrismaClient } = require('./generated/prisma') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```js file=index.js highlight=2;delete|3,4;add showLineNumbers -async function main() { - //delete-next-line - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-cockroachdb.mdx deleted file mode 100644 index 381a3319f1..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-cockroachdb.mdx +++ /dev/null @@ -1,220 +0,0 @@ ---- -title: 'Querying the database using TypeScript and CockroachDB' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using TypeScript and CockroachDB' -metaDescription: 'Write data to and query the database using TypeScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.ts` and add the following code to it: - -```js file=index.ts copy showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts highlight=3,4;add showLineNumbers -async function main() { - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: - -```ts no-lines -const allUsers: (User & { - posts: Post[] -})[] - -export type Post = { - id: number - title: string - content: string | null - published: boolean - authorId: number | null -} -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -npx tsx index.ts -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-mysql.mdx deleted file mode 100644 index ee929e9772..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-mysql.mdx +++ /dev/null @@ -1,220 +0,0 @@ ---- -title: 'Querying the database using TypeScript and MySQL' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using TypeScript and MySQL' -metaDescription: 'Write data to and query the database using TypeScript and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-mysql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.ts` and add the following code to it: - -```js file=index.ts copy showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts highlight=3,4;add showLineNumbers -async function main() { - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: - -```ts no-lines -const allUsers: (User & { - posts: Post[] -})[] - -export type Post = { - id: number - title: string - content: string | null - published: boolean - authorId: number | null -} -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -npx tsx index.ts -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-planetscale.mdx deleted file mode 100644 index b28afc292d..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-planetscale.mdx +++ /dev/null @@ -1,221 +0,0 @@ ---- -title: 'Querying the database using TypeScript and PlanetScale' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using TypeScript and PlanetScale' -metaDescription: 'Write data to and query the database using TypeScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-planetscale -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.ts` and add the following code to it: - -```js file=index.ts copy showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts highlight=3,4;add showLineNumbers -async function main() { - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: - -```ts no-lines -const allUsers: (User & { - posts: Post[] -})[] - -export type Post = { - id: number - title: string - content: string | null - published: boolean - authorId: number | null -} -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -npx tsx index.ts -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-postgresql.mdx deleted file mode 100644 index 2765dd3411..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-postgresql.mdx +++ /dev/null @@ -1,219 +0,0 @@ ---- -title: 'Querying the database using TypeScript and PostgreSQL' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using TypeScript and PostgreSQL' -metaDescription: 'Write data to and query the database using TypeScript and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.ts` and add the following code to it: - -```js file=index.ts copy showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import PrismaClient from output folder specified in [`prisma init`](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-prismaPostgres) command. -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts highlight=3,4;add showLineNumbers -async function main() { - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: - -```ts no-lines -const allUsers: (User & { - posts: Post[] -})[] - -export type Post = { - id: number - title: string - content: string | null - published: boolean - authorId: number | null -} -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -npx tsx index.ts -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-prismaPostgres.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-prismaPostgres.mdx deleted file mode 100644 index cd0f4852f5..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-prismaPostgres.mdx +++ /dev/null @@ -1,243 +0,0 @@ ---- -title: 'Querying the database using TypeScript and Prisma Postgres' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using TypeScript and Prisma Postgres' -metaDescription: 'Write data to and query the database using TypeScript and Prisma Postgres' -langSwitcher: ['typescript'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-prismaPostgres -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain TypeScript script to explore some basic features of Prisma Client. - -Create a new file named `queries.ts` and add the following code to it: - -```js file=queries.ts copy -// 1 -import { PrismaClient } from './generated/prisma' -import { withAccelerate } from '@prisma/extension-accelerate' - -// 2 -const prisma = new PrismaClient() - .$extends(withAccelerate()) - -// 3 -async function main() { - // ... you will write your Prisma Client queries here -} - -// 4 -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - // 5 - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor and the `withAccelerate` extension. -1. Instantiate `PrismaClient` and add the Accelerate extension. -1. Define an `async` function named `main` to send queries to the database. -1. Call the `main` function. -1. Close the database connections when the script terminates. - -Inside the `main` function, add the following query to read all `User` records from the database and log the result: - -```ts file=queries.ts -async function main() { - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -npx tsx queries.ts -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). - -In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Profile` tables all at once. - -Adjust the `main` function by removing the code from before and adding the following: - -```ts file=queries.ts highlight=2-21;add copy -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. - -The records are connected via the [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) that you defined in your Prisma schema. - -Notice that you're also passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -npx tsx queries.ts -``` - -The output should look similar to this: - -```js no-copy showLineNumbers -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -Also note that the `allUsers` variable is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: - -```ts no-copy showLineNumbers -const allUsers: ({ - posts: { - id: number; - createdAt: Date; - updatedAt: Date; - title: string; - content: string | null; - published: boolean; - authorId: number; - }[]; - profile: { - id: number; - bio: string | null; - userId: number; - } | null; -} & { - ...; -})[] -``` - -
-Expand for a visual view of the records that have been created - - -The query added new records to the `User`, `Post`, and `Profile` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -
- -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=queries.ts copy -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -npx tsx queries.ts -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Congratulations! You've now learned how to query a Prisma Postgres database with Prisma Client in your application. If you got lost along the way, want to learn about more queries or explore the caching feature of Prisma Accelerate, check out the comprehensive [Prisma starter template](https://github.com/prisma/prisma-examples/tree/latest/databases/prisma-postgres). \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-sqlserver.mdx deleted file mode 100644 index 3fd7f12046..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/250-querying-the-database-typescript-sqlserver.mdx +++ /dev/null @@ -1,222 +0,0 @@ ---- -title: 'Querying the database using TypeScript and SQL Server' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database using TypeScript and SQL Server' -metaDescription: 'Write data to and query the database using TypeScript and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb', 'prismaPostgres'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-sqlserver -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.ts` and add the following code to it: - -```js file=index.ts copy showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts highlight=3,4;add showLineNumbers -async function main() { - // ... you will write your Prisma Client queries here - //add-start - const allUsers = await prisma.user.findMany() - console.log(allUsers) - //add-end -} -``` - -Now run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -The output should look similar to this: - -```js no-lines -[ - { - email: 'alice@prisma.io', - id: 1, - name: 'Alice', - posts: [ - { - content: null, - createdAt: 2020-03-21T16:45:01.246Z, - updatedAt: 2020-03-21T16:45:01.246Z, - id: 1, - published: false, - title: 'Hello World', - authorId: 1, - } - ], - profile: { - bio: 'I like turtles', - id: 1, - userId: 1, - } - } -] -``` - -Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: - -```ts no-lines -const allUsers: (User & { - posts: Post[] -})[] - -export type Post = { - id: number - title: string - content: string | null - published: boolean - authorId: number | null -} -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :----- | :------------------ | :-------- | -| `1` | `"alice@prisma.io"` | `"Alice"` | - -**Post** - -| **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | -| :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | -| `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | - -**Profile** - -| **id** | **bio** | **userId** | -| :----- | :----------------- | :--------- | -| `1` | `"I like turtles"` | `1` | - -> **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts copy showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -npx tsx index.ts -``` - -You will see the following output: - -```js no-lines -{ - id: 1, - title: 'Hello World', - content: null, - published: true, - authorId: 1 -} -``` - -The `Post` record with an `id` of `1` now got updated in the database: - -**Post** - -| **id** | **title** | **content** | **published** | **authorId** | -| :----- | :-------------- | :---------- | :------------ | :----------- | -| `1` | `"Hello World"` | `null` | `true` | `1` | - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/300-next-steps.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/300-next-steps.mdx deleted file mode 100644 index a8cae6ef57..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/300-next-steps.mdx +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: 'Next steps with Prisma ORM and your relational database' -sidebar_label: 'Next steps' -metaTitle: 'Next steps after setting up Prisma ORM with your relational database' -metaDescription: 'Next steps to take now that you have successfully added Prisma ORM to your new TypeScript or JavaScript project' -hide_table_of_contents: true ---- - -This section lists a number of potential next steps you can now take from here. Feel free to explore these or read the [Introduction](/orm/overview/introduction/what-is-prisma) page to get a high-level overview of Prisma ORM. - -### Continue exploring the Prisma Client API - -You can send a variety of queries with the Prisma Client API. Check out the [API reference](/orm/prisma-client) and use your existing database setup from this guide to try them out. - -:::tip - -You can use your editor's auto-completion feature to learn about the different API calls and the arguments it takes. Auto-completion is commonly invoked by hitting CTRL+SPACE on your keyboard. - -::: - -
-Expand for more Prisma Client API examples - -Here are a few suggestions for a number of more queries you can send with Prisma Client: - -**Filter all `Post` records that contain `"hello"`** - -```js -const filteredPosts = await prisma.post.findMany({ - where: { - OR: [{ title: { contains: 'hello' } }, { content: { contains: 'hello' } }], - }, -}) -``` - -**Create a new `Post` record and connect it to an existing `User` record** - -```js -const post = await prisma.post.create({ - data: { - title: 'Join us for Prisma Day 2020', - author: { - connect: { email: 'alice@prisma.io' }, - }, - }, -}) -``` - -**Use the fluent relations API to retrieve the `Post` records of a `User` by traversing the relations** - -```js -const posts = await prisma.profile - .findUnique({ - where: { id: 1 }, - }) - .user() - .posts() -``` - -**Delete a `User` record** - -```js -const deletedUser = await prisma.user.delete({ - where: { email: 'sarah@prisma.io' }, -}) -``` - -
- -### Build an app with Prisma ORM - -The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - -- [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) -- [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) -- [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) - -### Explore the data in Prisma Studio - -Prisma Studio is a visual editor for the data in your database. Run `npx prisma studio` in your terminal. - -If you are using [Prisma Postgres](https://www.prisma.io/postgres), you can also directly use Prisma Studio inside the [Console](https://console.prisma.io) by selecting the **Studio** tab in your project. - -### Get query insights and analytics with Prisma Optimize - -[Prisma Optimize](/optimize) helps you generate insights and provides recommendations that can help you make your database queries faster. [Try it out now!](/optimize/getting-started) - -Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. - -### Try a Prisma ORM example - -The [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository contains a number of ready-to-run examples: - -| Demo | Stack | Description | -| :------------------------------------------------------------------------------------------------------------------ | :----------- | --------------------------------------------------------------------------------------------------- | -| [`nextjs`](https://pris.ly/e/orm/nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app | -| [`nextjs-graphql`](https://pris.ly/e/ts/graphql-nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app (React) with a GraphQL API | -| [`graphql-nexus`](https://pris.ly/e/ts/graphql-nexus) | Backend only | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) | -| [`express`](https://pris.ly/e/ts/rest-express) | Backend only | Simple REST API with Express.JS | -| [`grpc`](https://pris.ly/e/ts/grpc) | Backend only | Simple gRPC API | diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/_install-prisma-client-partial.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/_install-prisma-client-partial.mdx deleted file mode 100644 index 2bf6ab6d15..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases/_install-prisma-client-partial.mdx +++ /dev/null @@ -1,25 +0,0 @@ -## Install and generate Prisma Client - -To get started with Prisma Client, first install the `@prisma/client` package: - -```terminal copy -npm install @prisma/client -``` - -Then, run `prisma generate` which reads your Prisma schema and generates the Prisma Client. - -```terminal copy -npx prisma generate -``` - -You can now import the `PrismaClient` constructor from the `@prisma/client` package to create an instance of Prisma Client to send queries to your database. You'll learn how to do that in the next section. - -:::note Good to know - -When you run `prisma generate`, you are actually creating code (TypeScript types, methods, queries, ...) that is tailored to _your_ Prisma schema file or files in the `prisma` directory. This means, that whenever you make changes to your Prisma schema file, you also need to update the Prisma Client. You can do this by running the `prisma generate` command. - -![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) - -Whenever you update your Prisma schema, you will have to update your database schema using either `prisma migrate dev` or `prisma db push`. This will keep your database schema in sync with your Prisma schema. These commands will also run `prisma generate` under the hood to re-generate your Prisma Client. - -::: diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb-node-mongodb.mdx deleted file mode 100644 index 13a23e4d08..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb-node-mongodb.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: 'Start from scratch with Prisma ORM using MongoDB and JavaScript' -sidebar_label: 'MongoDB' -metaTitle: 'Start from scratch with Prisma ORM using MongoDB and JavaScript (15 min)' -metaDescription: 'Learn how to create a new Node.js project from scratch by connecting Prisma ORM to your MongoDB database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database-node-mongodb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb- ---- - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your MongoDB database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli) and [Prisma Client](/orm/prisma-client). - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). - - - - The MongoDB database connector uses transactions to support nested writes. Transactions **require** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. - - - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma --save-dev -``` - -This creates a `package.json` with an initial setup for a Node.js app. - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb-typescript-mongodb.mdx deleted file mode 100644 index ed401e69f4..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb-typescript-mongodb.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Start from scratch with Prisma ORM using MongoDB and TypeScript' -sidebar_label: 'MongoDB' -metaTitle: 'Start from scratch with Prisma ORM using MongoDB and TypeScript (15 min)' -metaDescription: 'Learn how to create a new TypeScript project from scratch by connecting Prisma ORM to your MongoDB database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -sidebar_custom_props: { badge: '15 min' } -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database-typescript-mongodb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb- ---- - -Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your MongoDB database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli) and [Prisma Client](/orm/prisma-client). - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). - - - - The MongoDB database connector uses transactions to support nested writes. Transactions **require** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. - - - -Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -## Create project setup - -As a first step, create a project directory and navigate into it: - -```terminal copy -mkdir hello-prisma -cd hello-prisma -``` - -Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: - -```terminal copy -npm init -y -npm install prisma typescript tsx @types/node --save-dev -``` - -This creates a `package.json` with an initial setup for your TypeScript app. - -Next, initialize TypeScript: - -```terminal copy -npx tsc --init -``` - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/100-connect-your-database-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/100-connect-your-database-node-mongodb.mdx deleted file mode 100644 index c0af956fcc..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/100-connect-your-database-node-mongodb.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: 'Connect your database using JavaScript and MongoDB' -sidebar_label: 'Connect your database (MongoDB)' -metaTitle: 'Connect your database using JavaScript and MongoDB' -metaDescription: 'Connect your database to your project using JavaScript and MongoDB' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -toc: false -pagination_prev: getting-started/setup-prisma/start-from-scratch/mongodb-node-mongodb -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema-node-mongodb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env` (the example uses a [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) URL): - -```bash file=.env showLineNumbers -DATABASE_URL="mongodb+srv://test:test@cluster0.ns1yp.mongodb.net/myFirstDatabase" -``` - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For MongoDB, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USERNAME`: The name of your database user -- `PASSWORD`: The password for your database user -- `HOST`: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running -- `PORT`: The port where your database server is running (typically `27017` for MongoDB) -- `DATABASE`: The name of the database. Note that if you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. - -## Troubleshooting - -### `Error in connector: SCRAM failure: Authentication failed.` - -If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. - -### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` - -If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/100-connect-your-database-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/100-connect-your-database-typescript-mongodb.mdx deleted file mode 100644 index 82c326862a..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/100-connect-your-database-typescript-mongodb.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: 'Connect your database using TypeScript and MongoDB' -sidebar_label: 'Connect your database (MongoDB)' -metaTitle: 'Connect your database using TypeScript and MongoDB' -metaDescription: 'Connect your database to your project using TypeScript and MongoDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema-typescript-mongodb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env` (the example uses a [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) URL): - -```bash file=.env showLineNumbers -DATABASE_URL="mongodb+srv://test:test@cluster0.ns1yp.mongodb.net/myFirstDatabase" -``` - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For MongoDB, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USERNAME`: The name of your database user -- `PASSWORD`: The password for your database user -- `HOST`: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running -- `PORT`: The port where your database server is running (typically `27017` for MongoDB) -- `DATABASE`: The name of the database. Note that if you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. - -## Troubleshooting - -### `Error in connector: SCRAM failure: Authentication failed.` - -If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. - -### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` - -If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/125-creating-the-prisma-schema-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/125-creating-the-prisma-schema-node-mongodb.mdx deleted file mode 100644 index a2bd0d3782..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/125-creating-the-prisma-schema-node-mongodb.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: 'Creating the Prisma schema using JavaScript and MongoDB' -sidebar_label: 'Creating the Prisma schema' -metaTitle: 'Creating the Prisma schema using JavaScript and MongoDB' -metaDescription: 'Update the Prisma schema for MongoDB with JavaScript' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database-node-mongodb -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client-node-mongodb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema- ---- - - -## Update the Prisma schema - -Open the `prisma/schema.prisma` file and replace the default contents with the following: - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} - -model Post { - id String @id @default(auto()) @map("_id") @db.ObjectId - slug String @unique - title String - body String - author User @relation(fields: [authorId], references: [id]) - authorId String @db.ObjectId - comments Comment[] -} - -model User { - id String @id @default(auto()) @map("_id") @db.ObjectId - email String @unique - name String? - address Address? - posts Post[] -} - -model Comment { - id String @id @default(auto()) @map("_id") @db.ObjectId - comment String - post Post @relation(fields: [postId], references: [id]) - postId String @db.ObjectId -} - -// Address is an embedded document -type Address { - street String - city String - state String - zip String -} -``` - -There are also a number of subtle differences in how the schema is setup when compared to relational databases like PostgreSQL. - -For example, the underlying `ID` field name is always `_id` and must be mapped with `@map("_id")`. - -For more information check out the [MongoDB schema reference](/orm/reference/prisma-schema-reference#mongodb-2). diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/125-creating-the-prisma-schema-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/125-creating-the-prisma-schema-typescript-mongodb.mdx deleted file mode 100644 index fc255f746b..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/125-creating-the-prisma-schema-typescript-mongodb.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: 'Creating the Prisma schema using TypeScript and MongoDB' -sidebar_label: 'Creating the Prisma schema' -metaTitle: 'Creating the Prisma schema using TypeScript and MongoDB' -metaDescription: 'Update the Prisma schema for MongoDB with TypeScript' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database-typescript-mongodb -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client-typescript-mongodb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema- ---- - -## Update the Prisma schema - -Open the `prisma/schema.prisma` file and replace the default contents with the following: - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} - -model Post { - id String @id @default(auto()) @map("_id") @db.ObjectId - slug String @unique - title String - body String - author User @relation(fields: [authorId], references: [id]) - authorId String @db.ObjectId - comments Comment[] -} - -model User { - id String @id @default(auto()) @map("_id") @db.ObjectId - email String @unique - name String? - address Address? - posts Post[] -} - -model Comment { - id String @id @default(auto()) @map("_id") @db.ObjectId - comment String - post Post @relation(fields: [postId], references: [id]) - postId String @db.ObjectId -} - -// Address is an embedded document -type Address { - street String - city String - state String - zip String -} -``` - -There are also a number of subtle differences in how the schema is setup when compared to relational databases like PostgreSQL. - -For example, the underlying `ID` field name is always `_id` and must be mapped with `@map("_id")`. - -For more information check out the [MongoDB schema reference](/orm/reference/prisma-schema-reference#mongodb-2). - diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/200-install-prisma-client-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/200-install-prisma-client-node-mongodb.mdx deleted file mode 100644 index 85dd430ade..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/200-install-prisma-client-node-mongodb.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: 'Install Prisma Client (JavaScript and MongoDB)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: JavaScript and MongoDB' -metaDescription: 'Install and generate Prisma Client in your project using JavaScript and MongoDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema-node-mongodb -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/querying-the-database-node-mongodb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client- ---- - -## Install and generate Prisma Client - -To get started with Prisma Client, you need to install the `@prisma/client` package: - -```terminal copy -npm install @prisma/client -``` - -Then, run `prisma generate` which reads your Prisma schema and generates the Prisma Client. - -```terminal copy -npx prisma generate -``` - -![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) - -Whenever you update your Prisma schema, you will need to run the `prisma db push` command to create new indexes and regenerate Prisma Client. diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/200-install-prisma-client-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/200-install-prisma-client-typescript-mongodb.mdx deleted file mode 100644 index 1d1217095c..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/200-install-prisma-client-typescript-mongodb.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: 'Install Prisma Client (TypeScript and MongoDB)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client: TypeScript and MongoDB' -metaDescription: 'Install and generate Prisma Client in your project using TypeScript and MongoDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema-typescript-mongodb -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/querying-the-database-typescript-mongodb -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client- ---- - -## Install and generate Prisma Client - -To get started with Prisma Client, you need to install the `@prisma/client` package: - -```terminal copy -npm install @prisma/client -``` - -Then, run `prisma generate` which reads your Prisma schema and generates the Prisma Client. - -```terminal copy -npx prisma generate -``` - -![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) - -Whenever you update your Prisma schema, you will need to run the `prisma db push` command to create new indexes and regenerate Prisma Client. diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/250-querying-the-database-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/250-querying-the-database-node-mongodb.mdx deleted file mode 100644 index 3e3afcb5db..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/250-querying-the-database-node-mongodb.mdx +++ /dev/null @@ -1,217 +0,0 @@ ---- -title: 'Querying the database using JavaScript and MongoDB' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database with JavaScript and MongoDB' -metaDescription: 'Write data to and query the database using JavaScript and MongoDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client-node-mongodb -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js copy showLineNumbers -const { PrismaClient } = require('@prisma/client') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Connect to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```js file=index.js -async function main() { - //delete-next-line -- // ... you will write your Prisma Client queries here -//add-start -+ const allUsers = await prisma.user.findMany() -+ console.log(allUsers) -//add-end -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Comment` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Rich', - email: 'hello@prisma.com', - posts: { - create: { - title: 'My first post', - body: 'Lots of really interesting stuff', - slug: 'my-first-post', - }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with a new `Post` using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the other one via the `Post.author` ↔ `User.posts` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -The output should look similar to this: - -```json no-lines -[ - { - id: '60cc9b0e001e3bfd00a6eddf', - email: 'hello@prisma.com', - name: 'Rich', - address: null, - posts: [ - { - id: '60cc9bad005059d6007f45dd', - slug: 'my-first-post', - title: 'My first post', - body: 'Lots of really interesting stuff', - userId: '60cc9b0e001e3bfd00a6eddf', - }, - ], - }, -] -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :------------------------- | :------------------- | :------- | -| `60cc9b0e001e3bfd00a6eddf` | `"hello@prisma.com"` | `"Rich"` | - -**Post** - -| **id** | **createdAt** | **title** | **content** | **published** | **authorId** | -| :------------------------- | :------------------------- | :---------------- | :--------------------------------- | :------------ | :------------------------- | -| `60cc9bad005059d6007f45dd` | `2020-03-21T16:45:01.246Z` | `"My first post"` | `Lots of really interesting stuff` | `false` | `60cc9b0e001e3bfd00a6eddf` | - -> **Note**: The unique IDs in the `authorId` column on `Post` reference the `id` column of the `User` table, meaning the `id` value `60cc9b0e001e3bfd00a6eddf` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll add a couple of comments to the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js copy showLineNumbers -async function main() { - await prisma.post.update({ - where: { - slug: 'my-first-post', - }, - data: { - comments: { - createMany: { - data: [ - { comment: 'Great post!' }, - { comment: "Can't wait to read more!" }, - ], - }, - }, - }, - }) - const posts = await prisma.post.findMany({ - include: { - comments: true, - }, - }) - - console.dir(posts, { depth: Infinity }) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` - -You will see the following output: - -```json no-lines -[ - { - id: '60cc9bad005059d6007f45dd', - slug: 'my-first-post', - title: 'My first post', - body: 'Lots of really interesting stuff', - userId: '60cc9b0e001e3bfd00a6eddf', - comments: [ - { - id: '60cca420008a21d800578793', - postId: '60cca40300af8bf000f6ca99', - comment: 'Great post!', - }, - { - id: '60cca420008a21d800578794', - postId: '60cca40300af8bf000f6ca99', - comment: "Can't wait to try this!", - }, - ], - }, -] -``` - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/250-querying-the-database-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/250-querying-the-database-typescript-mongodb.mdx deleted file mode 100644 index d0e5efac14..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/250-querying-the-database-typescript-mongodb.mdx +++ /dev/null @@ -1,230 +0,0 @@ ---- -title: 'Querying the database using TypeScript and MongoDB' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database with TypeScript and MongoDB' -metaDescription: 'Write data to and query the database using TypeScript and MongoDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client-typescript-mongodb -pagination_next: getting-started/setup-prisma/start-from-scratch/mongodb/next-steps -slugSwitch: /getting-started/setup-prisma/start-from-scratch/mongodb/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -Create a new file named `index.ts` and add the following code to it: - -```js file=index.ts copy showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .catch(async (e) => { - console.error(e) - process.exit(1) - }) - .finally(async () => { - await prisma.$disconnect() - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Connect to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts showLineNumbers -async function main() { - // ... you will write your Prisma Client queries here -//add-start -+ const allUsers = await prisma.user.findMany() -+ console.log(allUsers) -//add-end -} -``` - -Now run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -This should print an empty array because there are no `User` records in the database yet: - -```json no-lines -[] -``` - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Comment` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts highlight=2-21;add copy showLineNumbers -async function main() { - //add-start - await prisma.user.create({ - data: { - name: 'Rich', - email: 'hello@prisma.com', - posts: { - create: { - title: 'My first post', - body: 'Lots of really interesting stuff', - slug: 'my-first-post', - }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - }, - }) - console.dir(allUsers, { depth: null }) - //add-end -} -``` - -This code creates a new `User` record together with a new `Post` using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the other one via the `Post.author` ↔ `User.posts` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -The output should look similar to this: - -```json no-lines -[ - { - id: '60cc9b0e001e3bfd00a6eddf', - email: 'hello@prisma.com', - name: 'Rich', - address: null, - posts: [ - { - id: '60cc9bad005059d6007f45dd', - slug: 'my-first-post', - title: 'My first post', - body: 'Lots of really interesting stuff', - userId: '60cc9b0e001e3bfd00a6eddf', - }, - ], - }, -] -``` - -Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: - -```ts no-lines -const allUsers: (User & { - posts: Post[] -})[] - -export type Post = { - id: number - title: string - body: string | null - published: boolean - authorId: number | null -} -``` - -The query added new records to the `User` and the `Post` tables: - -**User** - -| **id** | **email** | **name** | -| :------------------------- | :------------------- | :------- | -| `60cc9b0e001e3bfd00a6eddf` | `"hello@prisma.com"` | `"Rich"` | - -**Post** - -| **id** | **createdAt** | **title** | **content** | **published** | **authorId** | -| :------------------------- | :------------------------- | :---------------- | :--------------------------------- | :------------ | :------------------------- | -| `60cc9bad005059d6007f45dd` | `2020-03-21T16:45:01.246Z` | `"My first post"` | `Lots of really interesting stuff` | `false` | `60cc9b0e001e3bfd00a6eddf` | - -> **Note**: The unique IDs in the `authorId` column on `Post` reference the `id` column of the `User` table, meaning the `id` value `60cc9b0e001e3bfd00a6eddf` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll add a couple of comments to the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts copy showLineNumbers -async function main() { - await prisma.post.update({ - where: { - slug: 'my-first-post', - }, - data: { - comments: { - createMany: { - data: [ - { comment: 'Great post!' }, - { comment: "Can't wait to read more!" }, - ], - }, - }, - }, - }) - const posts = await prisma.post.findMany({ - include: { - comments: true, - }, - }) - - console.dir(posts, { depth: Infinity }) -} -``` - -Now run the code using the same command as before: - -```terminal copy -npx tsx index.ts -``` - -You will see the following output: - -```json no-lines -[ - { - id: '60cc9bad005059d6007f45dd', - slug: 'my-first-post', - title: 'My first post', - body: 'Lots of really interesting stuff', - userId: '60cc9b0e001e3bfd00a6eddf', - comments: [ - { - id: '60cca420008a21d800578793', - postId: '60cca40300af8bf000f6ca99', - comment: 'Great post!', - }, - { - id: '60cca420008a21d800578794', - postId: '60cca40300af8bf000f6ca99', - comment: "Can't wait to try this!", - }, - ], - }, -] -``` - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/300-next-steps.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/300-next-steps.mdx deleted file mode 100644 index 37b3d5384d..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb/300-next-steps.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: 'Next steps after setting up Prisma ORM with MongoDB' -sidebar_label: 'Next steps' -metaTitle: 'Next steps after setting up Prisma ORM with MongoDB' -metaDescription: 'Next steps to take now that you have successfully added Prisma ORM to your new JavaScript or TypeScript project' -hide_table_of_contents: true ---- - -This section lists a number of potential next steps you can now take from here. Feel free to explore these or read the [Introduction](/orm/overview/introduction/what-is-prisma) page to get a high-level overview of Prisma ORM. - -### Continue exploring the Prisma Client API - -You can send a variety of queries with the Prisma Client API. Check out the [API reference](/orm/prisma-client) and use your existing database setup from this guide to try them out. - -:::tip - -You can use your editor's auto-completion feature to learn about the different API calls and the arguments it takes. Auto-completion is commonly invoked by hitting CTRL+SPACE on your keyboard. - -::: - -
-Expand for more Prisma Client API examples - -Here are a few suggestions for a number of more queries you can send with Prisma Client: - -**Filter all `Post` records that contain `"hello"`** - -```js -const filteredPosts = await prisma.post.findMany({ - where: { - OR: [{ title: { contains: 'hello' } }, { body: { contains: 'hello' } }], - }, -}) -``` - -**Create a new `Post` record and connect it to an existing `User` record** - -```js -const post = await prisma.post.create({ - data: { - title: 'Join us for Prisma Day 2020', - slug: 'prisma-day-2020', - body: 'A conference on modern application development and databases.', - user: { - connect: { email: 'hello@prisma.com' }, - }, - }, -}) -``` - -**Use the fluent relations API to retrieve the `Post` records of a `User` by traversing the relations** - -```js -const user = await prisma.comment - .findUnique({ - where: { id: '60ff4e9500acc65700ebf470' }, - }) - .post() - .user() -``` - -**Delete a `User` record** - -```js -const deletedUser = await prisma.user.delete({ - where: { email: 'sarah@prisma.io' }, -}) -``` - -
- -### Build an app with Prisma ORM - -The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - -- [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) -- [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) -- [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) - -### Explore the data in Prisma Studio - -Prisma Studio is a visual editor for the data in your database. Run `npx prisma studio` in your terminal. - -### Try a Prisma ORM example - -The [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository contains a number of ready-to-run examples: - -| Demo | Stack | Description | -| :------------------------------------------------------------------------------------------------------------------ | :----------- | --------------------------------------------------------------------------------------------------- | -| [`nextjs`](https://pris.ly/e/orm/nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app | -| [`nextjs-graphql`](https://pris.ly/e/ts/graphql-nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app (React) with a GraphQL API | -| [`graphql-nexus`](https://pris.ly/e/ts/graphql-nexus) | Backend only | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) | -| [`express`](https://pris.ly/e/ts/rest-express) | Backend only | Simple REST API with Express.JS | -| [`grpc`](https://pris.ly/e/ts/grpc) | Backend only | Simple gRPC API | diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/_prisma-init-partial.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/_prisma-init-partial.mdx deleted file mode 100644 index a77182b411..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/_prisma-init-partial.mdx +++ /dev/null @@ -1,27 +0,0 @@ -import CodeBlock from '@theme/CodeBlock'; - -You can now invoke the Prisma CLI by prefixing it with `npx`: - -```terminal -npx prisma -``` - -Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: - -{`npx prisma init --datasource-provider ${props.datasource.toLowerCase()} --output ../generated/prisma`} - -This command does a few things: - -- Creates a new directory called `prisma` that contains a file called `schema.prisma`, which contains the Prisma Schema with your database connection variable and schema models. -- Sets the `datasource` to {props.datasource} and the output to a custom location, respectively. -- Creates the [`.env` file](/orm/more/development-environment/environment-variables) in the root directory of the project, which is used for defining environment variables (such as your database connection) - -Note that the default schema created by `prisma init` uses PostgreSQL as the `provider`. If you didn't specify a provider with the `datasource-provider` option, you need to edit the `datasource` block to use the {props.datasource.toLowerCase()} provider instead: - - -{`datasource db { - //edit-next-line - provider = "${props.datasource.toLowerCase()}" - url = env("DATABASE_URL") -}`} - \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/index.mdx b/content/100-getting-started/02-setup-prisma/100-start-from-scratch/index.mdx deleted file mode 100644 index 455593e360..0000000000 --- a/content/100-getting-started/02-setup-prisma/100-start-from-scratch/index.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: 'Start from scratch' -metaTitle: 'Start from scratch with Prisma ORM' -metaDescription: 'Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database of choice and generating a Prisma Client for database access.' -hide_table_of_contents: true ---- - - - -Start a fresh project from scratch with the following tutorials as they introduce you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - - - -## In this section - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-cockroachdb.mdx deleted file mode 100644 index 8faa0c838f..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-cockroachdb.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing project (JavaScript and CockroachDB)' -sidebar_label: 'Relational databases' -metaTitle: 'Add Prisma ORM to an existing project using JavaScript and CockroachDB (15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing Node.js project by connecting it to your CockroachDB database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - - - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -:::tip - -If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. - -::: - -## Prerequisites - -In order to successfully complete this guide, you need: - -- an existing Node.js project with a `package.json` -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [CockroachDB](https://www.cockroachlabs.com) database server running and a database with at least one table - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Set up Prisma ORM - -As a first step, navigate into your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-mysql.mdx deleted file mode 100644 index 27577e96cf..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-mysql.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing JavaScript project (MySQL)' -sidebar_label: 'Relational databases' -metaTitle: 'Add Prisma ORM to an existing project using JavaScript and MySQL (15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing Node.js project by connecting it to your MySQL database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - - - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -:::tip - -If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. - -::: - -## Prerequisites - -In order to successfully complete this guide, you need: - -- an existing Node.js project with a `package.json` -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [MySQL](https://www.mysql.com/) database server running and a database with at least one table - - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Set up Prisma ORM - -As a first step, navigate into your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-planetscale.mdx deleted file mode 100644 index d1f687604e..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-planetscale.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing JavaScript project (PlanetScale)' -sidebar_label: 'Relational databases' -metaTitle: 'Add Prisma ORM to an existing project using JavaScript and PlanetScale (15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing Node.js project by connecting it to your PlanetScale database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-planetscale -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - - - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -:::tip - -If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. - -::: - -## Prerequisites - -In order to successfully complete this guide, you need: - -- an existing Node.js project with a `package.json` -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [PlanetScale](https://planetscale.com/) database server running and a database with at least one table - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Set up Prisma ORM - -As a first step, navigate into your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-postgresql.mdx deleted file mode 100644 index 73e178c8c5..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-postgresql.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing JavaScript project (PostgreSQL)' -sidebar_label: 'Relational databases' -metaTitle: 'Add Prisma ORM to an existing project that using JavaScript and PostgreSQL(15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing Node.js project by connecting it to your PostgreSQL database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - - - - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -:::tip - -If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. - -::: - -## Prerequisites - -In order to successfully complete this guide, you need: - -- an existing Node.js project with a `package.json` -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [PostgreSQL](https://www.postgresql.org/) database server running and a database with at least one table - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Set up Prisma ORM - -As a first step, navigate into your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-sqlserver.mdx deleted file mode 100644 index 872be668d2..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-node-sqlserver.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing project (JavaScript and SQL Server)' -sidebar_label: 'Relational databases' -metaTitle: 'Add Prisma to an existing project using JavaScript and SQL Server (15 min)' -metaDescription: 'Learn how to add Prisma to an existing Node.js project by connecting it to your SQL Server database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - - - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -:::tip - - -If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. - -::: - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- A [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/?view=sql-server-ver16) database - - [Microsoft SQL Server on Linux for Docker](/orm/overview/databases/sql-server/sql-server-docker) - - [Microsoft SQL Server on Windows (local)](/orm/overview/databases/sql-server/sql-server-local) - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Set up Prisma ORM - -As a first step, navigate into your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-cockroachdb.mdx deleted file mode 100644 index adbdc5f8ae..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-cockroachdb.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing project (TypeScript and CockroachDB)' -sidebar_label: 'Relational databases' -metaTitle: 'Add Prisma ORM to an existing project using TypeScript and CockroachDB (15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing TypeScript project by connecting it to your CockroachDB database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - - - - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -:::tip - -If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. - -::: - -## Prerequisites - -In order to successfully complete this guide, you need: - -- an existing Node.js project with a `package.json` -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [CockroachDB](https://www.cockroachlabs.com) database server running and a database with at least one table - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Set up Prisma ORM - -As a first step, navigate into your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-mysql.mdx deleted file mode 100644 index 1c89468762..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-mysql.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing project (TypeScript and MySQL)' -sidebar_label: 'Relational databases' -metaTitle: 'Integrate Prisma into a TypeScript Project with MySQL (15 min)' -metaDescription: 'Step-by-step guide to connecting a MySQL database to an existing TypeScript project using Prisma and generating a Prisma Client.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - -## Overview - -This guide walks you through integrating Prisma ORM into an existing Node.js or TypeScript project. You'll learn how to: - -- Connect Prisma to your MySQL database -- Use the [Prisma CLI](/orm/tools/prisma-cli) -- Generate a [Prisma Client](/orm/prisma-client) for database access -- Introspect your existing database schema using [Prisma Introspection](/orm/prisma-schema/introspection) - -:::tip -Migrating from another ORM? Check out our dedicated guides for [TypeORM](/guides/migrate-from-typeorm) and [Sequelize](/guides/migrate-from-sequelize). -::: - -## Prerequisites - -Before you begin, ensure you have: - -- An existing Node.js project with a `package.json` file -- [Node.js](https://nodejs.org/en/) installed (see [system requirements](/orm/reference/system-requirements)) -- A running [MySQL](https://www.mysql.com/) database with at least one table - -> 📌 You'll need your [database connection URL](/orm/reference/connection-urls), including credentials. - -> 💡 Don’t have a database yet? Try our [Quickstart guide](/getting-started/quickstart-sqlite) with SQLite to explore Prisma ORM. - -## Step 1: Set Up Prisma - -1. Open your terminal and navigate to the project directory containing your `package.json`. - -2. Install Prisma CLI as a development dependency: - -```bash -npm install prisma --save-dev diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-planetscale.mdx deleted file mode 100644 index b25b8800ab..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-planetscale.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing project (TypeScript and PlanetScale)' -sidebar_label: 'Relational databases' -metaTitle: 'Add Prisma ORM to an existing project using TypeScript and PlanetScale (15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing TypeScript project by connecting it to your PlanetScale database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - - - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -:::tip - -If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. - -::: - -## Prerequisites - -In order to successfully complete this guide, you need: - -- an existing Node.js project with a `package.json` -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [PlanetScale](https://planetscale.com/) database server running and a database with at least one table - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Set up Prisma ORM - -As a first step, navigate into your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-postgresql.mdx deleted file mode 100644 index 1fd554d7e4..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-postgresql.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing project (TypeScript and PostgreSQL)' -sidebar_label: 'Relational databases' -metaTitle: 'Add Prisma ORM to an existing project using TypeScript and PostgreSQL (15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing TypeScript project by connecting it to your PostgreSQL database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - - - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -:::tip - -If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. - -::: - -## Prerequisites - -In order to successfully complete this guide, you need: - -- an existing Node.js project with a `package.json` -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- a [PostgreSQL](https://www.postgresql.org/) database server running and a database with at least one table - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Set up Prisma ORM - -As a first step, navigate into your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-sqlserver.mdx deleted file mode 100644 index a563f5dccc..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases-typescript-sqlserver.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing project (TypeScript and SQL Server)' -sidebar_label: 'Relational databases' -metaTitle: 'Add Prisma ORM to an existing project using TypeScript and SQL Server (15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing TypeScript project by connecting it to your SQL Server database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases- ---- - - - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -:::tip - -If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. - -::: - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- A [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/?view=sql-server-ver16) database - - [Microsoft SQL Server on Linux for Docker](/orm/overview/databases/sql-server/sql-server-docker) - - [Microsoft SQL Server on Windows (local)](/orm/overview/databases/sql-server/sql-server-local) - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -## Set up Prisma ORM - -As a first step, navigate into your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-cockroachdb.mdx deleted file mode 100644 index 3ce1f6f2d0..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-cockroachdb.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Connect your existing database using JavaScript and CockroachDB' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using JavaScript and CockroachDB' -metaDescription: 'Connect your database to your existing project using JavaScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -toc: false -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-node-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -The `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`. You now need to adjust the connection URL to point to your own database. - -

Connection URL

- -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. CockroachDB uses the PostgreSQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -postgresql://USER:PASSWORD@HOST:PORT/DATABASE?PARAMETERS -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running. The default for CockroachDB is `26257`. -- `DATABASE`: The name of the database -- `PARAMETERS`: Any additional connection parameters. See the CockroachDB documentation [here](https://www.cockroachlabs.com/docs/stable/connection-parameters.html#additional-connection-parameters). - -For a [CockroachDB Serverless](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart.html) or [Cockroach Dedicated](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart-trial-cluster) database hosted on [CockroachDB Cloud](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart/), the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="postgresql://:@..cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full&sslrootcert=$HOME/.postgresql/root.crt&options=--" -``` - -To find your connection string on CockroachDB Cloud, click the 'Connect' button on the overview page for your database cluster, and select the 'Connection string' tab. - -For a [CockroachDB database hosted locally](https://www.cockroachlabs.com/docs/stable/secure-a-cluster.html), the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="postgresql://root@localhost:26257?sslmode=disable" -``` - -Your connection string is displayed as part of the welcome text when starting CockroachDB from the command line. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-mysql.mdx deleted file mode 100644 index 6f9b36cfb5..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-mysql.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 'Connect your existing database using JavaScript and MySQL' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using JavaScript and MySQL' -metaDescription: 'Connect your database to your existing project using JavaScript and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -toc: false -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-node-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mysql" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" -``` - -You now need to adjust the connection URL to point to your own database. - -

Connection URL

- -The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. For MySQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mysql://USER:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running (typically `3306` for MySQL) -- `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) - -As an example, for a MySQL database hosted on AWS RDS, the [connection URL](/orm/reference/connection-urls) might look similar to this: - -```bash file=.env -DATABASE_URL="mysql://johndoe:XXX@mysql–instance1.123456789012.us-east-1.rds.amazonaws.com:3306/mydb" -``` - -When running MySQL locally, your connection URL typically looks similar to this: - -```bash file=.env -DATABASE_URL="mysql://root:randompassword@localhost:3306/mydb" -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-planetscale.mdx deleted file mode 100644 index 5e59471d9b..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-planetscale.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: 'Connect your existing database using JavaScript and PlanetScale' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using JavaScript and PlanetScale' -metaDescription: 'Connect your database to your existing project using JavaScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-node-planetscale -pagination_next: getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-planetscale -slugSwitch: /getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database- ---- - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -You will also need to set the relation mode type to `prisma` in order to [emulate foreign key constraints](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client) in the `datasource` block: - -```prisma file=schema.prisma highlight=4;add showLineNumbers -datasource db { - provider = "mysql" - url = env("DATABASE_URL") - //add-next-line - relationMode = "prisma" -} -``` - -> **Note**: Since February 2024, you can alternatively [use foreign key constraints on a database-level in PlanetScale](/orm/overview/databases/planetscale#option-2-enable-foreign-key-constraints-in-the-planetscale-database-settings), which omits the need for setting `relationMode = "prisma"`. - -The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="mysql://janedoe:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" -``` - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. PlanetScale uses the MySQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mysql://USER:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running (typically `3306` for MySQL) -- `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) - -For a database hosted with PlanetScale, the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="mysql://myusername:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" -``` - -The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' to get the Prisma format for the connection URL. - -
-Alternative method: connecting using the PlanetScale CLI - -Alternatively, you can connect to your PlanetScale database server using the [PlanetScale CLI](https://planetscale.com/docs/concepts/planetscale-environment-setup), and use a local connection URL. In this case the connection URL will look like this: - -```bash file=.env -DATABASE_URL="mysql://root@localhost:PORT/mydb" -``` - - - -We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. - - - -To connect to your branch, use the following command: - -```terminal -pscale connect prisma-test branchname --port PORT -``` - -The `--port` flag can be omitted if you are using the default port `3306`. - -
\ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-postgresql.mdx deleted file mode 100644 index 33a3055f80..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-postgresql.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: 'Connect your existing database using JavaScript and PostgreSQL' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using JavaScript and PostgreSQL' -metaDescription: 'Connect your database to your existing project using JavaScript and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -toc: false -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-node-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" -``` - -You now need to adjust the connection URL to point to your own database. - -

Connection URL

- -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For PostgreSQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA -``` - -> **Note**: In most cases, you can use the [`postgres://` and `postgresql:// URI scheme designators interchangeably`](https://www.postgresql.org/docs/10/libpq-connect.html#id-1.7.3.8.3.6) - however, depending on how your database is hosted, you might need to be specific. - -If you're unsure what to provide for the `schema` parameter for a PostgreSQL connection URL, you can probably omit it. In that case, the default schema name `public` will be used. - -As an example, for a PostgreSQL database hosted on Heroku, the connection URL might look similar to this: - -```bash file=.env -DATABASE_URL="postgresql://opnmyfngbknppm:XXX@ec2-46-137-91-216.eu-west-1.compute.amazonaws.com:5432/d50rgmkqi2ipus?schema=hello-prisma" -``` - -When running PostgreSQL locally on macOS, your user and password as well as the database name _typically_ correspond to the current _user_ of your OS, e.g. assuming the user is called `janedoe`: - -```bash file=.env -DATABASE_URL="postgresql://janedoe:janedoe@localhost:5432/janedoe?schema=hello-prisma" -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-sqlserver.mdx deleted file mode 100644 index 57fa9a847d..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-node-sqlserver.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: 'Connect your existing database using JavaScript and SQL Server' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using JavaScript and SQL Server' -metaDescription: 'Connect your existing database to your project using JavaScript and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -toc: false -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-node-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "sqlserver" - url = env("DATABASE_URL") -} -``` - -The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema), the following example connection URL [uses SQL authentication](/orm/overview/databases/sql-server), but there are [other ways to format your connection URL](/orm/overview/databases/sql-server) - -```bash file=.env -DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=r@ndomP@$$w0rd;trustServerCertificate=true" -``` - -Adjust the connection URL to match your setup - see [Microsoft SQL Server connection URL](/orm/overview/databases/sql-server) for more information. - -> Make sure TCP/IP connections are enabled via [SQL Server Configuration Manager](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver16&viewFallbackFrom=sql-server-ver16) to avoid `No connection could be made because the target machine actively refused it. (os error 10061)` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-cockroachdb.mdx deleted file mode 100644 index 2a80965129..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-cockroachdb.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Connect your existing database using TypeScript and CockroachDB' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using TypeScript and CockroachDB' -metaDescription: 'Connect your existing database to your project using TypeScript and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: 'hidden-sidebar tech-switch' -hide_table_of_contents: true -toc: false -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -The `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`. You now need to adjust the connection URL to point to your own database. - -

Connection URL

- -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. CockroachDB uses the PostgreSQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -postgresql://USER:PASSWORD@HOST:PORT/DATABASE?PARAMETERS -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running. The default for CockroachDB is `26257`. -- `DATABASE`: The name of the database -- `PARAMETERS`: Any additional connection parameters. See the CockroachDB documentation [here](https://www.cockroachlabs.com/docs/stable/connection-parameters.html#additional-connection-parameters). - -For a [CockroachDB Serverless](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart.html) or [Cockroach Dedicated](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart-trial-cluster) database hosted on [CockroachDB Cloud](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart/), the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="postgresql://:@..cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full&sslrootcert=$HOME/.postgresql/root.crt&options=--" -``` - -To find your connection string on CockroachDB Cloud, click the 'Connect' button on the overview page for your database cluster, and select the 'Connection string' tab. - -For a [CockroachDB database hosted locally](https://www.cockroachlabs.com/docs/stable/secure-a-cluster.html), the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="postgresql://root@localhost:26257?sslmode=disable" -``` - -Your connection string is displayed as part of the welcome text when starting CockroachDB from the command line. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-mysql.mdx deleted file mode 100644 index 412a150be7..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-mysql.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 'Connect your existing database using TypeScript and MySQL' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using TypeScript and MySQL' -metaDescription: 'Connect your existing database to your project using TypeScript and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -toc: false -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mysql" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" -``` - -You now need to adjust the connection URL to point to your own database. - -

Connection URL

- -The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. For MySQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mysql://USER:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running (typically `3306` for MySQL) -- `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) - -As an example, for a MySQL database hosted on AWS RDS, the [connection URL](/orm/reference/connection-urls) might look similar to this: - -```bash file=.env -DATABASE_URL="mysql://johndoe:XXX@mysql–instance1.123456789012.us-east-1.rds.amazonaws.com:3306/mydb" -``` - -When running MySQL locally, your connection URL typically looks similar to this: - -```bash file=.env -DATABASE_URL="mysql://root:randompassword@localhost:3306/mydb" -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-planetscale.mdx deleted file mode 100644 index 3dfe674538..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-planetscale.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: 'Connect your existing database using TypeScript and PlanetScale' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using TypeScript and PlanetScale' -metaDescription: 'Connect your existing database to your project using TypeScript and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -toc: false -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-planetscale -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -You will also need to [set the relation mode type to `prisma`](/orm/prisma-schema/data-model/relations/relation-mode#emulate-relations-in-prisma-orm-with-the-prisma-relation-mode) in the `datasource` block: - -```prisma file=schema.prisma highlight=4;add showLineNumbers -datasource db { - provider = "mysql" - url = env("DATABASE_URL") - //add-next-line - relationMode = "prisma" -} -``` - -The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="mysql://janedoe:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" -``` - -You now need to adjust the connection URL to point to your own database. - -

Connection URL

- -The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. PlanetScale uses the MySQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mysql://USER:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USER`: The name of your database user -- `PASSWORD`: The password for your database user -- `PORT`: The port where your database server is running (typically `3306` for MySQL) -- `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) - -For a database hosted with PlanetScale, the [connection URL](/orm/reference/connection-urls) looks similar to this: - -```bash file=.env -DATABASE_URL="mysql://myusername:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" -``` - -The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' to get the Prisma format for the connection URL. - -
-Alternative method: connecting using the PlanetScale CLI - -Alternatively, you can connect to your PlanetScale database server using the [PlanetScale CLI](https://planetscale.com/docs/concepts/planetscale-environment-setup), and use a local connection URL. In this case the connection URL will look like this: - -```bash file=.env -DATABASE_URL="mysql://root@localhost:PORT/mydb" -``` - -To connect to your branch, use the following command: - -```terminal -pscale connect prisma-test branchname --port PORT -``` - -The `--port` flag can be omitted if you are using the default port `3306`. - -
diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-postgresql.mdx deleted file mode 100644 index 6035f3ee0f..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-postgresql.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: 'Connect your existing database using TypeScript and PostgresSQL' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using TypeScript and PostgresSQL' -metaDescription: 'Connect your existing database to your project using TypeScript and PostgresSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -toc: false -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: - -```bash file=.env -DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" -``` - -You now need to adjust the connection URL to point to your own database. - -

Connection URL

- -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For PostgreSQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA -``` - -> **Note**: In most cases, you can use the [`postgres://` and `postgresql:// URI scheme designators interchangeably`](https://www.postgresql.org/docs/10/libpq-connect.html#id-1.7.3.8.3.6) - however, depending on how your database is hosted, you might need to be specific. - -If you're unsure what to provide for the `schema` parameter for a PostgreSQL connection URL, you can probably omit it. In that case, the default schema name `public` will be used. - -As an example, for a PostgreSQL database hosted on Heroku, the connection URL might look similar to this: - -```bash file=.env -DATABASE_URL="postgresql://opnmyfngbknppm:XXX@ec2-46-137-91-216.eu-west-1.compute.amazonaws.com:5432/d50rgmkqi2ipus?schema=hello-prisma" -``` - -When running PostgreSQL locally on macOS, your user and password as well as the database name _typically_ correspond to the current _user_ of your OS, e.g. assuming the user is called `janedoe`: - -```bash file=.env -DATABASE_URL="postgresql://janedoe:janedoe@localhost:5432/janedoe?schema=hello-prisma" -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-sqlserver.mdx deleted file mode 100644 index e898b23b12..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/100-connect-your-database-typescript-sqlserver.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: 'Connect your existing database using TypeScript and SQL Server' -sidebar_label: 'Connect your database' -metaTitle: 'Connect your existing database using TypeScript and SQL Server' -metaDescription: 'Connect your existing database to your project using TypeScript and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -toc: false -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "sqlserver" - url = env("DATABASE_URL") -} -``` - -The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema), the following example connection URL [uses SQL authentication](/orm/overview/databases/sql-server), but there are [other ways to format your connection URL](/orm/overview/databases/sql-server) - -```bash file=.env -DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=r@ndomP@$$w0rd;trustServerCertificate=true" -``` - -Adjust the connection URL to match your setup - see [Microsoft SQL Server connection URL](/orm/overview/databases/sql-server) for more information. - -> Make sure TCP/IP connections are enabled via [SQL Server Configuration Manager](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver16&viewFallbackFrom=sql-server-ver16) to avoid `No connection could be made because the target machine actively refused it. (os error 10061)` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-cockroachdb.mdx deleted file mode 100644 index d7d5f1cda4..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-cockroachdb.mdx +++ /dev/null @@ -1,217 +0,0 @@ ---- -title: 'Introspection for CockroachDB in a JavaScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, JavaScript, and CockroachDB' -metaDescription: 'Introspect your existing project with Prisma ORM, JavaScript, and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -CREATE TABLE "User" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - name STRING(255), - email STRING(255) UNIQUE NOT NULL -); - -CREATE TABLE "Post" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - title STRING(255) UNIQUE NOT NULL, - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - content STRING, - published BOOLEAN NOT NULL DEFAULT false, - "authorId" INT8 NOT NULL, - FOREIGN KEY ("authorId") REFERENCES "User"(id) -); - -CREATE TABLE "Profile" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - bio STRING, - "userId" INT8 UNIQUE NOT NULL, - FOREIGN KEY ("userId") REFERENCES "User"(id) -); -``` - -> **Note**: Some fields are written in double quotes to ensure CockroachDB uses proper casing. If no double-quotes were used, CockroachDB would just read everything as _lowercase_ characters. - -
-Expand for a graphical overview of the tables - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------ | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `STRING(255)` | No | No | No | - | -| `email` | `STRING(255)` | No | No | **✔️** | - | - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------ | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `TIMESTAMP` | No | No | **✔️** | `now()` | -| `title` | `STRING(255)` | No | No | **✔️** | - | -| `content` | `STRING` | No | No | No | - | -| `published` | `BOOLEAN` | No | No | **✔️** | `false` | -| `authorId` | `INT8` | No | **✔️** | **✔️** | - | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `STRING` | No | No | No | - | -| `userId` | `INT8` | No | **✔️** | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the environment variable used to define the `url` in your `schema.prisma`, `DATABASE_URL`, that in our case is set in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this: - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id BigInt @id @default(autoincrement()) - title String @unique @db.String(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId BigInt - User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model Profile { - id BigInt @id @default(autoincrement()) - bio String? - userId BigInt @unique - User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model User { - id BigInt @id @default(autoincrement()) - name String? @db.String(255) - email String @unique @db.String(255) - Post Post[] - Profile Profile? -} -``` - -Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -Right now, there's a few minor "issues" with the data model: - -- The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. -- The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. -- Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. - -These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). - -Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: - -```prisma file=prisma/schema.prisma highlight=8,15,22,23;edit showLineNumbers -model Post { - id BigInt @id @default(autoincrement()) - title String @unique @db.String(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId BigInt - //edit-next-line - author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model Profile { - id BigInt @id @default(autoincrement()) - bio String? - userId BigInt @unique - //edit-next-line - user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model User { - id BigInt @id @default(autoincrement()) - name String? @db.String(255) - email String @unique @db.String(255) - //edit-start - posts Post[] - profile Profile? - //edit-end -} -``` - -In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. - -
- Using custom model and field names - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(sequence()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(sequence()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. - -
diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-mysql.mdx deleted file mode 100644 index 64ab5fdfd6..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-mysql.mdx +++ /dev/null @@ -1,220 +0,0 @@ ---- -title: 'Introspection for MySQL in a JavaScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, JavaScript, and MySQL' -metaDescription: 'Introspect your existing project with Prisma ORM, JavaScript, and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -CREATE TABLE User ( - id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, - name VARCHAR(255), - email VARCHAR(255) UNIQUE NOT NULL -); - -CREATE TABLE Post ( - id INTEGER PRIMARY KEY AUTO_INCREMENT 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 User(id) -); - -CREATE TABLE Profile ( - id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, - bio TEXT, - userId INTEGER UNIQUE NOT NULL, - FOREIGN KEY (userId) REFERENCES User(id) -); -``` - -
-Expand for a graphical overview of the tables - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `VARCHAR(255)` | No | No | No | - | -| `email` | `VARCHAR(255)` | No | No | **✔️** | - | - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `DATETIME(3)` | No | No | **✔️** | `now()` | -| `title` | `VARCHAR(255)` | No | No | **✔️** | - | -| `content` | `TEXT` | No | No | No | - | -| `published` | `BOOLEAN` | No | No | **✔️** | `false` | -| `authorId` | `INTEGER` | No | **✔️** | **✔️** | `false` | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :-------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `TEXT` | No | No | No | - | -| `userId` | `INTEGER` | No | **✔️** | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this (note that the fields on the models have been reordered for better readability): - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(0) - content String? @db.Text - published Boolean @default(false) - authorId Int - User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1") - - @@index([authorId], map: "authorId") -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? @db.Text - userId Int @unique(map: "userId") - User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1") -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique(map: "email") @db.VarChar(255) - Post Post[] - Profile Profile? -} -``` - -:::info - -Refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference) for detailed information about the schema definition. - -::: - -Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -Right now, there's a few minor "issues" with the data model: - -- The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. -- The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. -- Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. - -These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). - -Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: - -```prisma file=prisma/schema.prisma highlight=8,17,24,25;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(0) - content String? @db.Text - published Boolean @default(false) - authorId Int - //edit-next-line - author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1") - - @@index([authorId], map: "authorId") -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? @db.Text - userId Int @unique(map: "userId") - //edit-next-line - user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1") -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique(map: "email") @db.VarChar(255) - //edit-start - posts Post[] - profile Profile? - //edit-end -} -``` - -In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(autoincrement()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(autoincrement()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-planetscale.mdx deleted file mode 100644 index 453a978732..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-planetscale.mdx +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: 'Introspection for PlanetScale in a JavaScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, JavaScript, and PlanetScale' -metaDescription: 'Introspect your existing project with Prisma ORM, JavaScript, and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -CREATE TABLE `Post` ( - `id` int NOT NULL AUTO_INCREMENT, - `createdAt` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `updatedAt` datetime(3) NOT NULL, - `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, - `content` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, - `published` tinyint(1) NOT NULL DEFAULT '0', - `authorId` int NOT NULL, - PRIMARY KEY (`id`), - KEY `Post_authorId_idx` (`authorId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - -CREATE TABLE `Profile` ( - `id` int NOT NULL AUTO_INCREMENT, - `bio` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, - `userId` int NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `Profile_userId_key` (`userId`), - KEY `Profile_userId_idx` (`userId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - -CREATE TABLE `User` ( - `id` int NOT NULL AUTO_INCREMENT, - `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, - `name` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `User_email_key` (`email`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -``` - -
-Expand for a graphical overview of the tables - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `datetime(3)` | No | No | **✔️** | `now()` | -| `updatedAt` | `datetime(3)` | No | No | **✔️** | | -| `title` | `varchar(255)` | No | No | **✔️** | - | -| `content` | `varchar(191)` | No | No | No | - | -| `published` | `tinyint(1)` | No | No | **✔️** | `false` | -| `authorId` | `int` | No | No | **✔️** | - | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `varchar(191)` | No | No | No | - | -| `userId` | `int` | No | No | **✔️** | - | - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `varchar(191)` | No | No | No | - | -| `email` | `varchar(191)` | No | No | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this: - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime - title String @db.VarChar(255) - content String? - published Boolean @default(false) - authorId Int - - @@index([authorId]) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - - @@index([userId]) -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? -} -``` - -:::info - -Refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference) for detailed information about the schema definition. - -::: - -Prisma's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -You will then need to add in any missing relations between your data using [relation fields](/orm/prisma-schema/data-model/relations#relation-fields): - -```prisma file=prisma/schema.prisma highlight=8,17,27,28;add showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime - title String @db.VarChar(255) - content String? - published Boolean @default(false) - //add-next-line - author User @relation(fields: [authorId], references: [id]) - authorId Int - - @@index([authorId]) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - //add-next-line - user User @relation(fields: [userId], references: [id]) - userId Int @unique - - @@index([userId]) -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - //add-start - posts Post[] - profile Profile? - //add-end -} -``` - -After this, run introspection on your database for a second time: - -```terminal copy -npx prisma db pull -``` - -Prisma Migrate will now keep the manually added relation fields. - -Because relation fields are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database. - -In this example, the database schema follows the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models. This optimizes the ergonomics of the generated Prisma Client API. - -
- Using custom model and field names - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(autoincrement()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(autoincrement()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. - -
diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-postgresql.mdx deleted file mode 100644 index 6231b4a6f5..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-postgresql.mdx +++ /dev/null @@ -1,218 +0,0 @@ ---- -title: 'Introspection for PostgreSQL in a JavaScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, JavaScript, and PostgreSQL' -metaDescription: 'Introspect your existing project with Prisma ORM, JavaScript, and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -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) -); -``` - -> **Note**: Some fields are written in double-quotes to ensure PostgreSQL uses proper casing. If no double-quotes were used, PostgreSQL would just read everything as _lowercase_ characters. - -
-Expand for a graphical overview of the tables - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `VARCHAR(255)` | No | No | No | - | -| `email` | `VARCHAR(255)` | No | No | **✔️** | - | - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `TIMESTAMP` | No | No | **✔️** | `now()` | -| `title` | `VARCHAR(255)` | No | No | **✔️** | - | -| `content` | `TEXT` | No | No | No | - | -| `published` | `BOOLEAN` | No | No | **✔️** | `false` | -| `authorId` | `INTEGER` | No | **✔️** | **✔️** | - | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :-------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `TEXT` | No | No | No | - | -| `userId` | `INTEGER` | No | **✔️** | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a data model in your Prisma schema. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this (note that the fields on the models have been reordered for better readability): - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - Post Post[] - Profile Profile? -} -``` - -Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -Right now, there's a few minor "issues" with the data model: - -- The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. -- The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. -- Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. - -These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). - -Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: - -```prisma file=prisma/schema.prisma highlight=8,15,22,23;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - //edit-next-line - author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - //edit-next-line - user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - //edit-start - posts Post[] - profile Profile? - //edit-end -} -``` - -In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. - -
- Using custom model and field names - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(autoincrement()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(autoincrement()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. - -
diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-sqlserver.mdx deleted file mode 100644 index 983267bd6e..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-node-sqlserver.mdx +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: 'Introspection for SQL Server in a JavaScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, JavaScript, and SQL Server' -metaDescription: 'Introspect your database with Prisma ORM, JavaScript, and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -CREATE TABLE [dbo].[Post] ( - [id] INT NOT NULL IDENTITY(1,1), - [createdAt] DATETIME2 NOT NULL CONSTRAINT [Post_createdAt_df] DEFAULT CURRENT_TIMESTAMP, - [updatedAt] DATETIME2 NOT NULL, - [title] VARCHAR(255) NOT NULL, - [content] NVARCHAR(1000), - [published] BIT NOT NULL CONSTRAINT [Post_published_df] DEFAULT 0, - [authorId] INT NOT NULL, - CONSTRAINT [Post_pkey] PRIMARY KEY ([id]) -); - -CREATE TABLE [dbo].[Profile] ( - [id] INT NOT NULL IDENTITY(1,1), - [bio] NVARCHAR(1000), - [userId] INT NOT NULL, - CONSTRAINT [Profile_pkey] PRIMARY KEY ([id]), - CONSTRAINT [Profile_userId_key] UNIQUE ([userId]) -); - -CREATE TABLE [dbo].[User] ( - [id] INT NOT NULL IDENTITY(1,1), - [email] NVARCHAR(1000) NOT NULL, - [name] NVARCHAR(1000), - CONSTRAINT [User_pkey] PRIMARY KEY ([id]), - CONSTRAINT [User_email_key] UNIQUE ([email]) -); - -ALTER TABLE [dbo].[Post] ADD CONSTRAINT [Post_authorId_fkey] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; - -ALTER TABLE [dbo].[Profile] ADD CONSTRAINT [Profile_userId_fkey] FOREIGN KEY ([userId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; -``` - -
-Expand for a graphical overview of the tables - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `NVARCHAR(1000)` | No | No | No | - | -| `email` | `NVARCHAR(1000)` | No | No | **✔️** | - | - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `DATETIME2` | No | No | **✔️** | `now()` | -| `updatedAt` | `DATETIME2` | No | No | **✔️** | | -| `title` | `VARCHAR(255)` | No | No | **✔️** | - | -| `content` | `NVARCHAR(1000)` | No | No | No | - | -| `published` | `BIT` | No | No | **✔️** | `false` | -| `authorId` | `INT` | No | **✔️** | **✔️** | - | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `NVARCHAR(1000)` | No | No | No | - | -| `userId` | `INT` | No | **✔️** | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this (note that the fields on the models have been reordered for better readability): - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - User User @relation(fields: [authorId], references: [id]) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - User User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - Post Post[] - Profile Profile? -} -``` - -Prisma's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -Right now, there's a few minor "issues" with the data model: - -- The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. -- The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. -- Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. - -These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). - -Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: - -```prisma file=prisma/schema.prisma highlight=7,14,22,23;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - //edit-next-line - author User @relation(fields: [authorId], references: [id]) - authorId Int -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - //edit-next-line - user User @relation(fields: [userId], references: [id]) - userId Int @unique -} - -model User { - id Int @id @default(autoincrement()) - email String @unique @db.VarChar(255) - name String? @db.VarChar(255) - //edit-start - posts Post[] - profile Profile? - //edit-end -} -``` - -In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. - -
- Using custom model and field names - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(autoincrement()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(autoincrement()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. - -
diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-cockroachdb.mdx deleted file mode 100644 index 64a55d9a57..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-cockroachdb.mdx +++ /dev/null @@ -1,218 +0,0 @@ ---- -title: 'Introspection for CockroachDB in a TypeScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, TypeScript, and CockroachDB' -metaDescription: 'Introspect your database with Prisma ORM, TypeScript, and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -CREATE TABLE "User" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - name STRING(255), - email STRING(255) UNIQUE NOT NULL -); - -CREATE TABLE "Post" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - title STRING(255) UNIQUE NOT NULL, - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - content STRING, - published BOOLEAN NOT NULL DEFAULT false, - "authorId" INT8 NOT NULL, - FOREIGN KEY ("authorId") REFERENCES "User"(id) -); - -CREATE TABLE "Profile" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - bio STRING, - "userId" INT8 UNIQUE NOT NULL, - FOREIGN KEY ("userId") REFERENCES "User"(id) -); -``` - -> **Note**: Some fields are written in double quotes to ensure CockroachDB uses proper casing. If no double-quotes were used, CockroachDB would just read everything as _lowercase_ characters. - -
-Expand for a graphical overview of the tables - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------ | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `STRING(255)` | No | No | No | - | -| `email` | `STRING(255)` | No | No | **✔️** | - | - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------ | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `TIMESTAMP` | No | No | **✔️** | `now()` | -| `title` | `STRING(255)` | No | No | **✔️** | - | -| `content` | `STRING` | No | No | No | - | -| `published` | `BOOLEAN` | No | No | **✔️** | `false` | -| `authorId` | `INT8` | No | **✔️** | **✔️** | - | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `STRING` | No | No | No | - | -| `userId` | `INT8` | No | **✔️** | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the environment variable used to define the `url` in your `schema.prisma`, `DATABASE_URL`, that in our case is set in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this: - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id BigInt @id @default(autoincrement()) - title String @unique @db.String(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId BigInt - User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model Profile { - id BigInt @id @default(autoincrement()) - bio String? - userId BigInt @unique - User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model User { - id BigInt @id @default(autoincrement()) - name String? @db.String(255) - email String @unique @db.String(255) - Post Post[] - Profile Profile? -} -``` - -Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -Right now, there's a few minor "issues" with the data model: - -- The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. -- The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. -- Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. - -These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). - -Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: - -```prisma file=prisma/schema.prisma highlight=8,15,22,23;edit showLineNumbers -model Post { - id BigInt @id @default(autoincrement()) - title String @unique @db.String(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId BigInt - //edit-next-line - author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model Profile { - id BigInt @id @default(autoincrement()) - bio String? - userId BigInt @unique - //edit-next-line - user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model User { - id BigInt @id @default(autoincrement()) - name String? @db.String(255) - email String @unique @db.String(255) - //edit-start - posts Post[] - profile Profile? - //edit-end -} -``` - -In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. - -
- Using custom model and field names - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(sequence()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(sequence()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. - -
diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-mysql.mdx deleted file mode 100644 index 7df914b56b..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-mysql.mdx +++ /dev/null @@ -1,221 +0,0 @@ ---- -title: 'Introspection for MySQL in a TypeScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, TypeScript, and MySQL' -metaDescription: 'Introspect your existing project with Prisma ORM, TypeScript, and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -CREATE TABLE User ( - id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, - name VARCHAR(255), - email VARCHAR(255) UNIQUE NOT NULL -); - -CREATE TABLE Post ( - id INTEGER PRIMARY KEY AUTO_INCREMENT 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 User(id) -); - -CREATE TABLE Profile ( - id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, - bio TEXT, - userId INTEGER UNIQUE NOT NULL, - FOREIGN KEY (userId) REFERENCES User(id) -); -``` - -
-Expand for a graphical overview of the tables - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `VARCHAR(255)` | No | No | No | - | -| `email` | `VARCHAR(255)` | No | No | **✔️** | - | - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `DATETIME(3)` | No | No | **✔️** | `now()` | -| `title` | `VARCHAR(255)` | No | No | **✔️** | - | -| `content` | `TEXT` | No | No | No | - | -| `published` | `BOOLEAN` | No | No | **✔️** | `false` | -| `authorId` | `INTEGER` | No | **✔️** | **✔️** | `false` | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :-------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `TEXT` | No | No | No | - | -| `userId` | `INTEGER` | No | **✔️** | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this (note that the fields on the models have been reordered for better readability): - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(0) - content String? @db.Text - published Boolean @default(false) - authorId Int - User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1") - - @@index([authorId], map: "authorId") -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? @db.Text - userId Int @unique(map: "userId") - User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1") -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique(map: "email") @db.VarChar(255) - Post Post[] - Profile Profile? -} -``` - -:::info - -Refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference) for detailed information about the schema definition. - -::: - -Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -Right now, there's a few minor "issues" with the data model: - -- The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. -- The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. -- Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. - -These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). - -Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: - -```prisma file=prisma/schema.prisma highlight=8,17,24,25;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(0) - content String? @db.Text - published Boolean @default(false) - authorId Int - //edit-next-line - author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1") - - @@index([authorId], map: "authorId") -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? @db.Text - userId Int @unique(map: "userId") - //edit-next-line - user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1") -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique(map: "email") @db.VarChar(255) - //edit-start - posts Post[] - profile Profile? - //edit-end -} -``` - -In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(autoincrement()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(autoincrement()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-planetscale.mdx deleted file mode 100644 index 07b8f12df8..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-planetscale.mdx +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: 'Introspection for PlanetScale in a TypeScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, TypeScript, and PlanetScale' -metaDescription: 'Introspect your existing project with Prisma ORM, TypeScript, and PlanetScale' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-planetscale -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -CREATE TABLE `Post` ( - `id` int NOT NULL AUTO_INCREMENT, - `createdAt` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `updatedAt` datetime(3) NOT NULL, - `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, - `content` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, - `published` tinyint(1) NOT NULL DEFAULT '0', - `authorId` int NOT NULL, - PRIMARY KEY (`id`), - KEY `Post_authorId_idx` (`authorId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - -CREATE TABLE `Profile` ( - `id` int NOT NULL AUTO_INCREMENT, - `bio` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, - `userId` int NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `Profile_userId_key` (`userId`), - KEY `Profile_userId_idx` (`userId`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - -CREATE TABLE `User` ( - `id` int NOT NULL AUTO_INCREMENT, - `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, - `name` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `User_email_key` (`email`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -``` - -
-Expand for a graphical overview of the tables - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `datetime(3)` | No | No | **✔️** | `now()` | -| `updatedAt` | `datetime(3)` | No | No | **✔️** | | -| `title` | `varchar(255)` | No | No | **✔️** | - | -| `content` | `varchar(191)` | No | No | No | - | -| `published` | `tinyint(1)` | No | No | **✔️** | `false` | -| `authorId` | `int` | No | No | **✔️** | - | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `varchar(191)` | No | No | No | - | -| `userId` | `int` | No | No | **✔️** | - | - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `varchar(191)` | No | No | No | - | -| `email` | `varchar(191)` | No | No | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this: - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime - title String @db.VarChar(255) - content String? - published Boolean @default(false) - authorId Int - - @@index([authorId]) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - - @@index([userId]) -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? -} -``` - -:::info - -Refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference) for detailed information about the schema definition. - -::: - -Prisma's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -You will then need to add in any missing relations between your data using [relation fields](/orm/prisma-schema/data-model/relations#relation-fields): - -```prisma file=prisma/schema.prisma highlight=8,17,27,28;add showLineNumbers -model Post { - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - updatedAt DateTime - title String @db.VarChar(255) - content String? - published Boolean @default(false) - //add-next-line - author User @relation(fields: [authorId], references: [id]) - authorId Int - - @@index([authorId]) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - //add-next-line - user User @relation(fields: [userId], references: [id]) - userId Int @unique - - @@index([userId]) -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - //add-start - posts Post[] - profile Profile? - //add-end -} -``` - -After this, run introspection on your database for a second time: - -```terminal copy -npx prisma db pull -``` - -Prisma Migrate will now keep the manually added relation fields. - -Because relation fields are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database. - -In this example, the database schema follows the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models. This optimizes the ergonomics of the generated Prisma Client API. - -
- Using custom model and field names - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(autoincrement()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(autoincrement()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. - -
diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-postgresql.mdx deleted file mode 100644 index e87d3f4888..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-postgresql.mdx +++ /dev/null @@ -1,217 +0,0 @@ ---- -title: 'Introspection for PostgreSQL in a TypeScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, TypeScript, and PostgreSQL' -metaDescription: 'Introspect your existing project with Prisma ORM, TypeScript, and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -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) -); -``` - -> **Note**: Some fields are written in double-quotes to ensure PostgreSQL uses proper casing. If no double-quotes were used, PostgreSQL would just read everything as _lowercase_ characters. - -
-Expand for a graphical overview of the tables - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `VARCHAR(255)` | No | No | No | - | -| `email` | `VARCHAR(255)` | No | No | **✔️** | - | - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `TIMESTAMP` | No | No | **✔️** | `now()` | -| `title` | `VARCHAR(255)` | No | No | **✔️** | - | -| `content` | `TEXT` | No | No | No | - | -| `published` | `BOOLEAN` | No | No | **✔️** | `false` | -| `authorId` | `INTEGER` | No | **✔️** | **✔️** | - | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :-------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `TEXT` | No | No | No | - | -| `userId` | `INTEGER` | No | **✔️** | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a data model in your Prisma schema. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this (note that the fields on the models have been reordered for better readability): - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - Post Post[] - Profile Profile? -} -``` - -Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -Right now, there's a few minor "issues" with the data model: - -- The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. -- The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. -- Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. - -These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). - -Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: - -```prisma file=prisma/schema.prisma highlight=8,15,22,23;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - //edit-next-line - author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - //edit-next-line - user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - //edit-start - posts Post[] - profile Profile? - //edit-end -} -``` - -In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. - -
- Using custom model and field names - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(autoincrement()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(autoincrement()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. - -
diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-sqlserver.mdx deleted file mode 100644 index 811cbef53c..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/150-introspection-typescript-sqlserver.mdx +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: 'Introspection for SQL Server in a TypeScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection with Prisma ORM, TypeScript, and SQL Server' -metaDescription: 'Introspect your existing project with Prisma ORM, TypeScript, and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection- ---- - - -## Introspect your database with Prisma ORM - -For the purpose of this guide, we'll use a demo SQL schema with three tables: - -```sql no-lines -CREATE TABLE [dbo].[Post] ( - [id] INT NOT NULL IDENTITY(1,1), - [createdAt] DATETIME2 NOT NULL CONSTRAINT [Post_createdAt_df] DEFAULT CURRENT_TIMESTAMP, - [updatedAt] DATETIME2 NOT NULL, - [title] VARCHAR(255) NOT NULL, - [content] NVARCHAR(1000), - [published] BIT NOT NULL CONSTRAINT [Post_published_df] DEFAULT 0, - [authorId] INT NOT NULL, - CONSTRAINT [Post_pkey] PRIMARY KEY ([id]) -); - -CREATE TABLE [dbo].[Profile] ( - [id] INT NOT NULL IDENTITY(1,1), - [bio] NVARCHAR(1000), - [userId] INT NOT NULL, - CONSTRAINT [Profile_pkey] PRIMARY KEY ([id]), - CONSTRAINT [Profile_userId_key] UNIQUE ([userId]) -); - -CREATE TABLE [dbo].[User] ( - [id] INT NOT NULL IDENTITY(1,1), - [email] NVARCHAR(1000) NOT NULL, - [name] NVARCHAR(1000), - CONSTRAINT [User_pkey] PRIMARY KEY ([id]), - CONSTRAINT [User_email_key] UNIQUE ([email]) -); - -ALTER TABLE [dbo].[Post] ADD CONSTRAINT [Post_authorId_fkey] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; - -ALTER TABLE [dbo].[Profile] ADD CONSTRAINT [Profile_userId_fkey] FOREIGN KEY ([userId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; -``` - -
-Expand for a graphical overview of the tables - -**User** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | -| `name` | `NVARCHAR(1000)` | No | No | No | - | -| `email` | `NVARCHAR(1000)` | No | No | **✔️** | - | - -**Post** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | -| `createdAt` | `DATETIME2` | No | No | **✔️** | `now()` | -| `updatedAt` | `DATETIME2` | No | No | **✔️** | | -| `title` | `VARCHAR(255)` | No | No | **✔️** | - | -| `content` | `NVARCHAR(1000)` | No | No | No | - | -| `published` | `BIT` | No | No | **✔️** | `false` | -| `authorId` | `INT` | No | **✔️** | **✔️** | - | - -**Profile** - -| Column name | Type | Primary key | Foreign key | Required | Default | -| :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | -| `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | -| `bio` | `NVARCHAR(1000)` | No | No | No | - | -| `userId` | `INT` | No | **✔️** | **✔️** | - | - -
- -As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. - -Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. - -After the introspection is complete, your Prisma schema is updated: - -![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) - -The data model now looks similar to this (note that the fields on the models have been reordered for better readability): - -```prisma file=prisma/schema.prisma showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - User User @relation(fields: [authorId], references: [id]) -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - User User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - Post Post[] - Profile Profile? -} -``` - -Prisma's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. - -Right now, there's a few minor "issues" with the data model: - -- The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. -- The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. -- Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. - -These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). - -Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: - -```prisma file=prisma/schema.prisma highlight=7,14,22,23;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - //edit-next-line - author User @relation(fields: [authorId], references: [id]) - authorId Int -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - //edit-next-line - user User @relation(fields: [userId], references: [id]) - userId Int @unique -} - -model User { - id Int @id @default(autoincrement()) - email String @unique @db.VarChar(255) - name String? @db.VarChar(255) - //edit-start - posts Post[] - profile Profile? - //edit-end -} -``` - -In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. - -
- Using custom model and field names - -Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. - -Assume you obtained the following model from introspection that's based on _snake_case_ notation: - -```prisma no-lines -model my_user { - user_id Int @id @default(autoincrement()) - first_name String? - last_name String @unique -} -``` - -If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: - -```ts no-lines -const user = await prisma.my_user.create({ - data: { - first_name: 'Alice', - last_name: 'Smith', - }, -}) -``` - -If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): - -```prisma no-lines -model MyUser { - userId Int @id @default(autoincrement()) @map("user_id") - firstName String? @map("first_name") - lastName String @unique @map("last_name") - - @@map("my_user") -} -``` - -With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: - -```ts no-lines -const user = await prisma.myUser.create({ - data: { - firstName: 'Alice', - lastName: 'Smith', - }, -}) -``` - -Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. - -
diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-cockroachdb.mdx deleted file mode 100644 index 25c6df618c..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-cockroachdb.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: 'Baseline with Prisma ORM, JavaScript, and CockroachDB' -sidebar_label: 'Baseline your database' -metaTitle: 'Baseline with Prisma ORM, JavaScript, and CockroachDB' -metaDescription: 'Baseline your database with Prisma ORM, JavaScript, and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database- ---- - - -## Create an initial migration - -To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). - -Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. - -To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. - -First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: - -```terminal -mkdir -p prisma/migrations/0_init -``` - - - -`-p` will recursively create any missing folders in the path you provide. - - - -Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - -- `--from-empty`: assumes the data model you're migrating from is empty -- `--to-schema-datamodel`: the current database state using the URL in the `datasource` block -- `--script`: output a SQL script - -```terminal wrap -npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql -``` - -## Review the migration - -The command will generate a migration that should resemble the following script: - -```sql file=prisma/migrations/0_init/migration.sql -CREATE TABLE "User" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - name STRING(255), - email STRING(255) UNIQUE NOT NULL -); - -CREATE TABLE "Post" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - title STRING(255) UNIQUE NOT NULL, - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - content STRING, - published BOOLEAN NOT NULL DEFAULT false, - "authorId" INT8 NOT NULL, - FOREIGN KEY ("authorId") REFERENCES "User"(id) -); - -CREATE TABLE "Profile" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - bio STRING, - "userId" INT8 UNIQUE NOT NULL, - FOREIGN KEY ("userId") REFERENCES "User"(id) -); -``` - -Review the SQL migration file to ensure everything is correct. - -Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. - -```terminal -npx prisma migrate resolve --applied 0_init -``` - -The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. - -You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-mysql.mdx deleted file mode 100644 index ec112cdc58..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-mysql.mdx +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: 'Baseline with Prisma ORM, JavaScript, and MySQL' -sidebar_label: 'Baseline your database' -metaTitle: 'Baseline with Prisma ORM, JavaScript, and MySQL' -metaDescription: 'Baseline your database with Prisma ORM, JavaScript, and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database- ---- - - -## Create an initial migration - -To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). - -Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. - -To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. - -First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: - -```terminal -mkdir -p prisma/migrations/0_init -``` - - - -`-p` will recursively create any missing folders in the path you provide. - - - -Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - -- `--from-empty`: assumes the data model you're migrating from is empty -- `--to-schema-datamodel`: the current database state using the URL in the `datasource` block -- `--script`: output a SQL script - -```terminal wrap -npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql -``` - -## Review the migration - -The command will generate a migration that should resemble the following script: - -```sql file=prisma/migrations/0_init/migration.sql --- CreateTable -CREATE TABLE `Post` ( - `id` INTEGER NOT NULL AUTO_INCREMENT, - `title` VARCHAR(255) NOT NULL, - `createdAt` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0), - `content` TEXT NULL, - `published` BOOLEAN NOT NULL DEFAULT false, - `authorId` INTEGER NOT NULL, - - INDEX `authorId`(`authorId`), - PRIMARY KEY (`id`) -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- CreateTable -CREATE TABLE `Profile` ( - `id` INTEGER NOT NULL AUTO_INCREMENT, - `bio` TEXT NULL, - `userId` INTEGER NOT NULL, - - UNIQUE INDEX `userId`(`userId`), - PRIMARY KEY (`id`) -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- CreateTable -CREATE TABLE `User` ( - `id` INTEGER NOT NULL AUTO_INCREMENT, - `name` VARCHAR(255) NULL, - `email` VARCHAR(255) NOT NULL, - - UNIQUE INDEX `email`(`email`), - PRIMARY KEY (`id`) -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- AddForeignKey -ALTER TABLE `Post` ADD CONSTRAINT `Post_ibfk_1` FOREIGN KEY (`authorId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; - --- AddForeignKey -ALTER TABLE `Profile` ADD CONSTRAINT `Profile_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; -``` - -Review the SQL migration file to ensure everything is correct. - -Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. - -```terminal -npx prisma migrate resolve --applied 0_init -``` - -The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. - -You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-postgresql.mdx deleted file mode 100644 index 79cbdc4a08..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-postgresql.mdx +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: 'Baseline with Prisma ORM, JavaScript, and PostgreSQL' -sidebar_label: 'Baseline your database' -metaTitle: 'Baseline with Prisma ORM, JavaScript, and PostgreSQL' -metaDescription: 'Baseline your database with Prisma ORM, JavaScript, and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database- ---- - - -## Create an initial migration - -To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). - -Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. - -To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. - -First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: - -```terminal -mkdir -p prisma/migrations/0_init -``` - - - -`-p` will recursively create any missing folders in the path you provide. - - - -Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - -- `--from-empty`: assumes the data model you're migrating from is empty -- `--to-schema-datamodel`: the current database state using the URL in the `datasource` block -- `--script`: output a SQL script - -```terminal wrap -npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql -``` - -## Review the migration - -The command will generate a migration that should resemble the following script: - -```sql file=prisma/migrations/0_init/migration.sql --- CreateTable -CREATE TABLE "Post" ( - "id" SERIAL NOT NULL, - "title" VARCHAR(255) NOT NULL, - "createdAt" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "content" TEXT, - "published" BOOLEAN NOT NULL DEFAULT false, - "authorId" INTEGER NOT NULL, - - CONSTRAINT "Post_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Profile" ( - "id" SERIAL NOT NULL, - "bio" TEXT, - "userId" INTEGER NOT NULL, - - CONSTRAINT "Profile_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "User" ( - "id" SERIAL NOT NULL, - "name" VARCHAR(255), - "email" VARCHAR(255) NOT NULL, - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "Profile_userId_key" ON "Profile"("userId"); - --- 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 NO ACTION ON UPDATE NO ACTION; - --- AddForeignKey -ALTER TABLE "Profile" ADD CONSTRAINT "Profile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; -``` - -Review the SQL migration file to ensure everything is correct. - -Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. - -```terminal -npx prisma migrate resolve --applied 0_init -``` - -The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. - -You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-sqlserver.mdx deleted file mode 100644 index 436408fa9d..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-node-sqlserver.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: 'Baseline with Prisma ORM, JavaScript, and SQL Server' -sidebar_label: 'Baseline your database' -metaTitle: 'Baseline with Prisma ORM, JavaScript, and SQL Server' -metaDescription: 'Baseline your database with Prisma ORM, JavaScript, and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database- ---- - - -## Create an initial migration - -To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). - -Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. - -To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. - -First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: - -```terminal -mkdir -p prisma/migrations/0_init -``` - - - -`-p` will recursively create any missing folders in the path you provide. - - - -Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - -- `--from-empty`: assumes the data model you're migrating from is empty -- `--to-schema-datamodel`: the current database state using the URL in the `datasource` block -- `--script`: output a SQL script - -```terminal wrap -npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql -``` - -## Review the migration - -The command will generate a migration that should resemble the following script: - -```sql file=prisma/migrations/0_init/migration.sql -CREATE TABLE [dbo].[Post] ( - [id] INT NOT NULL IDENTITY(1,1), - [createdAt] DATETIME2 NOT NULL CONSTRAINT [Post_createdAt_df] DEFAULT CURRENT_TIMESTAMP, - [updatedAt] DATETIME2 NOT NULL, - [title] VARCHAR(255) NOT NULL, - [content] NVARCHAR(1000), - [published] BIT NOT NULL CONSTRAINT [Post_published_df] DEFAULT 0, - [authorId] INT NOT NULL, - CONSTRAINT [Post_pkey] PRIMARY KEY ([id]) -); - -CREATE TABLE [dbo].[Profile] ( - [id] INT NOT NULL IDENTITY(1,1), - [bio] NVARCHAR(1000), - [userId] INT NOT NULL, - CONSTRAINT [Profile_pkey] PRIMARY KEY ([id]), - CONSTRAINT [Profile_userId_key] UNIQUE ([userId]) -); - -CREATE TABLE [dbo].[User] ( - [id] INT NOT NULL IDENTITY(1,1), - [email] NVARCHAR(1000) NOT NULL, - [name] NVARCHAR(1000), - CONSTRAINT [User_pkey] PRIMARY KEY ([id]), - CONSTRAINT [User_email_key] UNIQUE ([email]) -); - -ALTER TABLE [dbo].[Post] ADD CONSTRAINT [Post_authorId_fkey] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; - -ALTER TABLE [dbo].[Profile] ADD CONSTRAINT [Profile_userId_fkey] FOREIGN KEY ([userId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; -``` - -Review the SQL migration file to ensure everything is correct. - -Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. - -```terminal -npx prisma migrate resolve --applied 0_init -``` - -The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. - -You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-cockroachdb.mdx deleted file mode 100644 index 65e048db8b..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-cockroachdb.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: 'Baseline with Prisma ORM, TypeScript, and CockroachDB' -sidebar_label: 'Baseline your database' -metaTitle: 'Baseline with Prisma ORM, TypeScript, and CockroachDB' -metaDescription: 'Baseline your database with Prisma ORM, TypeScript, and CockroachDB' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database- ---- - - -## Create an initial migration - -To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). - -Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. - -To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. - -First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: - -```terminal -mkdir -p prisma/migrations/0_init -``` - - - -`-p` will recursively create any missing folders in the path you provide. - - - -Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - -- `--from-empty`: assumes the data model you're migrating from is empty -- `--to-schema-datamodel`: the current database state using the URL in the `datasource` block -- `--script`: output a SQL script - -```terminal wrap -npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql -``` - -## Review the migration - -The command will generate a migration that should resemble the following script: - - -```sql file=prisma/migrations/0_init/migration.sql -CREATE TABLE "User" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - name STRING(255), - email STRING(255) UNIQUE NOT NULL -); - -CREATE TABLE "Post" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - title STRING(255) UNIQUE NOT NULL, - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - content STRING, - published BOOLEAN NOT NULL DEFAULT false, - "authorId" INT8 NOT NULL, - FOREIGN KEY ("authorId") REFERENCES "User"(id) -); - -CREATE TABLE "Profile" ( - id INT8 PRIMARY KEY DEFAULT unique_rowid(), - bio STRING, - "userId" INT8 UNIQUE NOT NULL, - FOREIGN KEY ("userId") REFERENCES "User"(id) -); -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-mysql.mdx deleted file mode 100644 index f2c4008c40..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-mysql.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: 'Baseline with Prisma ORM, TypeScript, and MySQL' -sidebar_label: 'Baseline your database' -metaTitle: 'Baseline with Prisma ORM, TypeScript, and MySQL' -metaDescription: 'Baseline your database with Prisma ORM, TypeScript, and MySQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database- ---- - - -## Create an initial migration - -To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). - -Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. - -To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. - -First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: - -```terminal -mkdir -p prisma/migrations/0_init -``` - - - -`-p` will recursively create any missing folders in the path you provide. - - - -Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - -- `--from-empty`: assumes the data model you're migrating from is empty -- `--to-schema-datamodel`: the current database state using the URL in the `datasource` block -- `--script`: output a SQL script - -```terminal wrap -npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql -``` - -## Review the migration - -The command will generate a migration that should resemble the following script: - -```sql file=prisma/migrations/0_init/migration.sql --- CreateTable -CREATE TABLE `Post` ( - `id` INTEGER NOT NULL AUTO_INCREMENT, - `title` VARCHAR(255) NOT NULL, - `createdAt` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0), - `content` TEXT NULL, - `published` BOOLEAN NOT NULL DEFAULT false, - `authorId` INTEGER NOT NULL, - - INDEX `authorId`(`authorId`), - PRIMARY KEY (`id`) -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- CreateTable -CREATE TABLE `Profile` ( - `id` INTEGER NOT NULL AUTO_INCREMENT, - `bio` TEXT NULL, - `userId` INTEGER NOT NULL, - - UNIQUE INDEX `userId`(`userId`), - PRIMARY KEY (`id`) -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- CreateTable -CREATE TABLE `User` ( - `id` INTEGER NOT NULL AUTO_INCREMENT, - `name` VARCHAR(255) NULL, - `email` VARCHAR(255) NOT NULL, - - UNIQUE INDEX `email`(`email`), - PRIMARY KEY (`id`) -) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- AddForeignKey -ALTER TABLE `Post` ADD CONSTRAINT `Post_ibfk_1` FOREIGN KEY (`authorId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; - --- AddForeignKey -ALTER TABLE `Profile` ADD CONSTRAINT `Profile_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; -``` - - -Review the SQL migration file to ensure everything is correct. - -Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. - -```terminal -npx prisma migrate resolve --applied 0_init -``` - -The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. - -You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-postgresql.mdx deleted file mode 100644 index 7041fe9521..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-postgresql.mdx +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: 'Baseline with Prisma ORM, TypeScript, and PostgreSQL' -sidebar_label: 'Baseline your database' -metaTitle: 'Baseline with Prisma ORM, TypeScript, and PostgreSQL' -metaDescription: 'Baseline your database with Prisma ORM, TypeScript, and PostgreSQL' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database- ---- - - -## Create an initial migration - -To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). - -Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. - -To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. - -First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: - -```terminal -mkdir -p prisma/migrations/0_init -``` - - - -`-p` will recursively create any missing folders in the path you provide. - - - -Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - -- `--from-empty`: assumes the data model you're migrating from is empty -- `--to-schema-datamodel`: the current database state using the URL in the `datasource` block -- `--script`: output a SQL script - -```terminal wrap -npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql -``` - -## Review the migration - -The command will generate a migration that should resemble the following script: - -```sql file=prisma/migrations/0_init/migration.sql --- CreateTable -CREATE TABLE "Post" ( - "id" SERIAL NOT NULL, - "title" VARCHAR(255) NOT NULL, - "createdAt" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "content" TEXT, - "published" BOOLEAN NOT NULL DEFAULT false, - "authorId" INTEGER NOT NULL, - - CONSTRAINT "Post_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Profile" ( - "id" SERIAL NOT NULL, - "bio" TEXT, - "userId" INTEGER NOT NULL, - - CONSTRAINT "Profile_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "User" ( - "id" SERIAL NOT NULL, - "name" VARCHAR(255), - "email" VARCHAR(255) NOT NULL, - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "Profile_userId_key" ON "Profile"("userId"); - --- 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 NO ACTION ON UPDATE NO ACTION; - --- AddForeignKey -ALTER TABLE "Profile" ADD CONSTRAINT "Profile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; -``` - -Review the SQL migration file to ensure everything is correct. - -Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. - -```terminal -npx prisma migrate resolve --applied 0_init -``` - -The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. - -You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-sqlserver.mdx deleted file mode 100644 index 61bbb0321a..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/170-baseline-your-database-typescript-sqlserver.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: 'Baseline with Prisma ORM, TypeScript, and SQL Server' -sidebar_label: 'Baseline your database' -metaTitle: 'Baseline with Prisma ORM, TypeScript, and SQL Server' -metaDescription: 'Baseline your database with Prisma ORM, TypeScript, and SQL Server' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database- ---- - - -## Create an initial migration - -To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). - -Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. - -To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. - -First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: - -```terminal -mkdir -p prisma/migrations/0_init -``` - - - -`-p` will recursively create any missing folders in the path you provide. - - - -Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - -- `--from-empty`: assumes the data model you're migrating from is empty -- `--to-schema-datamodel`: the current database state using the URL in the `datasource` block -- `--script`: output a SQL script - -```terminal wrap -npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql -``` - -## Review the migration - -The command will generate a migration that should resemble the following script: - -```sql file=prisma/migrations/0_init/migration.sql -CREATE TABLE [dbo].[Post] ( - [id] INT NOT NULL IDENTITY(1,1), - [createdAt] DATETIME2 NOT NULL CONSTRAINT [Post_createdAt_df] DEFAULT CURRENT_TIMESTAMP, - [updatedAt] DATETIME2 NOT NULL, - [title] VARCHAR(255) NOT NULL, - [content] NVARCHAR(1000), - [published] BIT NOT NULL CONSTRAINT [Post_published_df] DEFAULT 0, - [authorId] INT NOT NULL, - CONSTRAINT [Post_pkey] PRIMARY KEY ([id]) -); - -CREATE TABLE [dbo].[Profile] ( - [id] INT NOT NULL IDENTITY(1,1), - [bio] NVARCHAR(1000), - [userId] INT NOT NULL, - CONSTRAINT [Profile_pkey] PRIMARY KEY ([id]), - CONSTRAINT [Profile_userId_key] UNIQUE ([userId]) -); - -CREATE TABLE [dbo].[User] ( - [id] INT NOT NULL IDENTITY(1,1), - [email] NVARCHAR(1000) NOT NULL, - [name] NVARCHAR(1000), - CONSTRAINT [User_pkey] PRIMARY KEY ([id]), - CONSTRAINT [User_email_key] UNIQUE ([email]) -); - -ALTER TABLE [dbo].[Post] ADD CONSTRAINT [Post_authorId_fkey] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; - -ALTER TABLE [dbo].[Profile] ADD CONSTRAINT [Profile_userId_fkey] FOREIGN KEY ([userId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; -``` - -Review the SQL migration file to ensure everything is correct. - -Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. - -```terminal -npx prisma migrate resolve --applied 0_init -``` - -The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. - -You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-cockroachdb.mdx deleted file mode 100644 index 306e4ebfbb..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-cockroachdb.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client in an existing JavaScript project (CockroachDB)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using JavaScript and CockroachDB' -metaDescription: 'Install and generate Prisma Client in your existing JavaScript and CockroachDB project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-mysql.mdx deleted file mode 100644 index 6e1d802cd7..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-mysql.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client in an existing JavaScript project (MySQL)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using JavaScript and MySQL' -metaDescription: 'Install and generate Prisma Client in your existing JavaScript and MySQL project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-planetscale.mdx deleted file mode 100644 index 5e25861d0a..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-planetscale.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client in an existing JavaScript project (PlanetScale)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using JavaScript and PlanetScale' -metaDescription: 'Install and generate Prisma Client in your existing JavaScript and PlanetScale project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-planetscale -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-planetscale -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-postgresql.mdx deleted file mode 100644 index 79a60fe467..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-postgresql.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client in an existing JavaScript project (PostgreSQL)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using JavaScript and PostgreSQL' -metaDescription: 'Install and generate Prisma Client in your existing JavaScript and PostgreSQL project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-sqlserver.mdx deleted file mode 100644 index cef9feceb5..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-node-sqlserver.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client in an existing JavaScript project (SQL Server)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using JavaScript and SQL Server' -metaDescription: 'Install and generate Prisma Client in your existing JavaScript and SQL Server project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-cockroachdb.mdx deleted file mode 100644 index c1f9a4105d..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-cockroachdb.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client in an existing TypeScript project (CockroachDB)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using TypeScript and CockroachDB' -metaDescription: 'Install and generate Prisma Client in your existing TypeScript and CockroachDB project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-mysql.mdx deleted file mode 100644 index e970da5f15..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-mysql.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client in an existing TypeScript project (MySQL)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using TypeScript and MySQL' -metaDescription: 'Install and generate Prisma Client in your existing TypeScript and MySQL project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-planetscale.mdx deleted file mode 100644 index 8830aaab55..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-planetscale.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client in an existing TypeScript project (PlanetScale)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using TypeScript and PlanetScale' -metaDescription: 'Install and generate Prisma Client in your existing TypeScript and PlanetScale project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-planetscale -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-planetscale -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-postgresql.mdx deleted file mode 100644 index c56f64a9f2..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-postgresql.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: 'Install Prisma Client in an existing TypeScript project (PostgreSQL)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using TypeScript and PostgreSQL' -metaDescription: 'Install and generate Prisma Client in your existing TypeScript and PostgreSQL project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-sqlserver.mdx deleted file mode 100644 index cb7201e06a..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/200-install-prisma-client-typescript-sqlserver.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 'Install Prisma Client in your existing TypeScript project (SQL Server)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project using TypeScript and SQL Server' -metaDescription: 'Install and generate Prisma Client in your existing TypeScript and SQL Server project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client- ---- - -import InstallPrismaClient from './_install-prisma-client-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-cockroachdb.mdx deleted file mode 100644 index a015c01fad..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-cockroachdb.mdx +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: 'Query your existing CockroachDB database with JavaScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing CockroachDB database with JavaScript and Prisma ORM' -metaDescription: 'Write data to and query the CockroachDB database with your JavaScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js showLineNumbers -const { PrismaClient } = require('@prisma/client') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -```js file=index.js -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { title: 'Hello World' }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-mysql.mdx deleted file mode 100644 index 926e969795..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-mysql.mdx +++ /dev/null @@ -1,125 +0,0 @@ ---- -title: 'Query your existing MySQL database with JavaScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing MySQL database with JavaScript and Prisma ORM' -metaDescription: 'Write data to and query the MySQL database with your JavaScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js showLineNumbers -const { PrismaClient } = require('@prisma/client') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -```js file=index.js -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-planetscale.mdx deleted file mode 100644 index 055441a96d..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-planetscale.mdx +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: 'Query your existing PlanetScale database with JavaScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing PlanetScale database with JavaScript and Prisma ORM' -metaDescription: 'Write data to and query the PlanetScale database with your JavaScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js showLineNumbers -const { PrismaClient } = require('@prisma/client') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). - -The following examples are all based on the models in the Prisma schema. - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```js file=index.js showLineNumbers -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-postgresql.mdx deleted file mode 100644 index 552155f8ad..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-postgresql.mdx +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: 'Query your existing PostgreSQL database with JavaScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing PostgreSQL database with JavaScript and Prisma ORM' -metaDescription: 'Write data to and query the PostgreSQL database with your JavaScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js showLineNumbers -const { PrismaClient } = require('@prisma/client') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -```js file=index.js showLineNumbers -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-sqlserver.mdx deleted file mode 100644 index ad979dd368..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-node-sqlserver.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: 'Query your existing SQL Server database with JavaScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing SQL Server database with JavaScript and Prisma ORM' -metaDescription: 'Write data to and query the SQL Server database with your JavaScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js showLineNumbers -const { PrismaClient } = require('@prisma/client') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). - -The following examples are all based on the models in the Prisma schema. - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```js file=index.js showLineNumbers -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-cockroachdb.mdx deleted file mode 100644 index 2bec040594..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-cockroachdb.mdx +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: 'Query your existing CockroachDB database with TypeScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing CockroachDB database with TypeScript and Prisma ORM' -metaDescription: 'Write data to and query the CockroachDB database with your TypeScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-cockroachdb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.ts` and add the following code to it: - -```ts file=index.ts showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). - -The following examples are all based on the models in the Prisma schema. - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts showLineNumbers -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { title: 'Hello World' }, - data: { published: true }, - }) - console.log(post) -} -``` - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-mysql.mdx deleted file mode 100644 index 7379468b73..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-mysql.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: 'Query your existing MySQL database with TypeScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing MySQL database with TypeScript and Prisma ORM' -metaDescription: 'Write data to and query the MySQL database with your TypeScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-mysql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.ts` and add the following code to it: - -```ts file=index.ts showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). - -The following examples are all based on the models in the Prisma schema. - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts showLineNumbers -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-planetscale.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-planetscale.mdx deleted file mode 100644 index 5339ab4605..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-planetscale.mdx +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: 'Query your existing PlanetScale database with TypeScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing PlanetScale database with TypeScript and Prisma ORM' -metaDescription: 'Write data to and query the PlanetScale database with your TypeScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-planetscale -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.ts` and add the following code to it: - -```ts file=index.ts showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). - -The following examples are all based on the models in the Prisma schema. - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts showLineNumbers -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-postgresql.mdx deleted file mode 100644 index 7cd5bf286b..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-postgresql.mdx +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: 'Query your existing PostgreSQL database with TypeScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing PostgreSQL database with TypeScript and Prisma ORM' -metaDescription: 'Write data to and query the PostgreSQL database with your TypeScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-postgresql -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.ts` and add the following code to it: - -```ts file=index.ts showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). - -The following examples are all based on the models in the Prisma schema. - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts showLineNumbers -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-sqlserver.mdx deleted file mode 100644 index ef0b41aa99..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/250-querying-the-database-typescript-sqlserver.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: 'Query your existing SQL Server database with TypeScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Query your existing SQL Server database with TypeScript and Prisma ORM' -metaDescription: 'Write data to and query the SQL Server database with your TypeScript and Prisma ORM project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-sqlserver -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- ---- - - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.ts` and add the following code to it: - -```ts file=index.ts showLineNumbers -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). - -The following examples are all based on the models in the Prisma schema. - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts showLineNumbers -async function main() { - const allUsers = await prisma.user.findMany() - console.log(allUsers) -} -``` - -Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - -If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. - -```no-copy -[] -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Alice', - email: 'alice@prisma.io', - posts: { - create: { title: 'Hello World' }, - }, - profile: { - create: { bio: 'I like turtles' }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - profile: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` - -Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts showLineNumbers -async function main() { - const post = await prisma.post.update({ - where: { id: 1 }, - data: { published: true }, - }) - console.log(post) -} -``` - -Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: - -```terminal copy -npx tsx index.ts -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-cockroachdb.mdx deleted file mode 100644 index 88aaf399c1..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-cockroachdb.mdx +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: 'Evolve your schema for a CockroachDB database in a Javascript project' -sidebar_label: 'Evolve your schema' -metaTitle: 'Evolve your Prisma schema with Prisma Migrate : JavaScript-CockroachDB' -metaDescription: 'Evolve your Prisma schema with Prisma Migrate inside of your JavaScript and CockroachDB project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema- ---- - -## Add a `Tag` model to your schema - -In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). - -For the purpose of this guide, we'll make the following changes to the Prisma schema: - -1. Create a new model called `Tag` with the following fields: - - `id`: an auto-incrementing integer that will be the primary key for the model - - `name`: a non-null `String` - - `posts`: an implicit many-to-many relation field that links to the `Post` model -2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model - -Once you've made the changes to your schema, your schema should resemble the one below: - -```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - user User @relation(fields: [authorId], references: [id]) - //edit-next-line - tags Tag[] -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - user User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - post Post[] - profile Profile? -} - -//edit-start -model Tag { - id Int @id @default(autoincrement()) - name String - posts Post[] -} -//edit-end -``` - -To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: - -```terminal copy -npx prisma migrate dev --name tags-model -``` - -This command will: - -1. Create a new SQL migration file for the migration -1. Apply the generated SQL migration to the database -1. Regenerate Prisma Client - -The following migration will be generated and saved in your `prisma/migrations` folder: - -```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers - -- CreateTable -CREATE TABLE "Tag" ( - "id" SERIAL NOT NULL, - "name" VARCHAR(255) NOT NULL, - - CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_PostToTag" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "_PostToTag_AB_unique" ON "_PostToTag"("A", "B"); - --- CreateIndex -CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); - --- AddForeignKey -ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; -``` diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-mysql.mdx deleted file mode 100644 index 7b3ed655e2..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-mysql.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: 'Evolve your schema for a MySQL database in a Javascript project' -sidebar_label: 'Evolve your schema' -metaTitle: 'Evolve your Prisma schema with Prisma Migrate : JavaScript-MySQL' -metaDescription: 'Evolve your Prisma schema with Prisma Migrate inside of your JavaScript and MySQL project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema- ---- - -## Add a `Tag` model to your schema - -In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). - -For the purpose of this guide, we'll make the following changes to the Prisma schema: - -1. Create a new model called `Tag` with the following fields: - - `id`: an auto-incrementing integer that will be the primary key for the model - - `name`: a non-null `String` - - `posts`: an implicit many-to-many relation field that links to the `Post` model -2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model - -Once you've made the changes to your schema, your schema should resemble the one below: - -```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - user User @relation(fields: [authorId], references: [id]) - //edit-next-line - tags Tag[] -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - user User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - post Post[] - profile Profile? -} - -//edit-start -model Tag { - id Int @id @default(autoincrement()) - name String - posts Post[] -} -//edit-end -``` - -To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: - -```terminal copy -npx prisma migrate dev --name tags-model -``` - -This command will: - -1. Create a new SQL migration file for the migration -1. Apply the generated SQL migration to the database -1. Regenerate Prisma Client - -The following migration will be generated and saved in your `prisma/migrations` folder: - -```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers --- CreateTable -CREATE TABLE Tag ( - id SERIAL NOT NULL, - name VARCHAR(255) NOT NULL, - - CONSTRAINT Tag_pkey PRIMARY KEY (id) -); - --- CreateTable -CREATE TABLE _PostToTag ( - A INTEGER NOT NULL, - B INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX _PostToTag_AB_unique ON _PostToTag(A, B); - --- CreateIndex -CREATE INDEX _PostToTag_B_index ON _PostToTag(B); - --- AddForeignKey -ALTER TABLE _PostToTag ADD CONSTRAINT _PostToTag_A_fkey FOREIGN KEY (A) REFERENCES Post(id) ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE _PostToTag ADD CONSTRAINT _PostToTag_B_fkey FOREIGN KEY (B) REFERENCES Tag(id) ON DELETE CASCADE ON UPDATE CASCADE; -``` - -Congratulations, you just evolved your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-postgresql.mdx deleted file mode 100644 index c9ac290123..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-postgresql.mdx +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: 'Evolve your schema for a PostgreSQL database in a Javascript project' -sidebar_label: 'Evolve your schema' -metaTitle: 'Evolve your Prisma schema with Prisma Migrate : JavaScript-PostgreSQL' -metaDescription: 'Evolve your Prisma schema with Prisma Migrate inside of your JavaScript and PostgreSQL project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema- ---- - -## Add a `Tag` model to your schema - -In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). - -For the purpose of this guide, we'll make the following changes to the Prisma schema: - -1. Create a new model called `Tag` with the following fields: - - `id`: an auto-incrementing integer that will be the primary key for the model - - `name`: a non-null `String` - - `posts`: an implicit many-to-many relation field that links to the `Post` model -2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model - -Once you've made the changes to your schema, your schema should resemble the one below: - -```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - user User @relation(fields: [authorId], references: [id]) - //edit-next-line - tags Tag[] -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - user User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - post Post[] - profile Profile? -} -//edit-start -model Tag { - id Int @id @default(autoincrement()) - name String - posts Post[] -} -//edit-end -``` - -To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: - -```terminal copy -npx prisma migrate dev --name tags-model -``` - -This command will: - -1. Create a new SQL migration file for the migration -1. Apply the generated SQL migration to the database -1. Regenerate Prisma Client - -The following migration will be generated and saved in your `prisma/migrations` folder: - -```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers - -- CreateTable -CREATE TABLE "Tag" ( - "id" SERIAL NOT NULL, - "name" VARCHAR(255) NOT NULL, - - CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_PostToTag" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "_PostToTag_AB_unique" ON "_PostToTag"("A", "B"); - --- CreateIndex -CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); - --- AddForeignKey -ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; -``` - -Congratulations, you just evolved your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-sqlserver.mdx deleted file mode 100644 index 93c06b95e2..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-node-sqlserver.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: 'Evolve your schema for a SQL Server database in a Javascript project' -sidebar_label: 'Evolve your schema' -metaTitle: 'Evolve your Prisma schema with Prisma Migrate : JavaScript-sqlserver' -metaDescription: 'Evolve your Prisma schema with Prisma Migrate inside of your JavaScript and SQL Server project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema- ---- - -## Add a `Tag` model to your schema - -In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). - -For the purpose of this guide, we'll make the following changes to the Prisma schema: - -1. Create a new model called `Tag` with the following fields: - - `id`: an auto-incrementing integer that will be the primary key for the model - - `name`: a non-null `String` - - `posts`: an implicit many-to-many relation field that links to the `Post` model -2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model - -Once you've made the changes to your schema, your schema should resemble the one below: - -```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - user User @relation(fields: [authorId], references: [id]) - //edit-next-line - tags Tag[] -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - user User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - post Post[] - profile Profile? -} - -//edit-start -model Tag { - id Int @id @default(autoincrement()) - name String - posts Post[] -} -//edit-end -``` - -To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: - -```terminal copy -npx prisma migrate dev --name tags-model -``` - -This command will: - -1. Create a new SQL migration file for the migration -1. Apply the generated SQL migration to the database -1. Regenerate Prisma Client - -The following migration will be generated and saved in your `prisma/migrations` folder: - -```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers - -- CreateTable -CREATE TABLE [dbo].[Tag] ( - [id] SERIAL NOT NULL, - [name] VARCHAR(255) NOT NULL, - - CONSTRAINT [Tag_pkey] PRIMARY KEY ([id]) -); - --- CreateTable -CREATE TABLE [dbo].[_PostToTag] ( - [A] INTEGER NOT NULL, - [B] INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX [_PostToTag_AB_unique] ON _PostToTag([A], [B]); - --- CreateIndex -CREATE INDEX [_PostToTag_B_index] ON [_PostToTag]([B]); - --- AddForeignKey -ALTER TABLE [dbo].[_PostToTag] ADD CONSTRAINT [_PostToTag_A_fkey] FOREIGN KEY ([A]) REFERENCES [dbo].[Post]([id]) ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE [dbo].[_PostToTag] ADD CONSTRAINT [_PostToTag_B_fkey] FOREIGN KEY ([B]) REFERENCES [dbo].[Tag]([id]) ON DELETE CASCADE ON UPDATE CASCADE; -``` - -Congratulations diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-cockroachdb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-cockroachdb.mdx deleted file mode 100644 index 328f9a3c03..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-cockroachdb.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: 'Evolve your schema for a CockroachDB database in a Typescript project' -sidebar_label: 'Evolve your schema' -metaTitle: 'Evolve your Prisma schema with Prisma Migrate : TypeScript-cockroachdb' -metaDescription: 'Evolve your Prisma schema with Prisma Migrate inside of your TypeScript and CockroachDB project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-cockroachdb -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema- ---- - -## Add a `Tag` model to your schema - -In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). - -For the purpose of this guide, we'll make the following changes to the Prisma schema: - -1. Create a new model called `Tag` with the following fields: - - `id`: an auto-incrementing integer that will be the primary key for the model - - `name`: a non-null `String` - - `posts`: an implicit many-to-many relation field that links to the `Post` model -2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model - -Once you've made the changes to your schema, your schema should resemble the one below: - -```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - user User @relation(fields: [authorId], references: [id]) - //edit-next-line - tags Tag[] -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - user User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - post Post[] - profile Profile? -} - -//edit-start -model Tag { - id Int @id @default(autoincrement()) - name String - posts Post[] -} -//edit-end -``` - -To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: - -```terminal copy -npx prisma migrate dev --name tags-model -``` - -This command will: - -1. Create a new SQL migration file for the migration -1. Apply the generated SQL migration to the database -1. Regenerate Prisma Client - -The following migration will be generated and saved in your `prisma/migrations` folder: - -```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers - -- CreateTable -CREATE TABLE "Tag" ( - "id" SERIAL NOT NULL, - "name" VARCHAR(255) NOT NULL, - - CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_PostToTag" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "_PostToTag_AB_unique" ON "_PostToTag"("A", "B"); - --- CreateIndex -CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); - --- AddForeignKey -ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; -``` - -Congratulations, you just evolved your database with Prisma Migrate 🚀 - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-mysql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-mysql.mdx deleted file mode 100644 index d810eddcb6..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-mysql.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: 'Evolve your schema for a MySQL database in a Typescript project' -sidebar_label: 'Evolve your schema' -metaTitle: 'Evolve your Prisma schema with Prisma Migrate : TypeScript-mysql' -metaDescription: 'Evolve your Prisma schema with Prisma Migrate inside of your TypeScript and MySQL project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-mysql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema- ---- - -## Add a `Tag` model to your schema - -In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). - -For the purpose of this guide, we'll make the following changes to the Prisma schema: - -1. Create a new model called `Tag` with the following fields: - - `id`: an auto-incrementing integer that will be the primary key for the model - - `name`: a non-null `String` - - `posts`: an implicit many-to-many relation field that links to the `Post` model -2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model - -Once you've made the changes to your schema, your schema should resemble the one below: - -```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - user User @relation(fields: [authorId], references: [id]) - //edit-next-line - tags Tag[] -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - user User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - post Post[] - profile Profile? -} - -//edit-start -model Tag { - id Int @id @default(autoincrement()) - name String - posts Post[] -} -//edit-end -``` - -To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: - -```terminal copy -npx prisma migrate dev --name tags-model -``` - -This command will: - -1. Create a new SQL migration file for the migration -1. Apply the generated SQL migration to the database -1. Regenerate Prisma Client - -The following migration will be generated and saved in your `prisma/migrations` folder: - -```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers --- CreateTable -CREATE TABLE Tag ( - id SERIAL NOT NULL, - name VARCHAR(255) NOT NULL, - - CONSTRAINT Tag_pkey PRIMARY KEY (id) -); - --- CreateTable -CREATE TABLE _PostToTag ( - A INTEGER NOT NULL, - B INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX _PostToTag_AB_unique ON _PostToTag(A, B); - --- CreateIndex -CREATE INDEX _PostToTag_B_index ON _PostToTag(B); - --- AddForeignKey -ALTER TABLE _PostToTag ADD CONSTRAINT _PostToTag_A_fkey FOREIGN KEY (A) REFERENCES Post(id) ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE _PostToTag ADD CONSTRAINT _PostToTag_B_fkey FOREIGN KEY (B) REFERENCES Tag(id) ON DELETE CASCADE ON UPDATE CASCADE; -``` - -Congratulations, you just evolved your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-postgresql.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-postgresql.mdx deleted file mode 100644 index 9159fff535..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-postgresql.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: 'Evolve your schema for a PostgreSQL database in a Typescript project' -sidebar_label: 'Evolve your schema' -metaTitle: 'Evolve your Prisma schema with Prisma Migrate : TypeScript-postgresql' -metaDescription: 'Evolve your Prisma schema with Prisma Migrate inside of your TypeScript and PostgreSQL project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-postgresql -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema- ---- - -## Add a `Tag` model to your schema - -In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). - -For the purpose of this guide, we'll make the following changes to the Prisma schema: - -1. Create a new model called `Tag` with the following fields: - - `id`: an auto-incrementing integer that will be the primary key for the model - - `name`: a non-null `String` - - `posts`: an implicit many-to-many relation field that links to the `Post` model -2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model - -Once you've made the changes to your schema, your schema should resemble the one below: - -```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - user User @relation(fields: [authorId], references: [id]) - //edit-next-line - tags Tag[] -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - user User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - post Post[] - profile Profile? -} - -//edit-start -model Tag { - id Int @id @default(autoincrement()) - name String - posts Post[] -} -//edit-end -``` - -To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: - -```terminal copy -npx prisma migrate dev --name tags-model -``` - -This command will: - -1. Create a new SQL migration file for the migration -1. Apply the generated SQL migration to the database -1. Regenerate Prisma Client - -The following migration will be generated and saved in your `prisma/migrations` folder: - -```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers - -- CreateTable -CREATE TABLE "Tag" ( - "id" SERIAL NOT NULL, - "name" VARCHAR(255) NOT NULL, - - CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_PostToTag" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "_PostToTag_AB_unique" ON "_PostToTag"("A", "B"); - --- CreateIndex -CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); - --- AddForeignKey -ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; -``` - - - -Congratulations, you just evolved your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-sqlserver.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-sqlserver.mdx deleted file mode 100644 index 4b98a336f0..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/275-evolve-your-schema-typescript-sqlserver.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: 'Evolve your schema for a SQL Server database in a Typescript project' -sidebar_label: 'Evolve your schema' -metaTitle: 'Evolve your Prisma schema with Prisma Migrate : TypeScript-sql-server' -metaDescription: 'Evolve your Prisma schema with Prisma Migrate inside of your TypeScript and SQL Server project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'cockroachdb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-sqlserver -pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema- ---- - -## Add a `Tag` model to your schema - -In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). - -For the purpose of this guide, we'll make the following changes to the Prisma schema: - -1. Create a new model called `Tag` with the following fields: - - `id`: an auto-incrementing integer that will be the primary key for the model - - `name`: a non-null `String` - - `posts`: an implicit many-to-many relation field that links to the `Post` model -2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model - -Once you've made the changes to your schema, your schema should resemble the one below: - -```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers -model Post { - id Int @id @default(autoincrement()) - title String @db.VarChar(255) - createdAt DateTime @default(now()) @db.Timestamp(6) - content String? - published Boolean @default(false) - authorId Int - user User @relation(fields: [authorId], references: [id]) - //edit-next-line - tags Tag[] -} - -model Profile { - id Int @id @default(autoincrement()) - bio String? - userId Int @unique - user User @relation(fields: [userId], references: [id]) -} - -model User { - id Int @id @default(autoincrement()) - name String? @db.VarChar(255) - email String @unique @db.VarChar(255) - post Post[] - profile Profile? -} - -//edit-start -model Tag { - id Int @id @default(autoincrement()) - name String - posts Post[] -} -//edit-end -``` - -To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: - -```terminal copy -npx prisma migrate dev --name tags-model -``` - -This command will: - -1. Create a new SQL migration file for the migration -1. Apply the generated SQL migration to the database -1. Regenerate Prisma Client - -The following migration will be generated and saved in your `prisma/migrations` folder: - -```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers - -- CreateTable -CREATE TABLE [dbo].[Tag] ( - [id] SERIAL NOT NULL, - [name] VARCHAR(255) NOT NULL, - - CONSTRAINT [Tag_pkey] PRIMARY KEY ([id]) -); - --- CreateTable -CREATE TABLE [dbo].[_PostToTag] ( - [A] INTEGER NOT NULL, - [B] INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX [_PostToTag_AB_unique] ON _PostToTag([A], [B]); - --- CreateIndex -CREATE INDEX [_PostToTag_B_index] ON [_PostToTag]([B]); - --- AddForeignKey -ALTER TABLE [dbo].[_PostToTag] ADD CONSTRAINT [_PostToTag_A_fkey] FOREIGN KEY ([A]) REFERENCES [dbo].[Post]([id]) ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE [dbo].[_PostToTag] ADD CONSTRAINT [_PostToTag_B_fkey] FOREIGN KEY ([B]) REFERENCES [dbo].[Tag]([id]) ON DELETE CASCADE ON UPDATE CASCADE; -``` - -Congratulations, you just evolved your database with Prisma Migrate 🚀 diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/300-next-steps.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/300-next-steps.mdx deleted file mode 100644 index 9cbb67caa6..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/300-next-steps.mdx +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: 'Next steps after adding Prisma ORM to your existing project' -sidebar_label: 'Next steps' -metaTitle: 'Next steps after adding Prisma ORM to your existing project' -metaDescription: 'Next steps to take now that you have successfully added Prisma ORM to your relational database project' -hide_table_of_contents: true ---- - -This section lists a number of potential next steps you can now take from here. Feel free to explore these or read the [Introduction](/orm/overview/introduction/what-is-prisma) page to get a high-level overview of Prisma ORM. - -### Continue exploring the Prisma Client API - -You can send a variety of queries with the Prisma Client API. Check out the [API reference](/orm/prisma-client) and use your existing database setup from this guide to try them out. - -:::tip - -You can use your editor's auto-completion feature to learn about the different API calls and the arguments it takes. Auto-completion is commonly invoked by hitting CTRL+SPACE on your keyboard. - -::: - -
-Expand for more Prisma Client API examples - -Here are a few suggestions for a number of more queries you can send with Prisma Client: - -**Filter all `Post` records that contain `"hello"`** - -```js -const filteredPosts = await prisma.post.findMany({ - where: { - OR: [ - { title: { contains: "hello" }, - { content: { contains: "hello" }, - ], - }, -}) -``` - -**Create a new `Post` record and connect it to an existing `User` record** - -```js -const post = await prisma.post.create({ - data: { - title: 'Join us for Prisma Day 2020', - author: { - connect: { email: 'alice@prisma.io' }, - }, - }, -}) -``` - -**Use the fluent relations API to retrieve the `Post` records of a `User` by traversing the relations** - -```js -const posts = await prisma.profile - .findUnique({ - where: { id: 1 }, - }) - .user() - .posts() -``` - -**Delete a `User` record** - -```js -const deletedUser = await prisma.user.delete({ - where: { email: 'sarah@prisma.io' }, -}) -``` - -
- -### Build an app with Prisma ORM - -The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - -- [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) -- [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) -- [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) - -### Explore the data in Prisma Studio - -Prisma Studio is a visual editor for the data in your database. Run `npx prisma studio` in your terminal. - -### Get query insights and analytics with Prisma Optimize - -[Prisma Optimize](/optimize) helps you generate insights and provides recommendations that can help you make your database queries faster. [Try it out now!](/optimize/getting-started) - -Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. - -### Change the database schema (e.g. add more tables) - -To evolve the app, you need to follow the same flow of the tutorial: - -1. Manually adjust your database schema using SQL -1. Re-introspect your database -1. Optionally re-configure your Prisma Client API -1. Re-generate Prisma Client - -![Introspect workflow](/img/getting-started/prisma-evolve-app-workflow.png) - -### Try a Prisma ORM example - -The [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository contains a number of ready-to-run examples: - -| Demo | Stack | Description | -| :------------------------------------------------------------------------------------------------------------------ | :----------- | --------------------------------------------------------------------------------------------------- | -| [`nextjs`](https://pris.ly/e/orm/nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app | -| [`nextjs-graphql`](https://pris.ly/e/ts/graphql-nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app (React) with a GraphQL API | -| [`graphql-nexus`](https://pris.ly/e/ts/graphql-nexus) | Backend only | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) | -| [`express`](https://pris.ly/e/ts/rest-express) | Backend only | Simple REST API with Express.JS | -| [`grpc`](https://pris.ly/e/ts/grpc) | Backend only | Simple gRPC API | diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/_install-prisma-client-partial.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/_install-prisma-client-partial.mdx deleted file mode 100644 index 2bf6ab6d15..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases/_install-prisma-client-partial.mdx +++ /dev/null @@ -1,25 +0,0 @@ -## Install and generate Prisma Client - -To get started with Prisma Client, first install the `@prisma/client` package: - -```terminal copy -npm install @prisma/client -``` - -Then, run `prisma generate` which reads your Prisma schema and generates the Prisma Client. - -```terminal copy -npx prisma generate -``` - -You can now import the `PrismaClient` constructor from the `@prisma/client` package to create an instance of Prisma Client to send queries to your database. You'll learn how to do that in the next section. - -:::note Good to know - -When you run `prisma generate`, you are actually creating code (TypeScript types, methods, queries, ...) that is tailored to _your_ Prisma schema file or files in the `prisma` directory. This means, that whenever you make changes to your Prisma schema file, you also need to update the Prisma Client. You can do this by running the `prisma generate` command. - -![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) - -Whenever you update your Prisma schema, you will have to update your database schema using either `prisma migrate dev` or `prisma db push`. This will keep your database schema in sync with your Prisma schema. These commands will also run `prisma generate` under the hood to re-generate your Prisma Client. - -::: diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb-node-mongodb.mdx deleted file mode 100644 index 92366024f7..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb-node-mongodb.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing MongoDB project using JavaScript' -sidebar_label: 'MongoDB' -metaTitle: 'Add Prisma ORM to an existing MongoDB project using JavaScript (15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing Node.js project by connecting it to your MongoDB database and generating a Prisma Client for database access.' -toc: false -langSwitcher: ['typescript', 'node'] -hide_table_of_contents: true -dbSwitcher: ['mongodb'] -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database-node-mongodb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb- ---- - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -If you're migrating to Prisma ORM from Mongoose, see our [Migrate from Mongoose guide](/guides/migrate-from-mongoose). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). - - - - The MongoDB database connector uses transactions to support nested writes. Transactions **requires** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. - - - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -## Set up Prisma ORM - -As a first step, navigate into it your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb-typescript-mongodb.mdx deleted file mode 100644 index fec31143a6..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb-typescript-mongodb.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Add Prisma ORM to an existing MongoDB project using TypeScript ' -sidebar_label: 'MongoDB' -metaTitle: 'Add Prisma ORM to an existing MongoDB project using TypeScript (15 min)' -metaDescription: 'Learn how to add Prisma ORM to an existing TypeScript project by connecting it to your MongoDB database and generating a Prisma Client for database access.' -hide_table_of_contents: true -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -sidebar_custom_props: { badge: '15 min' } -sidebar_class_name: hidden-sidebar -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database-typescript-mongodb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb- ---- - -Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). - - - -If you're migrating to Prisma ORM from Mongoose, see our [Migrate from Mongoose guide](/guides/migrate-from-mongoose). - - - -## Prerequisites - -In order to successfully complete this guide, you need: - -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) -- Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). - - - - The MongoDB database connector uses transactions to support nested writes. Transactions **requires** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. - - - -Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). - -> See [System requirements](/orm/reference/system-requirements) for exact version requirements. - -## Set up Prisma ORM - -As a first step, navigate into it your project directory that contains the `package.json` file. - -Next, add the Prisma CLI as a development dependency to your project: - -```terminal copy -npm install prisma --save-dev -``` - -:::note - -If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. - -::: - -import PrismaInitPartial from './_prisma-init-partial.mdx' - - - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/100-connect-your-database-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/100-connect-your-database-node-mongodb.mdx deleted file mode 100644 index 09e3fd39de..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/100-connect-your-database-node-mongodb.mdx +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: 'Connect MongoDB to your existing Node.js project' -sidebar_label: 'Connect your database (MongoDB)' -metaTitle: 'Connect your MongoDB database' -metaDescription: 'Connect your MongoDB database to your existing Node.js project' -langSwitcher: ['typescript', 'node'] -sidebar_class_name: hidden-sidebar -hide_table_of_contents: true -dbSwitcher: ['mongodb'] -toc: false -pagination_prev: getting-started/setup-prisma/add-to-existing-project/mongodb-node-mongodb -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/introspection-node-mongodb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: - -```bash file=.env showLineNumbers -DATABASE_URL="mongodb+srv://test:test@cluster0.ns1yp.mongodb.net/myFirstDatabase" -``` - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For MongoDB, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USERNAME`: The name of your database user -- `PASSWORD`: The password for your database user -- `HOST`: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running -- `PORT`: The port where your database server is running (typically `27017` for MongoDB) -- `DATABASE`: The name of the database. Note that if you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. - -## Troubleshooting - -### `Error in connector: SCRAM failure: Authentication failed.` - -If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. - -### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` - -If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/100-connect-your-database-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/100-connect-your-database-typescript-mongodb.mdx deleted file mode 100644 index f53849a73d..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/100-connect-your-database-typescript-mongodb.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: 'Connect your MongoDB database to your existing TypeScript project' -sidebar_label: 'Connect your database (MongoDB)' -metaTitle: 'Connect your MongoDB database using TypeScript' -metaDescription: 'Connect your MongoDB database to your existing TypeScript project' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/mongodb-typescript-mongodb -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/introspection-typescript-mongodb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database- ---- - -## Connecting your database - -To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} -``` - -In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: - -```bash file=.env showLineNumbers -DATABASE_URL="mongodb+srv://test:test@cluster0.ns1yp.mongodb.net/myFirstDatabase" -``` - -You now need to adjust the connection URL to point to your own database. - -The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For MongoDB, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): - -```no-lines -mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE -``` - -Here's a short explanation of each component: - -- `USERNAME`: The name of your database user -- `PASSWORD`: The password for your database user -- `HOST`: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running -- `PORT`: The port where your database server is running (typically `27017` for MongoDB) -- `DATABASE`: The name of the database. Note that if you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. - -## Troubleshooting - -### `Error in connector: SCRAM failure: Authentication failed.` - -If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. - -### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` - -If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/125-introspection-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/125-introspection-node-mongodb.mdx deleted file mode 100644 index 7d4f30e8f9..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/125-introspection-node-mongodb.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: 'Introspection for MongoDB in a JavaScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection: MongoDB and JavaScript' -metaDescription: 'Introspect your MongoDB database with Prisma ORM' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database-node-mongodb -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client-node-mongodb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb/introspection- ---- - - -Prisma ORM introspects a MongoDB schema by sampling the data stored in the given database and inferring the schema of that data. - -For the purposes of illustrating introspection, this guide will help you setup a MongoDB from scratch. But if you have a MongoDB database already, feel free to jump to [Initializing Prisma ORM](#initializing-prisma-orm) in your project. - -## Setting up your Database - -To see this in action, first create a `blog` database with 2 collections: `User` and `Post`. We recommend [MongoDB Compass](https://www.mongodb.com/products/tools/compass) for setting this up: - -![Create a blog database using Compass](/img/getting-started/1-create-database.jpg) - -First, add a user to our `User` collection: - -![Create a user within the User collection](/img/getting-started/2-create-user.jpg) - -Next, add some posts to our `Post` collection. It's important that the ObjectID in `userId` matches the user you created above. - -![Create some posts within the Post collection](/img/getting-started/3-create-posts.jpg) - -## Initializing Prisma ORM - -Now that you have a MongoDB database, the next step is to create a new project and initialize Prisma ORM: - -```terminal copy -mkdir blog -cd blog -npm init -y -npm install -D prisma -npx prisma init --datasource-provider mongodb --output ../generated/prisma -``` - -Initializing Prisma ORM will create a `prisma/schema.prisma` file like the following: - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} -``` - -Next you'll need to adjust your `.env` file to point the `DATABASE_URL` to your MongoDB database - -## Introspecting MongoDB with Prisma ORM - -You're now ready to introspect. Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command introspects our database and writes the inferred schema into your `prisma/schema.prisma` file: - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} - -model Post { - id String @id @default(auto()) @map("_id") @db.ObjectId - title String - userId String @db.ObjectId -} - -model User { - id String @id @default(auto()) @map("_id") @db.ObjectId - email String -} -``` - -## Tweaking the Schema - -To be able to join data using Prisma Client, you can add the [`@relation`](/orm/reference/prisma-schema-reference#relation) attributes to our models: - -```prisma file=prisma/schema.prisma highlight=14;add|20;add showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} - -model Post { - id String @id @default(auto()) @map("_id") @db.ObjectId - title String - userId String @db.ObjectId - //add-next-line - user User @relation(fields: [userId], references: [id]) -} - -model User { - id String @id @default(auto()) @map("_id") @db.ObjectId - email String - //add-next-line - posts Post[] -} -``` - -:::tip - -We're actively working on MongoDB introspection. Provide feedback for this feature in [this issue](https://github.com/prisma/prisma/issues/8241). - -::: - -And with that, you're ready to generate Prisma Client. - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/125-introspection-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/125-introspection-typescript-mongodb.mdx deleted file mode 100644 index d7f371fc9f..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/125-introspection-typescript-mongodb.mdx +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: 'Introspection for MongoDB in a TypeScript project' -sidebar_label: 'Introspection' -metaTitle: 'Introspection: MongoDB and TypeScript' -metaDescription: 'Introspection your MongoDB database with Prisma ORM' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database-typescript-mongodb -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client-typescript-mongodb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb/introspection- ---- - -# Introspection - -Prisma ORM introspects a MongoDB schema by sampling the data stored in the given database and inferring the schema of that data. - -For the purposes of illustrating introspection, this guide will help you setup a MongoDB from scratch. But if you have a MongoDB database already, feel free to jump to [Initializing Prisma ORM](#initializing-prisma-orm) in your project. - -## Setting up your Database - -To see this in action, first create a `blog` database with 2 collections: `User` and `Post`. We recommend [MongoDB Compass](https://www.mongodb.com/products/tools/compass) for setting this up: - -![Create a blog database using Compass](/img/getting-started/1-create-database.jpg) - -First, add a user to our `User` collection: - -![Create a user within the User collection](/img/getting-started/2-create-user.jpg) - -Next, add some posts to our `Post` collection. It's important that the ObjectID in `userId` matches the user you created above. - -![Create some posts within the Post collection](/img/getting-started/3-create-posts.jpg) - -## Initializing Prisma ORM - -Now that you have a MongoDB database, the next step is to create a new project and initialize Prisma ORM: - -```terminal copy -mkdir blog -cd blog -npm init -y -npm install -D prisma -npx prisma init --datasource-provider mongodb --output ../generated/prisma -``` - -Initializing Prisma ORM will create a `prisma/schema.prisma` file. Edit this file to use MongoDB: - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} -``` - -Next you'll need to adjust your `.env` file to point the `DATABASE_URL` to your MongoDB database - -## Introspecting MongoDB with Prisma ORM - -You're now ready to introspect. Run the following command to introspect your database: - -```terminal copy -npx prisma db pull -``` - -This command introspects our database and writes the inferred schema into your `prisma/schema.prisma` file: - -```prisma file=prisma/schema.prisma showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} - -model Post { - id String @id @default(auto()) @map("_id") @db.ObjectId - title String - userId String @db.ObjectId -} - -model User { - id String @id @default(auto()) @map("_id") @db.ObjectId - email String -} -``` - -## Tweaking the Schema - -To be able to join data using Prisma Client, you can add the [`@relation`](/orm/reference/prisma-schema-reference#relation) attributes to our models: - -```prisma file=prisma/schema.prisma highlight=14;add|20;add showLineNumbers -datasource db { - provider = "mongodb" - url = env("DATABASE_URL") -} - -generator client { - provider = "prisma-client-js" -} - -model Post { - id String @id @default(auto()) @map("_id") @db.ObjectId - title String - userId String @db.ObjectId - //add-next-line - user User @relation(fields: [userId], references: [id]) -} - -model User { - id String @id @default(auto()) @map("_id") @db.ObjectId - email String - //add-next-line - posts Post[] -} -``` - -:::tip - -We're actively working on MongoDB introspection. Provide feedback for this feature in [this issue](https://github.com/prisma/prisma/issues/8241). - -::: - -And with that, you're ready to generate Prisma Client. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/200-install-prisma-client-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/200-install-prisma-client-node-mongodb.mdx deleted file mode 100644 index 77bfa807a1..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/200-install-prisma-client-node-mongodb.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: 'Install Prisma Client in your existing JavaScript project (MongoDB)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project: JavaScript and MongoDB' -metaDescription: 'Install and generate Prisma Client in your existing project using a MongoDB database and Javascript.' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/mongodb/introspection-node-mongodb -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/querying-the-database-node-mongodb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client- ---- - -## Install and generate Prisma Client - -To get started with Prisma Client, you need to install the `@prisma/client` package: - -```terminal copy -npm install @prisma/client -``` - -The install command invokes `prisma generate` for you which reads your Prisma schema and generates a version of Prisma Client that is _tailored_ to your models. - -![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) - -Whenever you make changes to your Prisma schema in the future, you manually need to invoke `prisma generate` in order to accommodate the changes in your Prisma Client API. - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/200-install-prisma-client-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/200-install-prisma-client-typescript-mongodb.mdx deleted file mode 100644 index a7b90e1c75..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/200-install-prisma-client-typescript-mongodb.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: 'Install Prisma Client in an existing TypeScript project (MongoDB)' -sidebar_label: 'Install Prisma Client' -metaTitle: 'Install Prisma Client in your existing project: TypeScript and MongoDB' -metaDescription: 'Install and generate Prisma Client in your existing project using a MongoDB database and TypeScript.' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/mongodb/introspection-typescript-mongodb -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/querying-the-database-typescript-mongodb -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client- ---- - -## Install and generate Prisma Client - -To get started with Prisma Client, you need to install the `@prisma/client` package: - -```terminal copy -npm install @prisma/client -``` - -The install command invokes `prisma generate` for you which reads your Prisma schema and generates a version of Prisma Client that is _tailored_ to your models. - -![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) - -Whenever you make changes to your Prisma schema in the future, you manually need to invoke `prisma generate` in order to accommodate the changes in your Prisma Client API. diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/250-querying-the-database-node-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/250-querying-the-database-node-mongodb.mdx deleted file mode 100644 index e82d311963..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/250-querying-the-database-node-mongodb.mdx +++ /dev/null @@ -1,220 +0,0 @@ ---- -title: 'Query your existing MongoDB database with JavaScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database in your existing project: MongoDB and JavaScript' -metaDescription: 'Write data to and query your MongoDB database in your existing project.' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -sidebar_class_name: hidden-sidebar -pagination_prev: getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client-node-mongodb -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.js` and add the following code to it: - -```js file=index.js copy -const { PrismaClient } = require('@prisma/client') - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Connect to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```js file=index.js showLineNumbers -async function main() { -- // ... you will write your Prisma Client queries here -//add-start -+ const allUsers = await prisma.user.findMany() -+ console.log(allUsers) -//add-end -} -``` - -Now run the code with this command: - -```terminal copy -node index.js -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Comment` tables. - -Adjust the `main` function to send a `create` query to the database: - -```js file=index.js copy showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Rich', - email: 'hello@prisma.com', - posts: { - create: { - title: 'My first post', - body: 'Lots of really interesting stuff', - slug: 'my-first-post', - }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with a new `Post` using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the other one via the `Post.author` ↔ `User.posts` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -node index.js -``` - -The output should look similar to this: - -```json no-lines -[ - { - id: '60cc9b0e001e3bfd00a6eddf', - email: 'hello@prisma.com', - name: 'Rich', - posts: [ - { - id: '60cc9bad005059d6007f45dd', - slug: 'my-first-post', - title: 'My first post', - body: 'Lots of really interesting stuff', - userId: '60cc9b0e001e3bfd00a6eddf', - }, - ], - }, -] -``` - -The query added new records to the `User` and the `Post` collections: - - - -The `id` field in the Prisma schema maps to `_id` in the underlying MongoDB database. - - - -**User** collection - -| **\_id** | **email** | **name** | -| :------------------------- | :------------------- | :------- | -| `60cc9b0e001e3bfd00a6eddf` | `"hello@prisma.com"` | `"Rich"` | - -**Post** collection - -| **\_id** | **createdAt** | **title** | **content** | **published** | **authorId** | -| :------------------------- | :------------------------- | :---------------- | :--------------------------------- | :------------ | :------------------------- | -| `60cc9bad005059d6007f45dd` | `2020-03-21T16:45:01.246Z` | `"My first post"` | `Lots of really interesting stuff` | `false` | `60cc9b0e001e3bfd00a6eddf` | - -> **Note**: The unique identifier in the `authorId` document field on `Post` reference the `_id` document field in the `User` collection, meaning the `_id` value `60cc9b0e001e3bfd00a6eddf` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll add a couple of comments to the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```js file=index.js copy -async function main() { - await prisma.post.update({ - where: { - slug: 'my-first-post', - }, - data: { - comments: { - createMany: { - data: [ - { comment: 'Great post!' }, - { comment: "Can't wait to read more!" }, - ], - }, - }, - }, - }) - const posts = await prisma.post.findMany({ - include: { - comments: true, - }, - }) - - console.dir(posts, { depth: Infinity }) -} -``` - -Now run the code using the same command as before: - -```terminal copy -node index.js -``` - -You will see the following output: - -```json no-lines -[ - { - id: '60cc9bad005059d6007f45dd', - slug: 'my-first-post', - title: 'My first post', - body: 'Lots of really interesting stuff', - userId: '60cc9b0e001e3bfd00a6eddf', - comments: [ - { - id: '60cca420008a21d800578793', - postId: '60cca40300af8bf000f6ca99', - comment: 'Great post!', - }, - { - id: '60cca420008a21d800578794', - postId: '60cca40300af8bf000f6ca99', - comment: "Can't wait to try this!", - }, - ], - }, -] -``` - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 - diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/250-querying-the-database-typescript-mongodb.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/250-querying-the-database-typescript-mongodb.mdx deleted file mode 100644 index 08f3d9ec9a..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/250-querying-the-database-typescript-mongodb.mdx +++ /dev/null @@ -1,234 +0,0 @@ ---- -title: 'Query your existing MongoDB database with TypeScript and Prisma ORM' -sidebar_label: 'Querying the database' -metaTitle: 'Querying the database in your existing project: MongoDB and TypeScript' -metaDescription: 'Write data to and query your MongoDB database' -langSwitcher: ['typescript', 'node'] -dbSwitcher: ['mongodb'] -hide_table_of_contents: true -pagination_prev: getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client-typescript-mongodb -pagination_next: getting-started/setup-prisma/add-to-existing-project/mongodb/next-steps -slugSwitch: /getting-started/setup-prisma/add-to-existing-project/mongodb/querying-the-database- ---- - -## Write your first query with Prisma Client - -Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. - -If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. - -For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). - -Create a new file named `index.ts` and add the following code to it: - -```js file=index.ts copy -import { PrismaClient } from './generated/prisma' - -const prisma = new PrismaClient() - -async function main() { - // ... you will write your Prisma Client queries here -} - -main() - .then(async () => { - await prisma.$disconnect() - }) - .catch(async (e) => { - console.error(e) - await prisma.$disconnect() - process.exit(1) - }) -``` - -Here's a quick overview of the different parts of the code snippet: - -1. Import the `PrismaClient` constructor from the `@prisma/client` node module -1. Instantiate `PrismaClient` -1. Define an `async` function named `main` to send queries to the database -1. Connect to the database -1. Call the `main` function -1. Close the database connections when the script terminates - -Inside the `main` function, add the following query to read all `User` records from the database and print the result: - -```ts file=index.ts showLineNumbers -async function main() { - // ... you will write your Prisma Client queries here -//add-start -+ const allUsers = await prisma.user.findMany() -+ console.log(allUsers) -//add-end -} -``` - -Now run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -If you introspected an existing database with records, the query should return an array of JavaScript objects. - -## Write data into the database - -The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Comment` tables. - -Adjust the `main` function to send a `create` query to the database: - -```ts file=index.ts copy showLineNumbers -async function main() { - await prisma.user.create({ - data: { - name: 'Rich', - email: 'hello@prisma.com', - posts: { - create: { - title: 'My first post', - body: 'Lots of really interesting stuff', - slug: 'my-first-post', - }, - }, - }, - }) - - const allUsers = await prisma.user.findMany({ - include: { - posts: true, - }, - }) - console.dir(allUsers, { depth: null }) -} -``` - -This code creates a new `User` record together with a new `Post` using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the other one via the `Post.author` ↔ `User.posts` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. - -Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` relations on the returned `User` objects. - -Run the code with this command: - -```terminal copy -npx tsx index.ts -``` - -The output should look similar to this: - -```json no-lines -[ - { - id: '60cc9b0e001e3bfd00a6eddf', - email: 'hello@prisma.com', - name: 'Rich', - posts: [ - { - id: '60cc9bad005059d6007f45dd', - slug: 'my-first-post', - title: 'My first post', - body: 'Lots of really interesting stuff', - userId: '60cc9b0e001e3bfd00a6eddf', - }, - ], - }, -] -``` - -Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: - -```ts no-lines showLineNumbers -const allUsers: (User & { - posts: Post[] -})[] - -export type Post = { - id: number - title: string - body: string | null - published: boolean - authorId: number | null -} -``` - -The query added new records to the `User` and the `Post` collections: - - - -The `id` field in the Prisma schema maps to `_id` in the underlying MongoDB database. - - - -**User** collection - -| **\_id** | **email** | **name** | -| :------------------------- | :------------------- | :------- | -| `60cc9b0e001e3bfd00a6eddf` | `"hello@prisma.com"` | `"Rich"` | - -**Post** collection - -| **\_id** | **createdAt** | **title** | **content** | **published** | **authorId** | -| :------------------------- | :------------------------- | :---------------- | :--------------------------------- | :------------ | :------------------------- | -| `60cc9bad005059d6007f45dd` | `2020-03-21T16:45:01.246Z` | `"My first post"` | `Lots of really interesting stuff` | `false` | `60cc9b0e001e3bfd00a6eddf` | - -> **Note**: The unique identifier in the `authorId` document field on `Post` reference the `_id` document field in the `User` collection, meaning the `_id` value `60cc9b0e001e3bfd00a6eddf` column therefore refers to the first (and only) `User` record in the database. - -Before moving on to the next section, you'll add a couple of comments to the `Post` record you just created using an `update` query. Adjust the `main` function as follows: - -```ts file=index.ts copy showLineNumbers -async function main() { - await prisma.post.update({ - where: { - slug: 'my-first-post', - }, - data: { - comments: { - createMany: { - data: [ - { comment: 'Great post!' }, - { comment: "Can't wait to read more!" }, - ], - }, - }, - }, - }) - const posts = await prisma.post.findMany({ - include: { - comments: true, - }, - }) - - console.dir(posts, { depth: Infinity }) -} -``` - -Now run the code using the same command as before: - -```terminal copy -npx tsx index.ts -``` - -You will see the following output: - -```json no-lines -[ - { - id: '60cc9bad005059d6007f45dd', - slug: 'my-first-post', - title: 'My first post', - body: 'Lots of really interesting stuff', - userId: '60cc9b0e001e3bfd00a6eddf', - comments: [ - { - id: '60cca420008a21d800578793', - postId: '60cca40300af8bf000f6ca99', - comment: 'Great post!', - }, - { - id: '60cca420008a21d800578794', - postId: '60cca40300af8bf000f6ca99', - comment: "Can't wait to try this!", - }, - ], - }, -] -``` - -Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/300-next-steps.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/300-next-steps.mdx deleted file mode 100644 index a088fcdf0f..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb/300-next-steps.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: 'Next steps after adding Prisma ORM to an existing project using MongoDB' -sidebar_label: 'Next steps' -metaTitle: 'Next steps after adding Prisma ORM to an existing project using MongoDB' -metaDescription: 'Next steps to take now that you have successfully added Prisma ORM to your existing Node.js or TypeScript project.' -hide_table_of_contents: true ---- - -This section lists a number of potential next steps you can now take from here. Feel free to explore these or read the [Introduction](/orm/overview/introduction/what-is-prisma) page to get a high-level overview of Prisma ORM. - -### Continue exploring the Prisma Client API - -You can send a variety of queries with the Prisma Client API. Check out the [API reference](/orm/prisma-client) and use your existing database setup from this guide to try them out. - -:::tip - -You can use your editor's auto-completion feature to learn about the different API calls and the arguments it takes. Auto-completion is commonly invoked by hitting CTRL+SPACE on your keyboard. - -::: - -
-Expand for more Prisma Client API examples - -Here are a few suggestions for a number of more queries you can send with Prisma Client: - -**Filter all `Post` records that contain `"hello"`** - -```js -const filteredPosts = await prisma.post.findMany({ - where: { - OR: [{ title: { contains: 'hello' } }, { body: { contains: 'hello' } }], - }, -}) -``` - -**Create a new `Post` record and connect it to an existing `User` record** - -```js -const post = await prisma.post.create({ - data: { - title: 'Join us for Prisma Day 2020', - slug: 'prisma-day-2020', - body: 'A conference on modern application development and databases.', - user: { - connect: { email: 'hello@prisma.com' }, - }, - }, -}) -``` - -**Use the fluent relations API to retrieve the `Post` records of a `User` by traversing the relations** - -```js -const user = await prisma.comment - .findUnique({ - where: { id: '60ff4e9500acc65700ebf470' }, - }) - .post() - .user() -``` - -**Delete a `User` record** - -```js -const deletedUser = await prisma.user.delete({ - where: { email: 'sarah@prisma.io' }, -}) -``` - -
- -### Build an app with Prisma ORM - -The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - -- [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) -- [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) -- [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) - -### Explore the data in Prisma Studio - -Prisma Studio is a visual editor for the data in your database. Run `npx prisma studio` in your terminal. - -### Try a Prisma ORM example - -The [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository contains a number of ready-to-run examples: - -| Demo | Stack | Description | -| :------------------------------------------------------------------------------------------------------------------ | :----------- | --------------------------------------------------------------------------------------------------- | -| [`nextjs`](https://pris.ly/e/orm/nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app | -| [`nextjs-graphql`](https://pris.ly/e/ts/graphql-nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app (React) with a GraphQL API | -| [`graphql-nexus`](https://pris.ly/e/ts/graphql-nexus) | Backend only | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) | -| [`express`](https://pris.ly/e/ts/rest-express) | Backend only | Simple REST API with Express.JS | -| [`grpc`](https://pris.ly/e/ts/grpc) | Backend only | Simple gRPC API | diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/_prisma-init-partial.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/_prisma-init-partial.mdx deleted file mode 100644 index 4fdfa6d8f3..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/_prisma-init-partial.mdx +++ /dev/null @@ -1,33 +0,0 @@ -import CodeBlock from '@theme/CodeBlock'; - -You can now invoke the Prisma CLI by prefixing it with `npx`: - -```terminal -npx prisma -``` - -:::info - -See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma ORM using a different package manager. - -::: - -Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: - -{`npx prisma init --datasource-provider ${props.datasource.toLowerCase()} --output ../generated/prisma`} - -This command does a few things: - -- Creates a new directory called `prisma` that contains a file called `schema.prisma`, which contains the Prisma Schema with your database connection variable and schema models. -- Sets the `datasource` to {props.datasource} and the output to a custom location, respectively. -- Creates the [`.env` file](/orm/more/development-environment/environment-variables) in the root directory of the project, which is used for defining environment variables (such as your database connection) - -Note that the default schema created by `prisma init` uses PostgreSQL as the `provider`. If you didn't specify a provider with the `datasource-provider` option, you need to edit the `datasource` block to use the {props.datasource.toLowerCase()} provider instead: - - -{`datasource db { - //edit-next-line - provider = "${props.datasource.toLowerCase()}" - url = env("DATABASE_URL") -}`} - \ No newline at end of file diff --git a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/index.mdx b/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/index.mdx deleted file mode 100644 index 142fedb80d..0000000000 --- a/content/100-getting-started/02-setup-prisma/200-add-to-existing-project/index.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: 'Add to existing project' -metaTitle: 'Add Prisma ORM to an existing project' -metaDescription: 'Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database of choice and generating a Prisma Client for database access.' -hide_table_of_contents: true ---- - - - -Include Prisma ORM in an existing project with the following documentation, which explains some core concepts as it guides you through integrating Prisma ORM into your workflow. - - - -## In this section - - diff --git a/content/100-getting-started/02-setup-prisma/index.mdx b/content/100-getting-started/02-setup-prisma/index.mdx deleted file mode 100644 index 3532293fe7..0000000000 --- a/content/100-getting-started/02-setup-prisma/index.mdx +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: 'Set up Prisma ORM' -metaTitle: 'Set up Prisma ORM' -metaDescription: 'Get started with Prisma ORM and your favorite database. Learn about data modeling, migrations and querying.' -hide_table_of_contents: true -staticLink: true ---- - -Start from scratch or add Prisma ORM to an existing project. The following tutorials introduce you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). - -## In this section - - diff --git a/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx b/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx index 49fad38bf8..9d3e6275ff 100644 --- a/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx +++ b/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx @@ -113,16 +113,87 @@ Next, initialize TypeScript with a `tsconfig.json` file in the project: npx tsc --init ``` -### 2.2. Set up Prisma ORM +### 2.2. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +### 2.3. Set up Prisma ORM Install the required dependencies to use Prisma Postgres: ```terminal npm install prisma --save-dev -npm install @prisma/extension-accelerate +npm install @prisma/client @prisma/adapter-pg dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma migrate` and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +### 2.4. Create prisma.config.ts + +Create a `prisma.config.ts` file in the root directory for Prisma configuration: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) ``` -### 2.3. Create a TypeScript script +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +### 2.5. Create a script to query the database Create an `index.ts` file in the root directory, this will be used to query your application with Prisma ORM: @@ -132,9 +203,18 @@ touch index.ts ## 3. Migrate the database schema -Update your `prisma/schema.prisma` file to include a simple `User` model: +Update your `prisma/schema.prisma` file to include the `User` and `Post` models: ```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +} + model User { id Int @id @default(autoincrement()) email String @unique @@ -158,15 +238,39 @@ After adding the models, migrate your database using [Prisma Migrate](/orm/prism npx prisma migrate dev --name init ``` +This command creates the database tables based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + ## 4. Send queries with Prisma ORM +### 4.1. Instantiate Prisma Client + +Create a `lib/prisma.ts` file to instantiate Prisma Client with the driver adapter: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPg } from '@prisma/adapter-pg' +import { PrismaClient } from '../generated/prisma/client' + +const connectionString = `${process.env.DATABASE_URL}` + +const adapter = new PrismaPg({ connectionString }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +### 4.2. Write your first query + Paste the following boilerplate into `index.ts`: ```ts file=index.ts -import { PrismaClient } from './generated/prisma' -import { withAccelerate } from '@prisma/extension-accelerate' - -const prisma = new PrismaClient().$extends(withAccelerate()) +import { prisma } from './lib/prisma' async function main() { // ... you will write your Prisma ORM queries here @@ -185,15 +289,12 @@ main() This code contains a `main` function that's invoked at the end of the script. It also instantiates `PrismaClient` which you'll use to send queries to your database. -### 4.1. Create a new `User` record +### 4.3. Create a new `User` record Let's start with a small query to create a new `User` record in the database and log the resulting object to the console. Add the following code to your `index.ts` file: ```ts file=index.ts -import { PrismaClient } from './generated/prisma' -import { withAccelerate } from '@prisma/extension-accelerate' - -const prisma = new PrismaClient().$extends(withAccelerate()) +import { prisma } from './lib/prisma' async function main() { // add-start @@ -241,17 +342,14 @@ npx tsx index.ts Great job, you just created your first database record with Prisma Postgres! 🎉 -### 4.2. Retrieve all `User` records +### 4.4. Retrieve all `User` records Prisma ORM offers various queries to read data from your database. In this section, you'll use the `findMany` query that returns _all_ the records in the database for a given model. Delete the previous Prisma ORM query and add the new `findMany` query instead: ```ts file=index.ts -import { PrismaClient } from './generated/prisma' -import { withAccelerate } from '@prisma/extension-accelerate' - -const prisma = new PrismaClient().$extends(withAccelerate()) +import { prisma } from './lib/prisma' async function main() { // add-start @@ -295,17 +393,14 @@ npx tsx index.ts Notice how the single `User` object is now enclosed with square brackets in the console. That's because the `findMany` returned an array with a single object inside. -### 4.3. Explore relation queries +### 4.5. Explore relation queries One of the main features of Prisma ORM is the ease of working with [relations](/orm/prisma-schema/data-model/relations). In this section, you'll learn how to create a `User` and a `Post` record in a nested write query. Afterwards, you'll see how you can retrieve the relation from the database using the `include` option. First, adjust your script to include the nested query: ```ts file=index.ts -import { PrismaClient } from './generated/prisma' -import { withAccelerate } from '@prisma/extension-accelerate' - -const prisma = new PrismaClient().$extends(withAccelerate()) +import { prisma } from './lib/prisma' async function main() { // add-start @@ -367,10 +462,7 @@ npx tsx index.ts In order to also retrieve the `Post` records that belong to a `User`, you can use the `include` option via the `posts` relation field: ```ts file=index.ts -import { PrismaClient } from './generated/prisma' -import { withAccelerate } from '@prisma/extension-accelerate' - -const prisma = new PrismaClient().$extends(withAccelerate()) +import { prisma } from './lib/prisma' async function main() { // add-start @@ -444,14 +536,14 @@ This time, you're seeing two `User` objects being printed. Both of them have a ` ## Next steps -You just got your feet wet with a basic Prisma Postgres setup. If you want to explore more complex queries, such as adding caching functionality, check out the official [Quickstart](/getting-started/quickstart-prismaPostgres). +You just got your feet wet with a basic Prisma Postgres setup. If you want to explore more complex queries, such as adding caching functionality, check out the official [Quickstart](/getting-started/prisma-orm/quickstart/prisma-postgres). ### View and edit data in Prisma Studio Prisma ORM comes with a built-in GUI to view and edit the data in your database. You can open it using the following command: ```terminal -npx prisma studio +npx prisma studio --config ./prisma.config.ts ``` With Prisma Postgres, you can also directly use Prisma Studio inside the [Console](https://console.prisma.io) by selecting the **Studio** tab in your project. diff --git a/content/100-getting-started/03-prisma-postgres/100-quickstart/100-kysely.mdx b/content/100-getting-started/03-prisma-postgres/100-quickstart/100-kysely.mdx new file mode 100644 index 0000000000..1b2b1ff247 --- /dev/null +++ b/content/100-getting-started/03-prisma-postgres/100-quickstart/100-kysely.mdx @@ -0,0 +1,151 @@ +--- +title: 'Use Prisma Postgres with Kysely' +sidebar_label: 'Kysely' +metaTitle: 'Quickstart: Kysely with Prisma Postgres (10 min)' +metaDescription: 'Get started with Kysely and Prisma Postgres by creating a type-safe SQL query builder for your database.' +sidebar_custom_props: { badge: '10 min' } +--- + +[Kysely](https://kysely.dev) is a type-safe TypeScript SQL query builder that provides excellent TypeScript support and a fluent API for building SQL queries. In this guide, you'll learn how to connect Kysely to [Prisma Postgres](/postgres) and start querying your database with full type safety. + +## Prerequisites + +- **Node.js** - Version 14 or higher +- **TypeScript** - Version 4.6 or higher (5.4+ recommended for better type inference) +- A [Prisma Data Platform](https://console.prisma.io) account +- (Optional) **Kysely setup** - If you already have Kysely configured in your project, skip to [step 2](#2-get-your-direct-connection-string) + +For detailed Kysely installation and configuration, see the [Kysely Getting started guide](https://kysely.dev/docs/getting-started). + +## 1. Create a Prisma Postgres database + +Follow these steps to create your Prisma Postgres database: + +1. Log in to [Prisma Data Platform](https://console.prisma.io) and open the Console. +2. In a workspace of your choice, click the **New project** button. +3. Type a name for your project in the **Name** field, e.g. `kysely-quickstart`. +4. In the **Prisma Postgres** section, click the **Get started** button. +5. In the **Region** dropdown, select the region that's closest to your current location, e.g. US East (N. Virginia). +6. Click the **Create project** button. + +At this point, you'll be redirected to the Database page where you will need to wait for a few seconds while the status of your database changes from **PROVISIONING** to **CONNECTED**. + +Once the green **CONNECTED** label appears, your database is ready to use! + +## 2. Get your direct connection string + +To connect to Prisma Postgres via direct TCP, you need to: + +1. Open your project in the Prisma Console. +2. Navigate to your active Prisma Postgres instance. +3. Click the **API Keys** tab in the project's sidenav. +4. Click the **Create API key** button. +5. In the popup, provide a **Name** for the API key and click **Create**. +6. Copy the connection string starting with `postgres://`, this is your direct connection string. + +## 3. Create a new project + +Create a new directory for your project and initialize it: + +```terminal +mkdir kysely-quickstart +cd kysely-quickstart +npm init -y +``` + +## 4. Configure Kysely with Prisma Postgres + +Create a database connection file that uses your Prisma Postgres connection string: + + +```typescript file=database.ts +import { Pool } from 'pg' +import { Kysely, PostgresDialect } from 'kysely' + +const dialect = new PostgresDialect({ + pool: new Pool({ + connectionString: process.env.DATABASE_URL, + max: 10, + }) +}) + +// Define your database interface +interface Database { + users: { + id: number + email: string + name: string | null + } + posts: { + id: number + title: string + content: string | null + published: boolean + author_id: number + } +} + +export const db = new Kysely({ + dialect, +}) +``` + +Create a `.env` file and add your Prisma Postgres connection string: + +```env file=.env +DATABASE_URL="postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require" +``` + +## 5. Use Kysely with Prisma Postgres + +Now you can use Kysely to query your Prisma Postgres database: + +```typescript file=script.ts +import { db } from './database' + +async function main() { + // Insert a user + const user = await db + .insertInto('users') + .values({ + email: 'alice@prisma.io', + name: 'Alice', + }) + .returningAll() + .executeTakeFirstOrThrow() + + console.log('Created user:', user) + + // Query all users + const users = await db + .selectFrom('users') + .selectAll() + .execute() + + console.log('All users:', users) +} + +main() + .then(async () => { + await db.destroy() + }) + .catch(async (error) => { + console.error('Error:', error) + await db.destroy() + process.exit(1) + }) +``` + +## Next steps + +Now that you have Kysely connected to Prisma Postgres, you can: + +- **Learn more about Kysely** - Check out the [Kysely documentation](https://kysely.dev/docs/intro) for advanced query patterns +- **Explore migrations** - Learn about [Kysely migrations](https://kysely.dev/docs/migrations) for managing schema changes +- **Add more complex queries** - Explore [joins](https://kysely.dev/docs/category/join), [subqueries](https://kysely.dev/docs/examples/join/subquery-join), and [transactions](https://kysely.dev/docs/category/transactions) + +## More info + +- [Kysely documentation](https://kysely.dev) +- [Prisma Postgres documentation](/postgres) +- [PostgreSQL driver documentation](https://node-postgres.com) diff --git a/content/100-getting-started/03-prisma-postgres/100-quickstart/200-drizzle-orm.mdx b/content/100-getting-started/03-prisma-postgres/100-quickstart/200-drizzle-orm.mdx new file mode 100644 index 0000000000..c729d66565 --- /dev/null +++ b/content/100-getting-started/03-prisma-postgres/100-quickstart/200-drizzle-orm.mdx @@ -0,0 +1,193 @@ +--- +title: 'Use Prisma Postgres with Drizzle ORM' +sidebar_label: 'Drizzle ORM' +metaTitle: 'Quickstart: Drizzle ORM with Prisma Postgres (10 min)' +metaDescription: 'Get started with Drizzle ORM and Prisma Postgres by creating a lightweight, performant TypeScript ORM for your database.' +sidebar_custom_props: { badge: '10 min' } +--- + +[Drizzle ORM](https://orm.drizzle.team) is a lightweight and performant TypeScript ORM with developer experience in mind. It provides a SQL-like syntax with full TypeScript support and excellent performance. In this guide, you'll learn how to connect Drizzle ORM to [Prisma Postgres](/postgres) and start building type-safe database queries. + +## Prerequisites + +- **Node.js** - Version 16 or higher +- **TypeScript** - Version 5.0 or higher +- A [Prisma Data Platform](https://console.prisma.io) account +- (Optional) **Drizzle ORM setup** - If you already have Drizzle configured in your project, skip to [step 2](#2-get-your-direct-connection-string) + +For detailed Drizzle ORM installation and configuration, see the [Drizzle ORM Getting started guide](https://orm.drizzle.team/docs/get-started-postgresql). + +## 1. Create a Prisma Postgres database + +Follow these steps to create your Prisma Postgres database: + +1. Log in to [Prisma Data Platform](https://console.prisma.io) and open the Console. +2. In a workspace of your choice, click the **New project** button. +3. Type a name for your project in the **Name** field, e.g. `drizzle-quickstart`. +4. In the **Prisma Postgres** section, click the **Get started** button. +5. In the **Region** dropdown, select the region that's closest to your current location, e.g. US East (N. Virginia). +6. Click the **Create project** button. + +At this point, you'll be redirected to the Database page where you will need to wait for a few seconds while the status of your database changes from **PROVISIONING** to **CONNECTED**. + +Once the green **CONNECTED** label appears, your database is ready to use! + +## 2. Get your direct connection string + +To connect to Prisma Postgres via direct TCP, you need to: + +1. Open your project in the Prisma Console. +2. Navigate to your active Prisma Postgres instance. +3. Click the **API Keys** tab in the project's sidenav. +4. Click the **Create API key** button. +5. In the popup, provide a **Name** for the API key and click **Create**. +6. Copy the connection string starting with `postgres://`, this is your direct connection string. + +## 3. Create a new project + +Create a new directory for your project and initialize it: + +```terminal +mkdir drizzle-quickstart +cd drizzle-quickstart +npm init -y +``` + +## 4. Configure Drizzle ORM with Prisma Postgres + +Define your database schema using Drizzle's schema definition: + + +```typescript file=schema.ts +import { pgTable, serial, text, varchar, boolean, timestamp, integer } from 'drizzle-orm/pg-core' +import { relations } from 'drizzle-orm' + +export const users = pgTable('users', { + id: serial('id').primaryKey(), + email: varchar('email', { length: 255 }).notNull().unique(), + name: text('name'), + createdAt: timestamp('created_at').defaultNow().notNull(), +}) + +export const posts = pgTable('posts', { + id: serial('id').primaryKey(), + title: varchar('title', { length: 255 }).notNull(), + content: text('content'), + published: boolean('published').default(false).notNull(), + authorId: integer('author_id') + .notNull() + .references(() => users.id, { onDelete: 'cascade' }), + createdAt: timestamp('created_at').defaultNow().notNull(), +}) + +// Define relations +export const usersRelations = relations(users, ({ many }) => ({ + posts: many(posts), +})) + +export const postsRelations = relations(posts, ({ one }) => ({ + author: one(users, { + fields: [posts.authorId], + references: [users.id], + }), +})) +``` + +Configure Drizzle Kit with your Prisma Postgres connection string: + +```typescript file=drizzle.config.ts +import { defineConfig } from 'drizzle-kit' + +export default defineConfig({ + schema: './schema.ts', + out: './drizzle', + dialect: 'postgresql', + dbCredentials: { + url: process.env.DATABASE_URL!, + }, +}) +``` + +Create a `.env` file and add your Prisma Postgres connection string: + +```env file=.env +DATABASE_URL="postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require" +``` + +Create a database connection file: + +```typescript file=db.ts +import { drizzle } from 'drizzle-orm/node-postgres' +import { Pool } from 'pg' +import * as schema from './schema' + +const pool = new Pool({ + connectionString: process.env.DATABASE_URL, +}) + +export const db = drizzle({ client: pool, schema }) +``` + +## 5. Use Drizzle ORM with Prisma Postgres + +Generate and push your schema to the database: + +```terminal +npx drizzle-kit push +``` + +Now you can use Drizzle ORM to query your Prisma Postgres database: + +```typescript file=script.ts +import { db } from './db' +import { users, posts } from './schema' +import { eq } from 'drizzle-orm' + +async function main() { + // Insert a user + const [user] = await db + .insert(users) + .values({ + name: 'Alice', + email: 'alice@prisma.io', + }) + .returning() + + console.log('Created user:', user) + + // Query users with their posts + const usersWithPosts = await db.query.users.findMany({ + with: { + posts: true, + }, + }) + + console.log('Users with posts:', JSON.stringify(usersWithPosts, null, 2)) +} + +main() + .then(() => { + console.log('Done!') + process.exit(0) + }) + .catch((error) => { + console.error('Error:', error) + process.exit(1) + }) +``` + +## Next steps + +Now that you have Drizzle ORM connected to Prisma Postgres, you can: + +- **Learn more about Drizzle** - Check out the [Drizzle ORM documentation](https://orm.drizzle.team/docs/overview) for advanced features +- **Explore queries** - Learn about [select queries](https://orm.drizzle.team/docs/select), [joins](https://orm.drizzle.team/docs/joins), and [transactions](https://orm.drizzle.team/docs/transactions) +- **Manage migrations** - Explore [Drizzle Kit migrations](https://orm.drizzle.team/docs/migrations) for schema management +- **Use relational queries** - Take advantage of [Drizzle's relational query API](https://orm.drizzle.team/docs/rqb) for cleaner code + +## More info + +- [Drizzle ORM documentation](https://orm.drizzle.team) +- [Drizzle ORM GitHub repository](https://github.com/drizzle-team/drizzle-orm) +- [Prisma Postgres documentation](/postgres) +- [Drizzle Kit documentation](https://orm.drizzle.team/kit-docs/overview) diff --git a/content/100-getting-started/03-prisma-postgres/100-quickstart/300-typeorm.mdx b/content/100-getting-started/03-prisma-postgres/100-quickstart/300-typeorm.mdx new file mode 100644 index 0000000000..ff923f02cc --- /dev/null +++ b/content/100-getting-started/03-prisma-postgres/100-quickstart/300-typeorm.mdx @@ -0,0 +1,185 @@ +--- +title: 'Use Prisma Postgres with TypeORM' +sidebar_label: 'TypeORM' +metaTitle: 'Quickstart: TypeORM with Prisma Postgres (10 min)' +metaDescription: 'Get started with TypeORM and Prisma Postgres by connecting your TypeScript ORM to a managed PostgreSQL database.' +sidebar_custom_props: { badge: '10 min' } +--- + +[TypeORM](https://typeorm.io) is a feature-rich ORM that supports both Active Record and Data Mapper patterns, providing flexibility in how you structure your database code. In this guide, you'll learn how to connect TypeORM to [Prisma Postgres](/postgres) and start building type-safe database applications. + +## Prerequisites + +- **Node.js** - Version 16 or higher +- **TypeScript** - Version 4.5 or higher +- A [Prisma Data Platform](https://console.prisma.io) account +- (Optional) **TypeORM setup** - If you already have TypeORM configured in your project, skip to [step 2](#2-get-your-direct-connection-string) + +For detailed TypeORM installation and configuration, see the [TypeORM Getting started guide](https://typeorm.io/docs/getting-started/). + +## 1. Create a Prisma Postgres database + +Follow these steps to create your Prisma Postgres database: + +1. Log in to [Prisma Data Platform](https://console.prisma.io) and open the Console. +2. In a workspace of your choice, click the **New project** button. +3. Type a name for your project in the **Name** field, e.g. `typeorm-quickstart`. +4. In the **Prisma Postgres** section, click the **Get started** button. +5. In the **Region** dropdown, select the region that's closest to your current location, e.g. US East (N. Virginia). +6. Click the **Create project** button. + +At this point, you'll be redirected to the Database page where you will need to wait for a few seconds while the status of your database changes from **PROVISIONING** to **CONNECTED**. + +Once the green **CONNECTED** label appears, your database is ready to use! + +## 2. Get your direct connection string + +To connect to Prisma Postgres via direct TCP, you need to: + +1. Open your project in the Prisma Console. +2. Navigate to your active Prisma Postgres instance. +3. Click the **API Keys** tab in the project's sidenav. +4. Click the **Create API key** button. +5. In the popup, provide a **Name** for the API key and click **Create**. +6. Copy the connection string starting with `postgres://`, this is your direct connection string. + +## 3. Configure TypeORM with Prisma Postgres + +Update your TypeORM DataSource configuration to use your Prisma Postgres connection string. In your `data-source.ts` (or equivalent configuration file): + +```typescript file=data-source.ts +import "reflect-metadata" +import { DataSource } from "typeorm" +import { User } from "./entity/User" +import { Post } from "./entity/Post" + +export const AppDataSource = new DataSource({ + type: "postgres", + url: process.env.DATABASE_URL, // Your Prisma Postgres connection string + synchronize: true, // Set to false in production + logging: false, + entities: [User, Post], + migrations: [], + subscribers: [], +}) +``` + +Create a `.env` file and add your Prisma Postgres connection string: + +```env file=.env +DATABASE_URL="postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require" +``` + +:::tip + +For production applications, set `synchronize: false` and use [TypeORM migrations](https://typeorm.io/docs/migrations/setup) to manage schema changes safely. + +::: + +## 4. Define your entities + +Create your TypeORM entities as usual. Here's an example with User and Post entities: + +```typescript file=entity/User.ts +import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm" +import { Post } from "./Post" + +@Entity() +export class User { + @PrimaryGeneratedColumn() + id: number + + @Column({ unique: true }) + email: string + + @Column({ nullable: true }) + name: string + + @OneToMany(() => Post, (post) => post.author) + posts: Post[] +} +``` + +```typescript file=entity/Post.ts +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm" +import { User } from "./User" + +@Entity() +export class Post { + @PrimaryGeneratedColumn() + id: number + + @Column() + title: string + + @Column({ type: "text", nullable: true }) + content: string + + @Column({ default: false }) + published: boolean + + @ManyToOne(() => User, (user) => user.posts) + author: User +} +``` + +For more information on defining entities, see the [TypeORM Entities documentation](https://typeorm.io/docs/entity/entities). + +## 5. Initialize and use TypeORM + +Initialize your DataSource and start querying: + +```typescript file=index.ts +import "reflect-metadata" +import { AppDataSource } from "./data-source" +import { User } from "./entity/User" +import { Post } from "./entity/Post" + +AppDataSource.initialize() + .then(async () => { + console.log("Connected to Prisma Postgres!") + + // Create a user with a post + const user = new User() + user.email = "alice@prisma.io" + user.name = "Alice" + await AppDataSource.manager.save(user) + + const post = new Post() + post.title = "Hello World" + post.content = "This is my first post!" + post.published = true + post.author = user + await AppDataSource.manager.save(post) + + console.log("Created user and post!") + + // Query users with their posts + const users = await AppDataSource.getRepository(User).find({ + relations: { + posts: true, + }, + }) + + console.log("Users with posts:", JSON.stringify(users, null, 2)) + }) + .catch((error) => console.log("Error:", error)) +``` + +Run your application: + +```terminal +npx tsx index.ts +``` + +## Next steps + +Now that you have TypeORM connected to Prisma Postgres, you can: + +- **Learn more about TypeORM** - Check out the [TypeORM documentation](https://typeorm.io/docs/) for comprehensive guides + +## More info + +- [TypeORM documentation](https://typeorm.io) +- [Prisma Postgres documentation](/postgres) +- [TypeORM PostgreSQL driver documentation](https://typeorm.io/docs/drivers/postgres/) diff --git a/content/100-getting-started/03-prisma-postgres/100-quickstart/50-prisma-orm.mdx b/content/100-getting-started/03-prisma-postgres/100-quickstart/50-prisma-orm.mdx new file mode 100644 index 0000000000..d774affd78 --- /dev/null +++ b/content/100-getting-started/03-prisma-postgres/100-quickstart/50-prisma-orm.mdx @@ -0,0 +1,301 @@ +--- +title: 'Use Prisma Postgres with Prisma ORM' +sidebar_label: 'Prisma ORM' +metaTitle: 'Quickstart: Prisma ORM with Prisma Postgres (5 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to Prisma Postgres and generating a Prisma Client for database access.' +sidebar_custom_props: { badge: '5 min' } +--- + +import Prerequisites from '../../_components/_prerequisites.mdx' +import CreateProject from '../../_components/_create-project.mdx' +import ExploreData from '../../_components/_explore-data.mdx' +import NextSteps from '../../_components/_next-steps.mdx' + +[Prisma Postgres](/postgres) is a fully managed PostgreSQL database that scales to zero and integrates smoothly with both Prisma ORM and Prisma Studio. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to Prisma Postgres using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. + +## Prerequisites + + + +## 1. Create a Prisma Postgres database + +Follow these steps to create your Prisma Postgres database: + +1. Log in to [Prisma Data Platform](https://console.prisma.io) and open the Console. +2. In a workspace of your choice, click the **New project** button. +3. Type a name for your project in the **Name** field, e.g. `hello-ppg`. +4. In the **Prisma Postgres** section, click the **Get started** button. +5. In the **Region** dropdown, select the region that's closest to your current location, e.g. US East (N. Virginia). +6. Click the **Create project** button. + +At this point, you'll be redirected to the Database page where you will need to wait for a few seconds while the status of your database changes from **PROVISIONING** to **CONNECTED**. + +Once the green **CONNECTED** label appears, your database is ready to use! + +## 2. Get your direct connection string + +To connect to Prisma Postgres via direct TCP, you need to: + +1. Open your project in the Prisma Console. +2. Navigate to your active Prisma Postgres instance. +3. Click the **API Keys** tab in the project's sidenav. +4. Click the **Create API key** button. +5. In the popup, provide a **Name** for the API key and click **Create**. +6. Copy the connection string starting with `postgres://`, this is your direct connection string. + +## 3. Create a new project + + + +## 4. Install required dependencies + +Install the packages needed for this quickstart: + +```terminal +npm install prisma @types/node --save-dev +npm install @prisma/client @prisma/adapter-pg dotenv +``` + +Here's what each package does: + +- **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` +- **`@prisma/client`** - The Prisma Client library for querying your database +- **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`dotenv`** - Loads environment variables from your `.env` file + +## 5. Configure ESM support + +Update `tsconfig.json` for ESM compatibility: + +```json file=tsconfig.json +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "node", + "target": "ES2023", + "strict": true, + "esModuleInterop": true, + "ignoreDeprecations": "6.0" + } +} +``` + +Update `package.json` to enable ESM: + +```json file=package.json +{ + // add-start + "type": "module", + // add-end +} +``` + +## 6. Initialize Prisma ORM + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +```terminal +npx prisma init --output ../generated/prisma +``` + +This command does a few things: + +- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a `.env` file in the root directory for environment variables +- Generates the Prisma Client in the `generated/prisma/` directory +- Creates a `prisma.config.ts` file for Prisma configuration + +Add your Prisma Postgres direct connection string to the `.env` file: + +```env file=.env +DATABASE_URL="postgres://your-connection-string" +``` + +The generated `prisma.config.ts` file looks like this: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: + +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +The generated schema uses [the ESM-first `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with a custom output path: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +} +``` + +## 7. Define your data model + +Open `prisma/schema.prisma` and add the following models: + +```prisma file=prisma/schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +} + +//add-start +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 +} +//add-end +``` + +## 8. Create and apply your first migration + +Create your first migration to set up the database tables: + +```terminal +npx prisma migrate dev --name init +``` + +This command creates the database tables based on your schema. + +Now run the following command to generate the Prisma Client: + +```terminal +npx prisma generate +``` + +## 9. Instantiate Prisma Client + +Now that you have all the dependencies installed, you can instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: + +```typescript file=lib/prisma.ts +import "dotenv/config"; +import { PrismaPg } from '@prisma/adapter-pg' +import { PrismaClient } from '../generated/prisma/client' + +const connectionString = `${process.env.DATABASE_URL}` + +const adapter = new PrismaPg({ connectionString }) +const prisma = new PrismaClient({ adapter }) + +export { prisma } +``` + +## 10. Write your first query + +Create a `script.ts` file to test your setup: + +```typescript file=script.ts +import { prisma } from './lib/prisma' + +async function main() { + // Create a new user with a post + const user = await prisma.user.create({ + data: { + name: 'Alice', + email: 'alice@prisma.io', + posts: { + create: { + title: 'Hello World', + content: 'This is my first post!', + published: true, + }, + }, + }, + include: { + posts: true, + }, + }) + console.log('Created user:', user) + + // Fetch all users with their posts + const allUsers = await prisma.user.findMany({ + include: { + posts: true, + }, + }) + console.log('All users:', JSON.stringify(allUsers, null, 2)) +} + +main() + .then(async () => { + await prisma.$disconnect() + }) + .catch(async (e) => { + console.error(e) + await prisma.$disconnect() + process.exit(1) + }) +``` + +Run the script: + +```terminal +npx tsx script.ts +``` + +You should see the created user and all users printed to the console! + +## 11. Explore your data with Prisma Studio + + + +## Next steps + + + +## More info + +- [Prisma Postgres documentation](/postgres) +- [Prisma Config reference](/orm/reference/prisma-config-reference) +- [Database connection management](/orm/prisma-client/setup-and-configuration/databases-connections) diff --git a/content/100-getting-started/03-prisma-postgres/110-import-from-existing-database-postgresql.mdx b/content/100-getting-started/03-prisma-postgres/110-import-from-existing-database-postgresql.mdx index 310401625f..1464590f14 100644 --- a/content/100-getting-started/03-prisma-postgres/110-import-from-existing-database-postgresql.mdx +++ b/content/100-getting-started/03-prisma-postgres/110-import-from-existing-database-postgresql.mdx @@ -1,13 +1,11 @@ --- -title: 'Import data from an existing database' -sidebar_label: 'Import from existing database' +title: 'Import data from an existing PostgreSQL database' +sidebar_label: 'PostgreSQL' metaTitle: 'Import from existing Postgres database into Prisma Postgres' -metaDescription: 'Learn how to import data from an existing database into Prisma Postgres.' +metaDescription: 'Learn how to import data from an existing PostgreSQL database into Prisma Postgres.' tocDepth: 3 toc: true search: true -dbSwitcher: [ "mysql", "postgresql"] -slugSwitch: /getting-started/prisma-postgres/import-from-existing-database- --- This guide provides step-by-step instructions for importing data from an existing PostgreSQL database into Prisma Postgres. @@ -18,7 +16,7 @@ You can accomplish this migration in three steps: 1. Export your existing data via `pg_dump`. 1. Import the previously exported data into Prisma Postgres via `pg_restore`. -In the third step, you will be using a [direct connection](/postgres/database/direct-connections) to securely connect to your Prisma Postgres database during to run `pg_restore`. +In the third step, you will be using a [direct connection](/postgres/database/direct-connections) to securely connect to your Prisma Postgres database to run `pg_restore`. ## Prerequisites @@ -27,6 +25,12 @@ In the third step, you will be using a [direct connection](/postgres/database/di - Node.js 18+ installed - PostgreSQL CLI Tools (`pg_dump`, `pg_restore`) for creating and restoring backups +:::info[Make sure your PostgreSQL tools match the Prisma Postgres version] + +Prisma Postgres runs PostgreSQL 17. Your `pg_dump` and `pg_restore` tools need to be version 17 to ensure compatibility. You can check your version by running `pg_dump --version` or `pg_restore --version`. + +::: + ## 1. Create a new Prisma Postgres database Follow these steps to create a new Prisma Postgres database: @@ -38,7 +42,15 @@ Follow these steps to create a new Prisma Postgres database: 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. -With your Prisma Postgres instance being created, you can move to the next step. +Once your database is provisioned, obtain your direct connection string: + +1. Navigate to your active Prisma Postgres instance. +1. Click the **API Keys** tab in the project's sidenav. +1. Click the **Create API key** button. +1. In the popup, provide a **Name** for the API key and click **Create**. +1. Copy the connection string starting with `postgres://`, this is your direct connection string. + +Save the connection string, you'll need it in step 3. ## 2. Export data from your existing database @@ -100,57 +112,43 @@ Running this command will create a backup file named `db_dump.bak` which you wil ## 3. Import data into Prisma Postgres -In this section, you'll use a [TCP Tunnel](/postgres/database/direct-connections#tcp-tunnel) in order to connect to your Prisma Postgres instance and import data via `pg_restore`. +In this section, you'll use your [direct connection string](/postgres/database/direct-connections) to connect to your Prisma Postgres instance and import data via `pg_restore`. -### 3.1. Connecting to the Prisma Postgres Database with `@prisma/ppg-tunnel` +Your direct connection string from step 1 should look like this: -Open a new terminal and set the environment variable for your Prisma Postgres database connection URL. - -```bash -export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..." -``` - -Run the tunnel: -```bash -npx @prisma/ppg-tunnel --host 127.0.0.1 --port 5432 +```no-copy +postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require ``` -You should see output similar to: +Use the backup file from **Step 2** to restore data into your Prisma Postgres database with `pg_restore` by running this command (replace `__USER__`, `__PASSWORD__` with the values from your direct connection string): -```cmd -Prisma Postgres auth proxy listening on 127.0.0.1:52604 🚀 - -Your connection is authenticated using your Prisma Postgres API key. -... - -============================== -hostname: 127.0.0.1 -port: 52604 -username: -password: -============================== +```bash +pg_restore \ + -h db.prisma.io \ + -p 5432 \ + -U __USER__ \ + -d postgres \ + -v \ + ./db_dump.bak \ +&& echo "-complete-" ``` +When prompted, enter the `__PASSWORD__` from your direct connection string. -:::note -Keep this tunnel process running to maintain the connection! -::: - -### 3.2. Restoring the Backup with `pg_restore` +:::tip -Use the backup file from **Step 2** to restore data into Prisma Postgres database with `pg_restore` by running this command: +You can also use the full connection string format: ```bash -PGSSLMODE=disable \ pg_restore \ - -h 127.0.0.1 \ - -p 5432 \ + -d "postgres://USER:PASSWORD@db.prisma.io:5432/postgres?sslmode=require" \ -v \ - -d postgres \ ./db_dump.bak \ && echo "-complete-" ``` +::: + Once the command completes execution, you will have successfully imported the data from your existing PostgreSQL database into Prisma Postgres 🎉 To validate that the import worked, you can use [Prisma Studio](/postgres/integrations/viewing-data#viewing-and-editing-data-in-prisma-studio). Either open it in the [Platform Console](https://console.prisma.io) by clicking the **Studio** tab in the left-hand sidenav in your project or run this command to launch Prisma Studio locally: @@ -163,63 +161,35 @@ npx prisma studio ### Scenario A: You are already using Prisma ORM -If you already using Prisma ORM, the only things you need to do are: - -- add the Prisma Accelerate extension to your project -- update the database connection URL and re-generate Prisma Client - -#### 4.A.1. Add the Prisma Accelerate extension - -Th Prisma Accelerate extension is [required](/postgres/introduction/overview#using-the-client-extension-for-prisma-accelerate-required) when using Prisma Postgres. If you are not currently using Prisma Accelerate with Prisma ORM, go through the following steps to make Prisma ORM work with Prisma Postgres. - -First, install the `@prisma/extension-accelerate` package in your project: - -```terminal -npm install @prisma/extension-accelerate -``` - -Then, add the extension to your Prisma Client instance: +If you're already using Prisma ORM, you need to update your database connection URL to point to your new Prisma Postgres instance. -```ts -import { withAccelerate } from '@prisma/extension-accelerate' +Update the `DATABASE_URL` in your `.env` file to match your Prisma Postgres direct connection string from step 1: -const prisma = new PrismaClient().$extends(withAccelerate()) +```bash file=.env +DATABASE_URL="postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require" ``` -#### 4.A.2. Update the database connection URL +Then, re-generate Prisma Client so that the updated environment variable takes effect: -The database connection URL is configured via the `url` of the `datasource` block in your `schema.prisma` file. Most commonly, it is set via an environment variable called `DATABASE_URL`: - -```prisma file=schema.prisma -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} +```terminal +npx prisma generate ``` -The next steps assumes that you're a `.env` file to set the `DATABASE_URL` environment variable (if that's not the case, you can set the environment variable in your preferred way). - -Open `.env` and update the value for the `DATABASE_URL` environment variable to match your Prisma Postgres connection URL, looking similar to this: - -```bash -DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=__API_KEY__" -``` +Once this is done, you can run your application and it should work as before. -As a last step, you need to re-generate Prisma Client for so that the updated environment variables takes effect and your queries go to Prisma Postgres going forward: +:::tip -``` -npx prisma generate --no-engine -``` +For a complete guide on setting up Prisma ORM with Prisma Postgres from scratch, including driver adapter configuration and best practices, see the [Prisma ORM with Prisma Postgres quickstart](/getting-started/prisma-orm/quickstart/prisma-postgres). -Once this is done, you can run your application and it should work as before. +::: ### Scenario B: You are not yet using Prisma ORM If you are not yet using Prisma ORM, you'll need to go through the following steps to use Prisma Postgres from your application: -1. Install the Prisma CLI in your project +1. Install the Prisma CLI and other required dependencies in your project 1. Introspect the database to generate a Prisma schema 1. Generate Prisma Client 1. Update the queries in your application to use Prisma ORM -You can find the detailed step-by-step instructions for this process in this guide: [Add Prisma ORM to an existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql). \ No newline at end of file +You can find the detailed step-by-step instructions for this process in this guide: [Add Prisma ORM to an existing project](/getting-started/prisma-orm/add-to-existing-project/prisma-postgres). \ No newline at end of file diff --git a/content/100-getting-started/03-prisma-postgres/115-import-from-existing-database-mysql.mdx b/content/100-getting-started/03-prisma-postgres/115-import-from-existing-database-mysql.mdx index 795c4c8634..0d009ba206 100644 --- a/content/100-getting-started/03-prisma-postgres/115-import-from-existing-database-mysql.mdx +++ b/content/100-getting-started/03-prisma-postgres/115-import-from-existing-database-mysql.mdx @@ -1,13 +1,11 @@ --- title: 'Import data from an existing MySQL database' -sidebar_label: 'Import from existing database' +sidebar_label: 'MySQL' metaTitle: 'Import from existing MySQL database into Prisma Postgres' metaDescription: 'Learn how to import data from an existing MySQL database into Prisma Postgres.' tocDepth: 3 toc: true search: true -dbSwitcher: ["mysql", "postgresql"] -slugSwitch: /getting-started/prisma-postgres/import-from-existing-database- --- This guide provides step-by-step instructions for importing data from an existing MySQL database into Prisma Postgres. @@ -26,6 +24,12 @@ You can accomplish this migration in four steps: - Node.js 18+ installed. - [pgloader](https://pgloader.io/) installed. +:::info[Make sure your PostgreSQL tools match the Prisma Postgres version] + +Prisma Postgres runs PostgreSQL 17. Your `pgloader` and any other PostgreSQL tools you use need to be compatible with PostgreSQL 17. + +::: + We recommend attempting this migration in a separate git development branch. ## 1. Create a new Prisma Postgres database @@ -49,16 +53,18 @@ Once your database was provisioned, find your direct Prisma Postgres connection Save the connection string, you'll need it in the next step. -## 2. Connect directly to a Prisma Postgres instance +## 2. Prepare your direct connection string -In this step, you'll use a [direct connection](/postgres/database/direct-connections) to connect to your Prisma Postgres instance. +In this step, you'll use the [direct connection string](/postgres/database/direct-connections) you obtained in step 1 to connect to your Prisma Postgres instance. -You'll need the Prisma Postgres connection URL from [step 1](/getting-started/prisma-postgres/import-from-existing-database-mysql#1-create-a-new-prisma-postgres-database): +Your direct connection string should look like this: ```no-copy -prisma+postgres://accelerate.prisma-data.net/?api_key=ey... +postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require ``` +You'll use this connection string in the next step when configuring pgloader. + ## 3. Migrate your MySQL data to Prisma Postgres using pgloader @@ -148,10 +154,10 @@ After migrating your data, you need to set up your Prisma project to work with P Initialize Prisma in your project by running `npx prisma init` in your project directory. This creates a `prisma` folder with a `schema.prisma` file and `.env` file (if not already present). -In the generated `.env` file, update `DATABASE_URL` to match your Prisma Postgres connection string that you received in [step 1](/getting-started/prisma-postgres/import-from-existing-database-mysql#1-create-a-new-prisma-postgres-database): +In the generated `.env` file, update `DATABASE_URL` to match your Prisma Postgres direct connection string that you received in [step 1](/getting-started/prisma-postgres/import-from-existing-database-mysql#1-create-a-new-prisma-postgres-database): ```terminal file=.env no-copy -DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=__API_KEY__" +DATABASE_URL="postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require" ``` [Introspect](/orm/prisma-schema/introspection) your newly migrated database by running: @@ -167,7 +173,7 @@ Congratulations! You've successfully migrated your MySQL database to Prisma Post :::note -For a comprehensive guide on getting started with Prisma and Prisma Postgres, see [start from scratch with Prisma and Prisma Postgres](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-prismaPostgres). +For a comprehensive guide on getting started with Prisma and Prisma Postgres, see [start from scratch with Prisma and Prisma Postgres](/getting-started/prisma-orm/quickstart/prisma-postgres). ::: @@ -187,10 +193,10 @@ datasource db { } ``` -In the generated `.env` file, update `DATABASE_URL` to match your new Prisma Postgres connection string that you received in [step 1](/getting-started/prisma-postgres/import-from-existing-database-mysql#1-create-a-new-prisma-postgres-database): +In the generated `.env` file, update `DATABASE_URL` to match your Prisma Postgres direct connection string that you received in [step 1](/getting-started/prisma-postgres/import-from-existing-database-mysql#1-create-a-new-prisma-postgres-database): ```terminal file=.env no-copy -DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=__API_KEY__" +DATABASE_URL="postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require" ``` Introspect your newly migrated Prisma Postgres database and generate Prisma Client: diff --git a/content/100-getting-started/03-prisma-postgres/120-upgrade-from-early-access.mdx b/content/100-getting-started/03-prisma-postgres/120-upgrade-from-early-access.mdx deleted file mode 100644 index a7ef91194e..0000000000 --- a/content/100-getting-started/03-prisma-postgres/120-upgrade-from-early-access.mdx +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: 'Upgrade from Early Access' -metaTitle: 'Upgrade Prisma Postgres from Early Access' -metaDescription: 'Upgrade your Prisma Postgres database from Early Access database to General Availability database.' -staticLink: true -tocDepth: 3 -toc: true ---- - -This guide shows you how to migrate your Prisma Postgres Early Access (EA) database to the now official Prisma Postgres General Availability (GA) database. Prisma Postgres Early Access was introduced to allow early adopters to test Prisma’s new managed PostgreSQL service. As we move to GA, it's crucial to safely migrate data from your EA database to the new GA database. - -Prisma will _not_ automatically migrate your data to ensure its integrity. Instead, this process must be done manually. You can accomplish this in three main steps: - -1. Back up your EA database via `pg_dump`. -2. Create a new GA database. -3. Import your backup into the GA database via `pg_restore`. - -We will be using the [`@prisma/ppg-tunnel`](https://www.npmjs.com/package/@prisma/ppg-tunnel) package to securely connect to both databases. This tool sets up a secure proxy tunnel, eliminating the need for manual credential handling. - -You can learn more about **Prisma Postgres** on [this page](/postgres). - -## Prerequisites - -Before you begin, make sure you have: - -- **Node.js** installed (version 16 or higher). -- **PostgreSQL CLI Tools** (`pg_dump`, `pg_restore`) for creating and restoring backups. -- A **Database connection string** for your Prisma Postgres database. - -To create and restore backups, ensure you have the PostgreSQL command-line tools installed. Run the following commands based on your operating system: - - - - - -```terminal -brew install postgresql@16 -which pg_dump -which pg_restore -``` - - - - - -```terminal -# Download from the official PostgreSQL website: -# https://www.postgresql.org/download/windows/ -# During installation, select "Command Line Tools". -# Then verify with: - -where pg_dump -where pg_restore -``` - - - - -```terminal -sudo apt-get update -sudo apt-get install postgresql-client-16 -which pg_dump -which pg_restore -``` - - - - - -:::tip -If you installed PostgreSQL but still see a “command not found” error for pg_dump or pg_restore, ensure your installation directory is in your system’s PATH environment variable. -::: - -:::note -Please make sure that you are installing Postgresql version 16. Other versions may cause errors during the backup and restore process. -::: - -## Option A: Interactive approach - -This approach is recommended if you prefer a guided, one-command solution. In this mode, the `@prisma/ppg-tunnel` CLI: - -1. Prompts you for your Early Access (EA) database API key (or `DATABASE_URL`). -2. Uses `pg_dump` behind the scenes to back up your EA database to a file in the current directory. -3. Prompts you for your new GA database URL or API Key. -4. Uses `pg_restore` to import the backup file into your GA database. - -Interactive mode does not accept any CLI arguments or read API keys from the environment. You must provide them interactively. - -### Steps - -1. Open a terminal and run: -```bash -npx @prisma/ppg-tunnel migrate-from-ea -``` - -2. When prompted, paste your Early Access database key or connection string. The CLI will create a `.bak` file in the current directory. - -3. When prompted again, paste your GA database key or connection string. The CLI will automatically restore the .bak file into the new GA database. - -4. Once complete, connect with your favorite Database IDE to verify your data in the GA database. - -## Option B: Manual backup-and-restore approach - -If you prefer or need finer control over the migration process (or to pass environment variables directly), follow these manual steps. -The migration involves three main parts: - -1. Back up your EA database via `pg_dump`. -2. Create a new GA database. -3. Import your backup into the GA database via `pg_restore`. - -We will still be using the `@prisma/ppg-tunnel` package to securely connect to both databases. - -## 1. Back up the EA database - -### 1.1. Connecting to the EA database directly with `@prisma/ppg-tunnel` - -In your terminal, run `npx @prisma/ppg-tunnel` to establish a secure tunnel to your Early Access database. - -If you already have a `.env` file in your current directory with `DATABASE_URL` set, the tunnel CLI will automatically pick it up—no need to manually export it. However, if you haven't set up a `.env` file, you'll need to set the `DATABASE_URL` environment variable explicitly. - -To set environment variable (with your actual EA database URL): -```bash -export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..." -``` -:::note -If you explicitly set `DATABASE_URL` in your terminal, that value will take precedence over the one in your `.env` file. -::: - -Run the tunnel: -```bash -npx @prisma/ppg-tunnel --host 127.0.0.1 --port 5432 -``` - -You should see output similar to: - -```cmd -Prisma Postgres auth proxy listening on 127.0.0.1:5432 🚀 - -Your connection is authenticated using your Prisma Postgres API key. -... - -============================== -hostname: 127.0.0.1 -port: 5432 -username: -password: -============================== -``` - -:::note -Please note that the port you will see in your output will be a randomly assigned port which may be different from the one mentioned here. -Also, Keep this terminal window open so the tunnel remains active! If you close it, the tunnel disconnects. -::: - -Copy the port number from the terminal output, you’ll need it in the next step for the `pg_dump` command. - -### 1.2. Creating the Backup with `pg_dump` - -With the tunnel running, you can now dump the EA database by running the following command: -```bash -PGSSLMODE=disable \ -pg_dump \ - -h 127.0.0.1 \ - -p 5432 \ - -Fc \ - -v \ - -d postgres \ - -f ./mydatabase.bak \ -&& echo "-complete-" -``` - -`PGSSLMODE=disable` indicates SSL is not required locally because the tunnel already encrypts the connection. - -``` -`-h` is the host (127.0.0.1) -`-p` is the port, which should match the one from the tunnel output. -`-Fc` uses the custom format for backups, recommended for pg_restore. -`-d` postgres is the default database name used in Prisma Postgres. -`-f` ./mydatabase.bak specifies the backup file name and location. -`-v` runs pg_dump in verbose mode. -``` - -This should create your backup file named `mydatabase.bak` in the current directory. We will use this backup file for importing in next steps. - -## 2. Create a new GA database - -Next, create your GA (General Availability) database: -1. Visit [console.prisma.io](https://console.prisma.io) and sign in (or create an account). -2. Create a Prisma Postgres database in the region of your choice. -3. Copy the Database URL for later use. - -Prisma Postgres GA uses PostgreSQL 17, so you’ll be restoring your EA backup into this new environment. - -## 3. Import the backup into the GA database - -### 3.1. Connecting to the GA Database with `@prisma/ppg-tunnel` - -Open a new terminal (or stop the previous tunnel) and connect to your GA database: - -Set environment variables for the new GA database: -```bash -export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..." -``` - -Run the tunnel: -```bash -npx @prisma/ppg-tunnel --host 127.0.0.1 --port 5432 -``` - -You should see output similar to: - -```cmd -Prisma Postgres auth proxy listening on 127.0.0.1:52604 🚀 - -Your connection is authenticated using your Prisma Postgres API key. -... - -============================== -hostname: 127.0.0.1 -port: 52604 -username: -password: -============================== -``` - - -:::note -Again, keep this tunnel process running to maintain the connection! -::: - -### 3.2. Restoring the Backup with `pg_restore` - -Use the backup file from **Step 1** to restore data into your GA database with `pg_restore` by running this command: - -```bash -PGSSLMODE=disable \ -pg_restore \ - -h 127.0.0.1 \ - -p 5432 \ - -v \ - -d postgres \ - ./mydatabase.bak \ -&& echo "-complete-" -``` - -Also, in this case the database name is `postgres`. You can replace it with your desired database name. It does not matter what you name your database as you will be able to use Prisma Postgres as usual. -The backup file name (mydatabase.bak in our example) should match the one you created in Step 1. - -This command restores the backup into the GA database. If successful, you should see `-complete-` in the terminal. - -## Next steps - -Connect with your favorite Database IDE or Prisma Client to confirm all tables, rows, and schemas match your old EA environment. - -Congratulations! You have successfully migrated your Prisma Postgres Early Access database to Prisma Postgres GA. If you encounter any issues, please reach out to our [support team](https://www.prisma.io/support). - - diff --git a/content/100-getting-started/_components/_create-prisma-client.mdx b/content/100-getting-started/_components/_create-prisma-client.mdx new file mode 100644 index 0000000000..9ac8c11aa5 --- /dev/null +++ b/content/100-getting-started/_components/_create-prisma-client.mdx @@ -0,0 +1,181 @@ +import CodeBlock from '@theme/CodeBlock'; + +Create a `lib/` directory and a `prisma.ts` file inside it to set up your Prisma Client instance: + +{props.database === 'prisma-postgres' && ( +<> + +{`import { PrismaClient } from '../generated/prisma' +import { withAccelerate } from '@prisma/extension-accelerate' + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const prisma = globalForPrisma.prisma ?? + new PrismaClient().$extends(withAccelerate()) + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma`} + + +)} + +{props.database === 'postgresql' && ( +<> + +{`import { PrismaClient } from '../generated/prisma' +import { PrismaPg } from '@prisma/adapter-pg' + +const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter }) + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma`} + + +)} + +{props.database === 'mysql' && ( +<> + +{`import { PrismaClient } from '../generated/prisma' +import { PrismaMariaDb } from '@prisma/adapter-mariadb' + +const adapter = new PrismaMariaDb({ + host: process.env.DB_HOST || 'localhost', + port: parseInt(process.env.DB_PORT || '3306'), + connectionLimit: 5 +}) + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter }) + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma`} + + +)} + +{props.database === 'sqlite' && ( +<> + +{`import { PrismaClient } from '../generated/prisma' +import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3' + +const adapter = new PrismaBetterSQLite3({ url: process.env.DATABASE_URL }) + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter }) + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma`} + + +)} + +{props.database === 'sqlserver' && ( +<> + +{`import { PrismaClient } from '../generated/prisma' +import { PrismaMSSQL } from '@prisma/adapter-mssql' + +const sqlConfig = { + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + server: process.env.DB_HOST, + pool: { + max: 10, + min: 0, + idleTimeoutMillis: 30000 + }, + options: { + encrypt: true, + trustServerCertificate: false + } +} + +const adapter = new PrismaMSSQL(sqlConfig) + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter }) + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma`} + + +)} + +{props.database === 'planetscale' && ( +<> + +{`import { PrismaClient } from '../generated/prisma' +import { PrismaPlanetScale } from '@prisma/adapter-planetscale' +import { fetch as undiciFetch } from 'undici' + +const adapter = new PrismaPlanetScale({ + url: process.env.DATABASE_URL, + fetch: undiciFetch +}) + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter }) + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma`} + + +)} + +{props.database === 'cockroachdb' && ( +<> + +{`import { PrismaClient } from '../generated/prisma' +import { PrismaPg } from '@prisma/adapter-pg' + +const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter }) + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma`} + + +)} + +{props.database === 'mongodb' && ( +<> + +{`import { PrismaClient } from '../generated/prisma' + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const prisma = globalForPrisma.prisma ?? new PrismaClient() + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma`} + + +)} + +:::note + +The global pattern prevents multiple instances of Prisma Client in development due to hot reloading. + +::: diff --git a/content/100-getting-started/_components/_create-project.mdx b/content/100-getting-started/_components/_create-project.mdx new file mode 100644 index 0000000000..d25affdf0d --- /dev/null +++ b/content/100-getting-started/_components/_create-project.mdx @@ -0,0 +1,14 @@ +Create a project directory and navigate into it: + +```terminal +mkdir hello-prisma +cd hello-prisma +``` + +Initialize a TypeScript project: + +```terminal +npm init -y +npm install typescript tsx @types/node --save-dev +npx tsc --init +``` diff --git a/content/100-getting-started/_components/_explore-data.mdx b/content/100-getting-started/_components/_explore-data.mdx new file mode 100644 index 0000000000..8e1ecd0362 --- /dev/null +++ b/content/100-getting-started/_components/_explore-data.mdx @@ -0,0 +1,7 @@ +Prisma Studio is a visual editor for your database. Launch it with: + +```terminal +npx prisma studio --config ./prisma.config.ts +``` + +This opens a web interface where you can view and edit your data. diff --git a/content/100-getting-started/_components/_install-prisma-client.mdx b/content/100-getting-started/_components/_install-prisma-client.mdx new file mode 100644 index 0000000000..3947901919 --- /dev/null +++ b/content/100-getting-started/_components/_install-prisma-client.mdx @@ -0,0 +1,83 @@ +import CodeBlock from '@theme/CodeBlock'; + +## {props.stepNumber ? `${props.stepNumber}. ` : ''}Install and generate Prisma Client + +To get started with Prisma Client, first install the required packages: + +{props.database === 'prisma-postgres' && ( +<> + +{`npm install @prisma/client @prisma/extension-accelerate`} + + +)} + +{props.database === 'postgresql' && ( +<> + +{`npm install @prisma/client @prisma/adapter-pg`} + + +)} + +{props.database === 'mysql' && ( +<> + +{`npm install @prisma/client @prisma/adapter-mariadb`} + + +)} + +{props.database === 'sqlite' && ( +<> + +{`npm install @prisma/client @prisma/adapter-better-sqlite3`} + + +)} + +{props.database === 'sqlserver' && ( +<> + +{`npm install @prisma/client @prisma/adapter-mssql`} + + +)} + +{props.database === 'planetscale' && ( +<> + +{`npm install @prisma/client @prisma/adapter-planetscale`} + + +)} + +{props.database === 'cockroachdb' && ( +<> + +{`npm install @prisma/client @prisma/adapter-pg`} + + +)} + +{props.database === 'mongodb' && ( +<> + +{`npm install @prisma/client`} + + +)} + +Then, run `prisma generate` which reads your Prisma schema and generates the Prisma Client: + +```terminal +npx prisma generate +``` + +:::note Good to know + +When you run `prisma generate`, you are creating code (TypeScript types, methods, queries) tailored to your Prisma schema. Whenever you make changes to your Prisma schema, you need to update the Prisma Client by running `prisma generate`. + +Whenever you update your Prisma schema, you will also need to update your database schema using either `prisma migrate dev` or `prisma db push`. These commands will also run `prisma generate` automatically. + +::: diff --git a/content/100-getting-started/_components/_next-steps.mdx b/content/100-getting-started/_components/_next-steps.mdx new file mode 100644 index 0000000000..e28f626f50 --- /dev/null +++ b/content/100-getting-started/_components/_next-steps.mdx @@ -0,0 +1,7 @@ +You've successfully set up Prisma ORM. Here's what you can explore next: + +- **Learn more about Prisma Client**: Explore the [Prisma Client API](/orm/prisma-client) for advanced querying, filtering, and relations +- **Database migrations**: Learn about [Prisma Migrate](/orm/prisma-migrate) for evolving your database schema +- **Performance optimization**: Discover [query optimization techniques](/orm/prisma-client/queries/query-optimization-performance) +- **Build a full application**: Check out our [framework guides](/guides) to integrate Prisma ORM with Next.js, Express, and more +- **Join the community**: Connect with other developers on [Discord](https://pris.ly/discord) diff --git a/content/100-getting-started/_components/_prerequisites.mdx b/content/100-getting-started/_components/_prerequisites.mdx new file mode 100644 index 0000000000..eacf532107 --- /dev/null +++ b/content/100-getting-started/_components/_prerequisites.mdx @@ -0,0 +1,11 @@ +You need: + +- [Node.js](https://nodejs.org/en/) v20.19+, v22.12+, or v24.0+ installed on your machine +- Basic knowledge of JavaScript or TypeScript + +{props.database && ( +
    +
  • A {props.database} database accessible
  • + {props.connectionDetails &&
  • {props.connectionDetails}
  • } +
+)} diff --git a/content/100-getting-started/_components/_prisma-init.mdx b/content/100-getting-started/_components/_prisma-init.mdx new file mode 100644 index 0000000000..64c5c0a227 --- /dev/null +++ b/content/100-getting-started/_components/_prisma-init.mdx @@ -0,0 +1,67 @@ +import CodeBlock from '@theme/CodeBlock'; + +## {props.stepNumber ? `${props.stepNumber}. ` : ''}Initialize Prisma + +You can now invoke the Prisma CLI by prefixing it with `npx`: + +```terminal +npx prisma +``` + +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: + +{props.database === 'prisma-postgres' ? ( +<> + +{`npx prisma init --db --output ../generated/prisma`} + + +:::info + +You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database. + +::: + +This command creates: + +- A `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- A new Prisma Postgres database (when using `--db` flag) +- A `.env` file in the root directory for environment variables +- A `generated/prisma/` directory for the generated Prisma Client + +The generated schema uses the modern `prisma-client` generator with a custom output path: + + +{`generator client { + provider = "prisma-client" + output = "../generated/prisma" +} + +datasource db { + provider = "postgresql" +}`} + + +) : ( +<> + +{`npx prisma init --datasource-provider ${props.datasource?.toLowerCase() || props.database} --output ../generated/prisma`} + + +This command does a few things: + +- Creates a new directory called `prisma` that contains a file called `schema.prisma`, which contains the Prisma Schema with your database connection variable and schema models. +- Sets the `datasource` to {props.datasource || props.database} and the output to a custom location, respectively. +- Creates the [`.env` file](/orm/more/development-environment/environment-variables) in the root directory of the project, which is used for defining environment variables (such as your database connection) + +Note that the default schema created by `prisma init` uses PostgreSQL as the `provider`. If you didn't specify a provider with the `datasource-provider` option, you need to edit the `datasource` block to use the {(props.datasource || props.database)?.toLowerCase()} provider instead: + + +{`datasource db { + //edit-next-line + provider = "${(props.datasource || props.database)?.toLowerCase()}" + url = env("DATABASE_URL") +}`} + + +)} diff --git a/content/100-getting-started/index.mdx b/content/100-getting-started/index.mdx index b03a3857a7..2cea2e85d4 100644 --- a/content/100-getting-started/index.mdx +++ b/content/100-getting-started/index.mdx @@ -3,10 +3,8 @@ title: 'Get Started' metaTitle: 'Get started with Prisma' metaDescription: 'Build data-driven applications with ease using Prisma ORM, add connection pooling or global caching with Prisma Accelerate.' hide_title: true -tocDepth: 1 sidebar_position: 0 sidebar_class_name: firstTitle -pagination_next: 'getting-started/quickstart-sqlite' --- import { @@ -18,198 +16,166 @@ import { Grid, LinkCard, List, + Plus, + Plug, SignalStream, PrismaPostgres, SquareLogo, + QuickstartLinkCard } from '@site/src/components/GettingStarted'; +Getting started - - -Get started - -Welcome 👋 - -Explore our products that make it easy to build and scale data-driven applications: - -[**Prisma ORM**](/orm/overview/introduction/what-is-prisma) is a next-generation Node.js and TypeScript ORM that unlocks a new level of developer experience when working with databases thanks to its intuitive data model, automated migrations, type-safety & auto-completion. - -[**Prisma Postgres**](/postgres) is a managed PostgreSQL service that gives you an _always-on_ database with _pay-as-you-go_ pricing. + -[**Prisma Optimize**](/optimize/) helps you analyze queries, generate insights, and provides recommendations to make your database queries faster. - -[**Prisma Accelerate**](/accelerate) is a global database cache with scalable connection pooling to make your queries fast. + - +[**Prisma ORM**](/orm/overview/introduction/what-is-prisma) is an open-source ORM that provides fast, type-safe access to Postgres, MySQL, SQLite, and more databases, and runs smoothly across Node.js, Bun, and Deno. +```terminal +npx prisma init --db +``` + + -## Prisma ORM + -Add Prisma ORM to your application in a few minutes to start modeling your data, run schema migrations and query your database. +[**Prisma Postgres**](/postgres) is a fully managed PostgreSQL database that scales to zero, integrates with Prisma ORM and Prisma Studio, and includes a generous free tier. -### The easiest way to get started with Prisma +```terminal +npx create-db +``` + + + -_Explore all Prisma products at once._ +
- + -### Explore quickly with a SQLite database +The fastest way to set up **Prisma ORM** with a ready-to-use **Prisma Postgres** database. -_These options don't require you to have your own database running._ + - - - - +
+
-### Choose an option to get started with your own database +### Already have your own database? -_Select one of these options if you want to connect Prisma ORM to your own database._ +The fastest way to set Prisma ORM up with a ready-to-use database. - - -

- Set up Prisma ORM from scratch with your favorite database and - learn basic workflows like data modeling, querying, and migrations. -

- + - + - -
- -

- Get started with Prisma ORM and your existing database by - introspecting your database schema and learn how to query your database. -

- + + +
+
+ +### Using Prisma Postgres with other tools? + +You can also use Prisma Postgres with different tools or ORMs. Pick one of the options below to see how to connect. + + + {/* */} + + +
+
+ +### Add Prisma to your favorite framework? + +Working with **Next.js**, **Remix**, or another framework? You can easily add Prisma to your setup in just a few steps and start using it right away. + + - -
-
- -## Prisma Accelerate - -Make your database queries faster by scaling your database connections and caching database results at the edge with Prisma Accelerate. - - - - - -
- - -## Prisma Optimize - -Make your database queries faster by using the insights and recommendations generated by Prisma Optimize. - - - - - + + + + + diff --git a/content/200-orm/025-getting-started/10-quickstart.mdx b/content/200-orm/025-getting-started/10-quickstart.mdx new file mode 100644 index 0000000000..ef7fcb6d6a --- /dev/null +++ b/content/200-orm/025-getting-started/10-quickstart.mdx @@ -0,0 +1,11 @@ +--- +title: 'Quickstart with Prisma ORM' +sidebar_label: 'Quickstart' +metaTitle: 'Quickstart with Prisma ORM' +metaDescription: "This section provides a quick step-by-step guide to get started with Prisma ORM." +hide_table_of_contents: true +--- + +import { Redirect } from '@docusaurus/router'; + + \ No newline at end of file diff --git a/content/200-orm/025-getting-started/20-add-to-existing-project.mdx b/content/200-orm/025-getting-started/20-add-to-existing-project.mdx new file mode 100644 index 0000000000..7e89ef8e26 --- /dev/null +++ b/content/200-orm/025-getting-started/20-add-to-existing-project.mdx @@ -0,0 +1,11 @@ +--- +title: 'Add Prisma ORM to an existing project' +sidebar_label: 'Add to existing project' +metaTitle: 'Add Prisma ORM to an existing project' +metaDescription: "This section provides a step-by-step guide to add Prisma ORM to an existing project." +hide_table_of_contents: true +--- + +import { Redirect } from '@docusaurus/router'; + + \ No newline at end of file diff --git a/content/200-orm/025-getting-started/_category_.json b/content/200-orm/025-getting-started/_category_.json new file mode 100644 index 0000000000..8f75e9e8ae --- /dev/null +++ b/content/200-orm/025-getting-started/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Getting started", + "collapsible": false, + "collapsed": false +} diff --git a/content/200-orm/025-getting-started/index.mdx b/content/200-orm/025-getting-started/index.mdx new file mode 100644 index 0000000000..87b4690c63 --- /dev/null +++ b/content/200-orm/025-getting-started/index.mdx @@ -0,0 +1,13 @@ +--- +title: 'Getting started with Prisma ORM' +sidebar_label: 'Getting started' +metaTitle: 'Getting started with Prisma ORM' +metaDescription: "This section provides a quick step-by-step guide to get started with Prisma ORM." +hide_table_of_contents: true +--- + +## In this section + +You can either start with a fresh Prisma ORM project with a database of your choice or add Prisma ORM to an existing project. + + diff --git a/content/200-orm/050-overview/500-databases/600-mongodb.mdx b/content/200-orm/050-overview/500-databases/600-mongodb.mdx index b927e6d98d..0e519206ff 100644 --- a/content/200-orm/050-overview/500-databases/600-mongodb.mdx +++ b/content/200-orm/050-overview/500-databases/600-mongodb.mdx @@ -14,7 +14,7 @@ This guide discusses the concepts behind using Prisma ORM and MongoDB, explains -To connect Prisma ORM with MongoDB, refer to our [Getting Started documentation](/getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb). +To connect Prisma ORM with MongoDB, refer to our [Getting Started documentation](/getting-started/prisma-orm/quickstart/mongodb). @@ -360,8 +360,8 @@ console.log(findNullOrMissing) The fastest way to start using MongoDB with Prisma ORM is to refer to our Getting Started documentation: -- [Start from scratch](/getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb) -- [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/mongodb-typescript-mongodb) +- [Start from scratch](/getting-started/prisma-orm/quickstart/mongodb) +- [Add to existing project](/getting-started/prisma-orm/add-to-existing-project/mongodb) These tutorials will take you through the process of connecting to MongoDB, pushing schema changes, and using Prisma Client. diff --git a/content/200-orm/050-overview/500-databases/840-cockroachdb.mdx b/content/200-orm/050-overview/500-databases/840-cockroachdb.mdx index 3d3bdf18b9..ca6984dd09 100644 --- a/content/200-orm/050-overview/500-databases/840-cockroachdb.mdx +++ b/content/200-orm/050-overview/500-databases/840-cockroachdb.mdx @@ -213,8 +213,8 @@ model Device { The fastest way to start using CockroachDB with Prisma ORM is to refer to our Getting Started documentation: -- [Start from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-cockroachdb) -- [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-cockroachdb) +- [Start from scratch](/getting-started/prisma-orm/quickstart/cockroachdb) +- [Add to existing project](/getting-started/prisma-orm/add-to-existing-project/cockroachdb) These tutorials will take you through the process of connecting to CockroachDB, migrating your schema, and using Prisma Client. diff --git a/content/200-orm/050-overview/500-databases/850-planetscale.mdx b/content/200-orm/050-overview/500-databases/850-planetscale.mdx index f000a80a33..d325915dc1 100644 --- a/content/200-orm/050-overview/500-databases/850-planetscale.mdx +++ b/content/200-orm/050-overview/500-databases/850-planetscale.mdx @@ -49,7 +49,7 @@ PlanetScale's branching model and design for scalability means that there are al ## How to use branches and deploy requests -When connecting to PlanetScale with Prisma ORM, you will need to use the correct connection string for your branch. The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' from the dropdown to get the Prisma format for the connection URL. See Prisma ORM's [Getting Started guide](/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale) for more details of how to connect to a PlanetScale database. +When connecting to PlanetScale with Prisma ORM, you will need to use the correct connection string for your branch. The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' from the dropdown to get the Prisma format for the connection URL. See Prisma ORM's [Getting started guide](/getting-started/prisma-orm/quickstart/planetscale) for more details of how to connect to a PlanetScale database. Every PlanetScale database is created with a branch called `main`, which is initially a development branch that you can use to test schema changes on. Once you are happy with the changes you make there, you can [promote it](https://planetscale.com/docs/concepts/branching#promote-a-branch-to-production) to become a production branch. Note that you can only push new changes to a development branch, so further changes will need to be created on a separate development branch and then later deployed to production using a [deploy request](https://planetscale.com/docs/concepts/branching#promote-a-branch-to-production). @@ -257,7 +257,7 @@ model User { } ``` -For a more detailed example, see the [Getting Started guide for PlanetScale](/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-planetscale). +For a more detailed example, see the [Getting started guide for PlanetScale](/getting-started/prisma-orm/add-to-existing-project/planetscale). ## How to define shard keys in your Prisma schema (Preview) @@ -353,8 +353,8 @@ You can then use Prisma Client as you normally would with full type-safety. Pris The fastest way to start using PlanetScale with Prisma ORM is to refer to our Getting Started documentation: -- [Start from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-planetscale) -- [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale) +- [Start from scratch](/getting-started/prisma-orm/quickstart/planetscale) +- [Add to existing project](/getting-started/prisma-orm/add-to-existing-project/planetscale) These tutorials will take you through the process of connecting to PlanetScale, pushing schema changes, and using Prisma Client. diff --git a/content/200-orm/100-prisma-schema/50-introspection.mdx b/content/200-orm/100-prisma-schema/50-introspection.mdx index 8d64093664..5d5394d3f8 100644 --- a/content/200-orm/100-prisma-schema/50-introspection.mdx +++ b/content/200-orm/100-prisma-schema/50-introspection.mdx @@ -7,7 +7,7 @@ metaDescription: 'Learn how you can introspect your database to generate a data You can introspect your database using the Prisma CLI in order to generate the [data model](/orm/prisma-schema/data-model) in your [Prisma schema](/orm/prisma-schema). The data model is needed to [generate Prisma Client](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). -Introspection is often used to generate an _initial_ version of the data model when [adding Prisma ORM to an existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql). +Introspection is often used to generate an _initial_ version of the data model when [adding Prisma ORM to an existing project](/getting-started/prisma-orm/add-to-existing-project/postgresql). However, it can also be [used _repeatedly_ in an application](#introspection-with-an-existing-schema). This is most commonly the case when you're _not_ using [Prisma Migrate](/orm/prisma-migrate) but perform schema migrations using plain SQL or another migration tool. In that case, you also need to re-introspect your database and subsequently re-generate Prisma Client to reflect the schema changes in your [Prisma Client API](/orm/prisma-client). diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx index 7c8f5d58f0..99beeecfb0 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx @@ -11,9 +11,9 @@ import { -Prisma Client is an auto-generated and type-safe query builder that's _tailored_ to your data. The easiest way to get started with Prisma Client is by following the **[Quickstart](/getting-started/quickstart-sqlite)**. +Prisma Client is an auto-generated and type-safe query builder that's _tailored_ to your data. The easiest way to get started with Prisma Client is by following the **[Quickstart](/getting-started/prisma-orm/quickstart/sqlite)**. - + Quickstart (5 min) @@ -22,16 +22,15 @@ The setup instructions [below](#set-up) provide a high-level overview of the ste Set up a new project from scratch
-
Add Prisma to an existing project diff --git a/content/200-orm/200-prisma-client/500-deployment/101-traditional/200-deploy-to-heroku.mdx b/content/200-orm/200-prisma-client/500-deployment/101-traditional/200-deploy-to-heroku.mdx index d45ffd8200..96c86441f6 100644 --- a/content/200-orm/200-prisma-client/500-deployment/101-traditional/200-deploy-to-heroku.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/101-traditional/200-deploy-to-heroku.mdx @@ -53,7 +53,7 @@ For brevity, the guide does not cover how migrations are created with `prisma mi You will use Heroku's [release phase](https://devcenter.heroku.com/articles/release-phase) to run the `prisma migrate deploy` command so that the migrations are applied before the application starts. -To learn more about how migrations are created with Prisma Migrate, check out the [start from scratch guide](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql) +To learn more about how migrations are created with Prisma Migrate, check out the [start from scratch guide](/getting-started/prisma-orm/quickstart/postgresql) ## 1. Download the example and install dependencies diff --git a/content/200-orm/200-prisma-client/500-deployment/101-traditional/250-deploy-to-koyeb.mdx b/content/200-orm/200-prisma-client/500-deployment/101-traditional/250-deploy-to-koyeb.mdx index e6f3e9ac75..ae17d01eb4 100644 --- a/content/200-orm/200-prisma-client/500-deployment/101-traditional/250-deploy-to-koyeb.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/101-traditional/250-deploy-to-koyeb.mdx @@ -48,7 +48,7 @@ For brevity, the guide does not cover how migrations are created with `prisma mi You will use Koyeb's [build step](https://www.koyeb.com/docs/build-and-deploy/build-from-git#the-buildpack-build-process) to run the `prisma migrate deploy` command so that the migrations are applied before the application starts. -To learn more about how migrations are created with Prisma Migrate, check out the [start from scratch guide](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql) +To learn more about how migrations are created with Prisma Migrate, check out the [start from scratch guide](/getting-started/prisma-orm/quickstart/postgresql) ## 1. Download the example and install dependencies diff --git a/content/200-orm/300-prisma-migrate/300-workflows/20-prototyping-your-schema.mdx b/content/200-orm/300-prisma-migrate/300-workflows/20-prototyping-your-schema.mdx index 374f39309a..e019dc32a6 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/20-prototyping-your-schema.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/20-prototyping-your-schema.mdx @@ -19,7 +19,7 @@ The Prisma CLI has a dedicated command for prototyping schemas: [`db push`](/orm > **Notes**: > > - `db push` does not interact with or rely on migrations. The migrations table `_prisma_migrations` will not be created or updated, and no migration files will be generated. -> - When working with PlanetScale, we recommend that you use `db push` instead of `migrate`. For details refer to our Getting Started documentation, either [Start from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-planetscale) or [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale) depending on your situation. +> - When working with PlanetScale, we recommend that you use `db push` instead of `migrate`. For details refer to our Getting started documentation, either [Start from scratch guide](/getting-started/prisma-orm/quickstart/planetscale) or [Add to existing project guide](/getting-started/prisma-orm/add-to-existing-project/planetscale) depending on your situation. ## Choosing `db push` or Prisma Migrate diff --git a/content/200-orm/500-reference/380-connection-urls.mdx b/content/200-orm/500-reference/380-connection-urls.mdx index 68fd631f08..a8bf1b54a9 100644 --- a/content/200-orm/500-reference/380-connection-urls.mdx +++ b/content/200-orm/500-reference/380-connection-urls.mdx @@ -15,7 +15,7 @@ The connection URL is provided via the `url` field of a `datasource` block in yo - **Port**: The port on which your database server is running - **Database name**: The name of the database you want to use -Make sure you have this information at hand when getting started with Prisma ORM. If you don't have a database server running yet, you can either use a local SQLite database file (see the [Quickstart](/getting-started/quickstart-sqlite)) or [setup a free PostgreSQL database with Prisma Postgres](/postgres). +Make sure you have this information at hand when getting started with Prisma ORM. If you don't have a database server running yet, you can either use a local SQLite database file (see the [Quickstart](/getting-started/prisma-orm/quickstart/sqlite)) or [setup a free PostgreSQL database with Prisma Postgres](/postgres). ## Format diff --git a/content/200-orm/800-more/100-under-the-hood/index.mdx b/content/200-orm/800-more/100-under-the-hood/index.mdx index 8bf96648f7..c90ba799c4 100644 --- a/content/200-orm/800-more/100-under-the-hood/index.mdx +++ b/content/200-orm/800-more/100-under-the-hood/index.mdx @@ -11,7 +11,7 @@ This page gives an overview of the Prisma ORM internals and how it works "under Note that **this page does not contain any practical information that is relevant for _using_ Prisma ORM**. It rather aims at providing a _mental model_ for what the Prisma ORM toolkit _actually_ is and how the different tools that are available to developers are structured. -If you're new to using Prisma ORM, be sure to check out the [Quickstart](/getting-started/quickstart-sqlite) and [Introduction](/orm/overview/introduction/what-is-prisma) pages first. +If you're new to using Prisma ORM, be sure to check out the [Quickstart](/getting-started/prisma-orm/quickstart/sqlite) and [Introduction](/orm/overview/introduction/what-is-prisma) pages first.
diff --git a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/index.mdx b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/index.mdx index 637b4c4e4b..10454a4417 100644 --- a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/index.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/index.mdx @@ -138,14 +138,14 @@ While `OR`, `in`, and `notIn` operators are affected, `AND` and `NOT` are not af With Prisma ORM version 5.0.0, we require the `cockroachdb` provider to be used when connecting to CockroachDB databases. Previously, we had accepted `postgresql` as well, but we are removing that option. -If you were using [native database types](/orm/reference/prisma-schema-reference#postgresql) and also the `postgresql` provider, you will need to [baseline your database](/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb) from PostgreSQL to CockroachDB: +If you were using [native database types](/orm/reference/prisma-schema-reference#postgresql) and also the `postgresql` provider, you will need to [baseline your database](/getting-started/prisma-orm/add-to-existing-project/cockroachdb#5-baseline-your-database) from PostgreSQL to CockroachDB: 1. Backup your existing `schema.prisma` file (e.g. use version control) 2. Update your `datasource` provider from `postgresql` to `cockroachdb` 3. Use `npx prisma db pull --force` in order to overwrite your existing Prisma schema (including native types) to those that are on your CockroachDB instance. 4. Review changes between your Prisma schema backup and the new Prisma schema generated by `db pull`. You can either use the new schema as is, or update it to include your preferred spacing, comments, etc. -5. Delete your existing migrations. We will be [performing a baseline](/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb) in order to make your local setup agree with your existing CockroachDB instance. -6. Perform the [baselining steps](/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb). After these steps, you'll have migrated successfully from the `postgresql` provider to the `cockroachdb` provider! +5. Delete your existing migrations. We will be [performing a baseline](/getting-started/prisma-orm/add-to-existing-project/cockroachdb#5-baseline-your-database) in order to make your local setup agree with your existing CockroachDB instance. +6. Perform the [baselining steps](/getting-started/prisma-orm/add-to-existing-project/cockroachdb#5-baseline-your-database). After these steps, you'll have migrated successfully from the `postgresql` provider to the `cockroachdb` provider! ### Removal of `runtime/index.js` from generated client diff --git a/content/250-postgres/100-introduction/220-npx-create-db.mdx b/content/250-postgres/100-introduction/220-npx-create-db.mdx index 7b5c93b971..c0fa7a3289 100644 --- a/content/250-postgres/100-introduction/220-npx-create-db.mdx +++ b/content/250-postgres/100-introduction/220-npx-create-db.mdx @@ -123,7 +123,7 @@ Once you have the output, take the **Prisma ORM-optimized connection string** (` DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=..." ``` -You can now follow the [Prisma Postgres quickstart guide](/getting-started/quickstart-prismaPostgres#3-set-database-connection-url) to connect your Prisma project to this database. +You can now follow the [Prisma Postgres quickstart guide](/getting-started/prisma-orm/quickstart/prisma-postgres) to connect your Prisma project to this database. If you're using other tools or libraries, use the **standard PostgreSQL connection string** (`postgresql://...`) with any PostgreSQL-compatible client, such as `psql`, `pgAdmin`, `node-postgres`, or an ORM of your choice. Detailed instructions are available in the guide for [connecting via direct PostgreSQL connection string](/postgres/database/direct-connections). diff --git a/content/250-postgres/300-database/650-direct-connections.mdx b/content/250-postgres/300-database/650-direct-connections.mdx index d020e30f5b..b63e7f4687 100644 --- a/content/250-postgres/300-database/650-direct-connections.mdx +++ b/content/250-postgres/300-database/650-direct-connections.mdx @@ -74,7 +74,13 @@ While direct connections are in Early Access, the following timeouts apply: User permissions are limited to read, write and schema changes. It is not possible to create separate databases, manage users and roles, or perform other administrative actions. -## TCP tunnel +## TCP tunnel (deprecated) + +:::warning + +The TCP tunnel feature has been **deprecated** in favor of [direct connections](#how-to-connect-to-prisma-postgres-via-direct-tcp). Please use direct connections for all new integrations and migrate existing implementations. + +::: Prisma Postgres can be accessed securely via a TCP tunnel using the [`@prisma/ppg-tunnel`](https://www.npmjs.com/package/@prisma/ppg-tunnel) package, an authentication proxy designed for local database workflows. This package establishes a secure connection to Prisma Postgres through a local TCP server, enabling secure access while automatically handling traffic routing and authentication. diff --git a/content/250-postgres/350-integrations/400-mcp-server.mdx b/content/250-postgres/350-integrations/400-mcp-server.mdx index e1c263571f..42caa36c6f 100644 --- a/content/250-postgres/350-integrations/400-mcp-server.mdx +++ b/content/250-postgres/350-integrations/400-mcp-server.mdx @@ -56,11 +56,6 @@ The remote Prisma MCP server follows the standard JSON-based configuration for M } ``` - -:::tip -If you want to try it the remote MCP server and explore it's capabilities, we recommend [Cloudflare's AI Playground](https://playground.ai.cloudflare.com/) for that. Add the `https://mcp.prisma.io/mcp` URL into the text field with the **Enter MCP server URL** placeholder, click **Connect**, and then authenticate with the [Prisma Console](https://console.prisma.io) in the popup window. Once connected, you can send prompts to the Playground and see what MCP tools the LLM chooses based on your prompts. -::: - ### Sample prompts - "Show me a list of all the databases in my account." diff --git a/content/250-postgres/400-query-optimization/100-setup.mdx b/content/250-postgres/400-query-optimization/100-setup.mdx index c4737247b1..a7a19dd194 100644 --- a/content/250-postgres/400-query-optimization/100-setup.mdx +++ b/content/250-postgres/400-query-optimization/100-setup.mdx @@ -12,7 +12,7 @@ Before you begin with Prisma Optimize for Prisma Postgres, ensure you have the f - A [Prisma Data Platform account](https://console.prisma.io/optimize?utm_source=docs&utm_medium=optimize-page). - A project using [Prisma Client](/orm/prisma-client) version `5.0.0` or higher (we recommend using the latest version). -- A [Prisma Postgres database](/postgres/introduction/getting-started). +- A [Prisma Postgres database](/postgres/getting-started). :::note diff --git a/content/250-postgres/50-getting-started/100-quickstart.mdx b/content/250-postgres/50-getting-started/100-quickstart.mdx new file mode 100644 index 0000000000..5fea9ceeeb --- /dev/null +++ b/content/250-postgres/50-getting-started/100-quickstart.mdx @@ -0,0 +1,11 @@ +--- +title: 'Quickstart with Prisma ORM' +sidebar_label: 'Quickstart' +metaTitle: 'Quickstart: Prisma ORM with Prisma Postgres (5 min)' +metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to Prisma Postgres and generating a Prisma Client for database access.' +hide_table_of_contents: true +--- + +import { Redirect } from '@docusaurus/router'; + + \ No newline at end of file diff --git a/content/250-postgres/50-getting-started/200-import-from-existing-database.mdx b/content/250-postgres/50-getting-started/200-import-from-existing-database.mdx new file mode 100644 index 0000000000..e72aa23fdf --- /dev/null +++ b/content/250-postgres/50-getting-started/200-import-from-existing-database.mdx @@ -0,0 +1,11 @@ +--- +title: 'Import data from an existing PostgreSQL database' +sidebar_label: 'Import from existing database' +metaTitle: 'Import from existing Postgres database into Prisma Postgres' +metaDescription: 'Learn how to import data from an existing PostgreSQL database into Prisma Postgres.' +hide_table_of_contents: true +--- + +import { Redirect } from '@docusaurus/router'; + + \ No newline at end of file diff --git a/content/250-postgres/50-getting-started/_category_.json b/content/250-postgres/50-getting-started/_category_.json new file mode 100644 index 0000000000..8f75e9e8ae --- /dev/null +++ b/content/250-postgres/50-getting-started/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Getting started", + "collapsible": false, + "collapsed": false +} diff --git a/content/250-postgres/100-introduction/200-getting-started.mdx b/content/250-postgres/50-getting-started/index.mdx similarity index 86% rename from content/250-postgres/100-introduction/200-getting-started.mdx rename to content/250-postgres/50-getting-started/index.mdx index ac3fc926fd..9a63cf6c87 100644 --- a/content/250-postgres/100-introduction/200-getting-started.mdx +++ b/content/250-postgres/50-getting-started/index.mdx @@ -8,7 +8,6 @@ toc: true ## Quickstart - To **bootstrap a new Prisma ORM project with a Prisma Postgres database**, run the following command in your terminal: ```terminal @@ -31,7 +30,7 @@ You can learn more about `npx create-db` in [the dedicated documentation](/postg The easiest ways to get started with Prisma Postgres is by following these guides: -- [**Start from scratch**](/getting-started/quickstart-prismaPostgres) +- [**Start from scratch**](/getting-started/prisma-postgres/quickstart/prisma-orm) - [**Import data from an existing database**](/getting-started/prisma-postgres/import-from-existing-database-postgresql) If you are looking to explore Prisma Postgres in a fullstack project, check out these resources: @@ -39,16 +38,6 @@ If you are looking to explore Prisma Postgres in a fullstack project, check out - [**Build a fullstack app with Next.js 15**](/guides/nextjs) - [**Next.js 15 example app**](https://github.com/prisma/nextjs-prisma-postgres-demo) (including authentication) -:::note - -When you are using Prisma Postgres, you don't need to include the query engine in the generated Prisma Client code. Make sure to always generate it using the `--no-engine` flag: - -```terminal -prisma generate --no-engine -``` - -::: - ## Connect via any database library / tool You can access Prisma Postgres with any ORM or database tool of your choice via [direct TCP connections](/postgres/database/direct-connections). @@ -67,4 +56,10 @@ Once you have the connection string, you can follow the setup docs for PostgreSQ - [TypeORM](https://typeorm.io/#installation) - [Sequelize](https://sequelize.org/docs/v6/getting-started/) - [MikroORM](https://mikro-orm.io/docs/quick-start) -- [node-postgres](https://node-postgres.com/) \ No newline at end of file +- [node-postgres](https://node-postgres.com/) + +## In this section + +You can either start with a fresh Prisma Postgres project or import data from an existing database to Prisma Postgres. + + diff --git a/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx b/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx index 388b68f1c8..634859b3b1 100644 --- a/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx +++ b/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx @@ -104,7 +104,7 @@ pnpm add @prisma/extension-accelerate :::info -This guide uses [Prisma Postgres](/postgres/introduction/getting-started). If you plan to use a different database, you can omit the [@prisma/extension-accelerate package](https://www.npmjs.com/package/@prisma/extension-accelerate/). +This guide uses [Prisma Postgres](/postgres/getting-started). If you plan to use a different database, you can omit the [@prisma/extension-accelerate package](https://www.npmjs.com/package/@prisma/extension-accelerate/). ::: @@ -126,7 +126,7 @@ Enter a name for your project and choose a database region. :::info -We're going to be using [Prisma Postgres](/postgres/introduction/getting-started) in this guide. If you're not using a Prisma Postgres database, you won't need to add the `--db` flag. +We're going to be using [Prisma Postgres](/postgres/getting-started) in this guide. If you're not using a Prisma Postgres database, you won't need to add the `--db` flag. ::: @@ -181,7 +181,7 @@ Next, add helper scripts to your `package.json` to simplify Prisma commands: :::info -If you're not using [Prisma Postgres](/postgres/introduction/getting-started) for your database, exclude the `--no-engine` flag from the `db:generate` script. +If you're not using [Prisma Postgres](/postgres/getting-started) for your database, exclude the `--no-engine` flag from the `db:generate` script. ::: @@ -221,7 +221,7 @@ if (process.env.NODE_ENV !== "production") { :::info -If you're not using [Prisma Postgres](/postgres/introduction/getting-started) for your database, exclude the `import { withAccelerate }` line and `.$extends(withAccelerate())` from the line following it. +If you're not using [Prisma Postgres](/postgres/getting-started) for your database, exclude the `import { withAccelerate }` line and `.$extends(withAccelerate())` from the line following it. ::: diff --git a/content/800-guides/230-betterauth-nextjs.mdx b/content/800-guides/230-betterauth-nextjs.mdx index 5a048fb22c..4907a37fa0 100644 --- a/content/800-guides/230-betterauth-nextjs.mdx +++ b/content/800-guides/230-betterauth-nextjs.mdx @@ -1,8 +1,8 @@ --- -title: 'How to use Prisma ORM with Better-Auth and Next.js' -metaTitle: 'How to use Prisma ORM and Prisma Postgres with Better-Auth and Next.js' -description: 'Learn how to use Prisma ORM in a Next.js app with Better-Auth' -sidebar_label: 'Better-Auth (with Next.js)' +title: 'How to use Prisma ORM with Better Auth and Next.js' +metaTitle: 'How to use Prisma ORM and Prisma Postgres with Better Auth and Next.js' +description: 'Learn how to use Prisma ORM in a Next.js app with Better Auth' +sidebar_label: 'Better Auth (with Next.js)' image: '/img/guides/prisma-betterauth-nextjs-cover.png' completion_time: '25 min' community_section: true @@ -10,9 +10,9 @@ community_section: true ## Introduction -[Better-Auth](https://better-auth.com/) is a modern, open-source authentication solution for web applications. It's built with TypeScript, React, and Prisma to provide a simple and extensible auth experience. +[Better Auth](https://better-auth.com/) is a modern, open-source authentication solution for web applications. It's built with TypeScript and provides a simple and extensible auth experience with support for multiple database adapters, including Prisma. -In this guide, you'll wire Better-Auth into a brand-new [Next.js](https://nextjs.org/) app and persist users in a [Prisma Postgres](https://prisma.io/postgres) database. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/betterauth-nextjs). +In this guide, you'll wire Better Auth into a brand-new [Next.js](https://nextjs.org/) app and persist users in a [Prisma Postgres](https://prisma.io/postgres) database. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/betterauth-nextjs). ## Prerequisites @@ -78,15 +78,15 @@ Once installed, initialize Prisma in your project: npx prisma init --db --output ../src/generated/prisma ``` :::info -You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My Better-Auth Project" +You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My Better Auth Project" ::: This will create: -- A `prisma` directory with a `schema.prisma` file. -- A Prisma Postgres database. -- A `.env` file containing the `DATABASE_URL` at the project root. -- An `output` directory for the generated Prisma Client as `better-auth/generated/prisma`. +- A `prisma` directory with a `schema.prisma` file +- A Prisma Postgres database +- A `.env` file containing the `DATABASE_URL` at the project root +- An `output` directory for the generated Prisma Client as `better-auth/generated/prisma` ### 2.2. Configure the Prisma client generator @@ -98,7 +98,7 @@ npx prisma generate ### 2.3. Set up a global Prisma client -Create a `/lib` directory and a `prisma.ts` file inside it. This file will be used to create and export your Prisma Client instance. +In the `src` directory, create a `lib` folder and a `prisma.ts` file inside it. This file will be used to create and export your Prisma Client instance. ```terminal mkdir -p src/lib @@ -149,19 +149,19 @@ We recommend using a connection pooler (like [Prisma Accelerate](https://www.pri If you choose not to use one, **avoid** instantiating `PrismaClient` globally in long-lived environments. Instead, create and dispose of the client per request to prevent exhausting your database connections. ::: -## 3. Set up Better-Auth +## 3. Set up Better Auth -Now it's time to integrate Better-Auth for authentication. +Now it's time to integrate Better Auth for authentication. -### 3.1. Install and configure Better-Auth +### 3.1. Install and configure Better Auth -First, install the Better-Auth core package: +First, install the Better Auth core package: ```terminal npm install better-auth ``` -Next, generate a secure secret that Better-Auth will use to sign authentication tokens. This ensures your tokens cannot be messed with. +Next, generate a secure secret that Better Auth will use to sign authentication tokens. This ensures your tokens cannot be messed with. ```terminal npx @better-auth/cli@latest secret @@ -170,7 +170,7 @@ npx @better-auth/cli@latest secret Copy the generated secret and add it, along with your application's URL, to your `.env` file: ```dotenv file=.env showLineNumbers -# Better-Auth +# Better Auth //add-start BETTER_AUTH_SECRET=your-generated-secret BETTER_AUTH_URL=http://localhost:3000 @@ -180,13 +180,13 @@ BETTER_AUTH_URL=http://localhost:3000 DATABASE_URL="your-database-url" ``` -Now, create a configuration file for Better-Auth at `src/lib/auth.ts`: +Now, create a configuration file for Better Auth. In the `src/lib` directory, create an `auth.ts` file: ```terminal touch src/lib/auth.ts ``` -In this file, you'll configure Better-Auth to use the Prisma adapter, which allows it to persist user and session data in your database. You will also enable email and password authentication. +In this file, you'll configure Better Auth to use the Prisma adapter, which allows it to persist user and session data in your database. You will also enable email and password authentication. ```ts file=src/lib/auth.ts import { betterAuth } from 'better-auth' @@ -200,7 +200,7 @@ export const auth = betterAuth({ }) ``` -Better-Auth also supports other sign-in methods like social logins (Google, GitHub, etc.), which you can explore in their [documentation](https://www.better-auth.com/docs/authentication/email-password). +Better Auth also supports other sign-in methods like social logins (Google, GitHub, etc.), which you can explore in their [documentation](https://www.better-auth.com/docs/authentication/email-password). ```ts file=src/lib/auth.ts import { betterAuth } from 'better-auth' @@ -240,9 +240,9 @@ export const auth = betterAuth({ ``` ::: -### 3.2. Add Better-Auth models to your schema +### 3.2. Add Better Auth models to your schema -Better-Auth provides a CLI command to automatically add the necessary authentication models (`User`, `Session`, `Account`, and `Verification`) to your `schema.prisma` file. +Better Auth provides a CLI command to automatically add the necessary authentication models (`User`, `Session`, `Account`, and `Verification`) to your `schema.prisma` file. Run the following command: @@ -329,16 +329,16 @@ npx prisma migrate dev --name add-auth-models ## 4. Set up the API routes -Better-Auth needs an API endpoint to handle authentication requests like sign-in, sign-up, and sign-out. You'll create a catch-all API route in Next.js to handle all requests sent to `/api/auth/[...all]`. +Better Auth needs an API endpoint to handle authentication requests like sign-in, sign-up, and sign-out. You'll create a catch-all API route in Next.js to handle all requests sent to `/api/auth/[...all]`. -First, create the necessary directory and file: +In the `src/app/api` directory, create an `auth/[...all]` folder structure and a `route.ts` file inside it: ```terminal mkdir -p "src/app/api/auth/[...all]" touch "src/app/api/auth/[...all]/route.ts" ``` -Add the following code to the newly created `route.ts` file. This code uses a helper from Better-Auth to create Next.js-compatible `GET` and `POST` request handlers. +Add the following code to the newly created `route.ts` file. This code uses a helper from Better Auth to create Next.js-compatible `GET` and `POST` request handlers. ```ts import { auth } from "@/lib/auth"; @@ -347,7 +347,7 @@ import { toNextJsHandler } from "better-auth/next-js"; export const { POST, GET } = toNextJsHandler(auth); ``` -Next, you'll need a client-side utility to interact with these endpoints from your React components. Create a new file `src/lib/auth-client.ts`: +Next, you'll need a client-side utility to interact with these endpoints from your React components. In the `src/lib` directory, create an `auth-client.ts` file: ```terminal touch src/lib/auth-client.ts @@ -363,7 +363,11 @@ export const { signIn, signUp, signOut, useSession } = createAuthClient() ## 5. Set up your pages -Now, let's build the user interface for authentication. Create the pages for signing up, signing in, and a protected dashboard: +Now, let's build the user interface for authentication. In the `src/app` directory, create the following folder structure: + +- `sign-up/page.tsx` +- `sign-in/page.tsx` +- `dashboard/page.tsx` ```terminal mkdir -p src/app/{sign-up,sign-in,dashboard} @@ -410,7 +414,7 @@ export default function SignUpPage() { } ``` -Now, import the `signUp` function from your Better-Auth client and add the `handleSubmit` function. This function is triggered on form submission and calls the `signUp.email` method provided by Better-Auth, passing the user's name, email, and password. +Now, import the `signUp` function from your Better Auth client and add the `handleSubmit` function. This function is triggered on form submission and calls the `signUp.email` method provided by Better Auth, passing the user's name, email, and password. ```tsx file=src/app/sign-up/page.tsx "use client"; @@ -611,7 +615,7 @@ export default function SignInPage() { } ``` -Add the `handleSubmit` function, this time importing and using the `signIn.email` method from Better-Auth. +Add the `handleSubmit` function, this time importing and using the `signIn.email` method from Better Auth. ```tsx file=src/app/sign-in/page.tsx "use client"; @@ -778,7 +782,7 @@ export default function DashboardPage() { } ``` -Import the `useSession` hook from your Better-Auth client. This hook is the key to managing authentication state on the client side. It provides the session data and a pending status. +Import the `useSession` hook from your Better Auth client. This hook is the key to managing authentication state on the client side. It provides the session data and a pending status. ```tsx file=src/app/dashboard/page.tsx "use client"; @@ -816,7 +820,7 @@ export default function DashboardPage() { const router = useRouter(); const { data: session, isPending } = useSession(); - //add-start: redirect if not signed in + //add-start useEffect(() => { if (!isPending && !session?.user) { router.push("/sign-in"); @@ -851,7 +855,7 @@ export default function DashboardPage() { } }, [isPending, session, router]); - //add-start: loading and redirect states + //add-start if (isPending) return

Loading...

; if (!session?.user) @@ -890,7 +894,7 @@ export default function DashboardPage() { if (!session?.user) return

Redirecting...

; - //add-start: destructure user from session + //add-start const { user } = session; //add-end @@ -899,7 +903,7 @@ export default function DashboardPage() {

Dashboard

Welcome, {user.name || "User"}!

Email: {user.email}

- {/* add-start: sign out button */} + {/* add-start */} + +

Already have an account? Sign in here.

+ //add-end + + + +``` + +Now add a script to handle form submission. Import the `authClient` and add an event listener to the form that prevents the default submission behavior, extracts the form data, and calls the Better Auth sign-up method. + +```html file=src/pages/sign-up/index.astro +--- +export const prerender = false; +--- + + + + + + Sign Up + + +
+

Sign Up

+
+ + + + +
+

Already have an account? Sign in here.

+
+ //add-start + + //add-end + + +``` + +Finally, add a server-side check to redirect authenticated users away from this page. If a user is already signed in, they should be redirected to the dashboard instead. + +```html file=src/pages/sign-up/index.astro +--- +export const prerender = false; + +//add-start +if (Astro.locals.user?.id) return Astro.redirect("/dashboard"); +//add-end +--- + + + + + + Sign Up + + +
+

Sign Up

+
+ + + + +
+

Already have an account? Sign in here.

+
+ + + +``` + +### 7.2. Sign in page + +This page allows existing users to authenticate. Start with the basic HTML structure in `src/pages/sign-in/index.astro`. + +```html file=src/pages/sign-in/index.astro +--- +export const prerender = false; +--- + + + + + + Sign In + + +
+

Sign In

+
+ + +``` + +Add a form with input fields for email and password. This form will collect the user's credentials. + +```html file=src/pages/sign-in/index.astro +--- +export const prerender = false; +--- + + + + + + Sign In + + +
+

Sign In

+ //add-start +
+ + + +
+

Don't have an account? Sign up here.

+ //add-end +
+ + +``` + +Now add a script to handle form submission. Import the `authClient` and add an event listener that prevents default submission, extracts the form data, and calls the Better Auth sign-in method. + +```html file=src/pages/sign-in/index.astro +--- +export const prerender = false; +--- + + + + + + Sign In + + +
+

Sign In

+
+ + + +
+

Don't have an account? Sign up here.

+
+ //add-start + + //add-end + + +``` + +Finally, add a server-side check to redirect authenticated users away from this page. If a user is already signed in, they should be redirected to the dashboard instead. + +```html file=src/pages/sign-in/index.astro +--- +export const prerender = false; + +//add-start +if (Astro.locals.user?.id) return Astro.redirect("/dashboard"); +//add-end +--- + + + + + + Sign In + + +
+

Sign In

+
+ + + +
+

Don't have an account? Sign up here.

+
+ + + +``` + +### 7.3. Dashboard page + +This is the protected page for authenticated users. Start with the basic HTML structure in `src/pages/dashboard/index.astro`. + +```html file=src/pages/dashboard/index.astro +--- +export const prerender = false; +--- + + + + + + Dashboard + + +
+

Dashboard

+
+ + +``` + +Add a server-side check to protect this route. If the user is not authenticated, redirect them to the sign-in page. + +```html file=src/pages/dashboard/index.astro +--- +export const prerender = false; + +//add-start +if (!Astro.locals.user?.id) return Astro.redirect("/sign-in"); +//add-end +--- + + + + + + Dashboard + + +
+

Dashboard

+
+ + +``` + +Now display the authenticated user's information. The `Astro.locals.user` object contains the user data that was set by the middleware. + +```html file=src/pages/dashboard/index.astro +--- +export const prerender = false; + +if (!Astro.locals.user?.id) return Astro.redirect("/sign-in"); +--- + + + + + + Dashboard + + +
+

Dashboard

+ //add-next-line +
{JSON.stringify(Astro.locals.user, null, 2)}
+
+ + +``` + +Finally, add a sign-out button. Import the `authClient` and add a button that calls the sign-out method, allowing the user to log out and be redirected to the sign-in page. + +```html file=src/pages/dashboard/index.astro +--- +export const prerender = false; + +if (!Astro.locals.user?.id) return Astro.redirect("/sign-in"); +--- + + + + + + Dashboard + + +
+

Dashboard

+
{JSON.stringify(Astro.locals.user, null, 2)}
+ //add-next-line + +
+ //add-start + + //add-end + + +``` + +### 7.4. Home page + +Finally, update the home page to provide simple navigation. Replace the contents of `src/pages/index.astro` with the following: + +```html file=src/pages/index.astro +--- +export const prerender = false; +--- + + + + + + Better Auth + Astro + Prisma + + +
+

Better Auth + Astro + Prisma

+ { + Astro.locals.user ? ( +
+

Welcome back, {Astro.locals.user.name}!

+ Go to Dashboard +
+ ) : ( + + ) + } +
+ + +``` + +## 8. Test it out + +Your application is now fully configured. + +1. Start the development server to test it: + +```terminal +npm run dev +``` + +2. Navigate to `http://localhost:4321` in your browser. You should see the home page with "Sign Up" and "Sign In" links. + +3. Click on **Sign Up**, create a new account, and you should be redirected to the dashboard. You can then sign out and sign back in. + +4. To view the user data directly in your database, you can use Prisma Studio. + +```terminal +npx prisma studio +``` + +5. This will open a new tab in your browser where you can see the `User`, `Session`, and `Account` tables and their contents. + +:::success + +Congratulations! You now have a fully functional authentication system built with Better Auth, Prisma, and Astro. + +::: + +## Next steps + +- Add support for social login or magic links +- Implement password reset and email verification +- Add user profile and account management pages +- Deploy to Vercel or Netlify and secure your environment variables +- Extend your Prisma schema with custom application models + +## Further reading + +- [Better Auth documentation](https://www.better-auth.com/docs) +- [Prisma documentation](/orm/overview/introduction) +- [Astro documentation](https://astro.build/docs) diff --git a/content/900-ai/prompts/astro.mdx b/content/900-ai/prompts/astro.mdx index 2fb3fe5caa..473c95d336 100644 --- a/content/900-ai/prompts/astro.mdx +++ b/content/900-ai/prompts/astro.mdx @@ -260,3 +260,29 @@ When asked about Prisma + Astro implementation, you MUST: Remember: There are NO EXCEPTIONS to these rules. ```` + +## Running the application + +Get your application running locally in three quick steps: + +**1. Generate the Prisma Client:** + +```terminal +npx prisma generate --no-engine +``` + +**2. View your database in Prisma Studio:** + +```terminal +npm run db:studio +``` + +Prisma Studio opens at `localhost:5555` where you can inspect your `User` table and see the test user stored in your database. + +**3. Start your Next.js development server:** + +```terminal +npm run dev +``` + +Visit `http://localhost:3000` to see your Next.js application live, displaying your first user fetched directly from your Prisma Postgres database! \ No newline at end of file diff --git a/content/900-ai/prompts/nextjs.mdx b/content/900-ai/prompts/nextjs.mdx index 329da64442..a2a01ec1aa 100644 --- a/content/900-ai/prompts/nextjs.mdx +++ b/content/900-ai/prompts/nextjs.mdx @@ -15,6 +15,22 @@ Include this prompt in your AI assistant to guide consistent code generation for - **Zed**: Use `/file` followed by your prompt's path. - **Windsurf**: Use `@Files` and choose your prompt file from the list. +## Video Tutorial + +Watch this step-by-step walkthrough showing this prompt in action: + +
+ +
+ ## Prompt ````md diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 5bc27295e3..6807372575 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -4,6 +4,7 @@ import { themes as prismThemes } from "prism-react-renderer"; import type { Config, RouteConfig } from "@docusaurus/types"; import type * as Preset from "@docusaurus/preset-classic"; +import type { PluginOptions } from "@signalwire/docusaurus-plugin-llms-txt/public"; const DOCUSAURUS_BASE_URL = process.env.DOCUSAURUS_BASE_URL ?? "/"; @@ -91,6 +92,21 @@ const config: Config = { enableInDevelopment: false, }, ], + [ + "@signalwire/docusaurus-plugin-llms-txt", + { + // Enable with defaults + generate: { + enableMarkdownFiles: true, + enableLlmsFullTxt: false, + }, + include: { + includeBlog: false, + includePages: false, + includeDocs: true, + }, + } satisfies PluginOptions, + ], async function pluginLlmsTxt(context) { return { name: "llms-txt-plugin", @@ -297,7 +313,7 @@ const config: Config = { to: "/postgres/database/prisma-studio", label: "Studio", sub: "Explore and manipulate your data", - icon: "fa-regular fa-table" + icon: "fa-regular fa-table", }, { type: "docSidebar", @@ -305,7 +321,7 @@ const config: Config = { className: "teal", label: "Optimize", sub: "AI-driven query analysis", - icon: "fa-regular fa-magnifying-glass-chart" + icon: "fa-regular fa-magnifying-glass-chart", }, { type: "docSidebar", @@ -313,7 +329,7 @@ const config: Config = { className: "teal", label: "Accelerate", sub: "Make your database global", - icon: "fa-regular fa-bolt" + icon: "fa-regular fa-bolt", }, { type: "docSidebar", @@ -321,7 +337,7 @@ const config: Config = { sidebarId: "aiSidebar", label: "Prisma + AI", sub: "Build faster with Prisma + AI", - icon: "fa-regular fa-robot" + icon: "fa-regular fa-robot", }, ], }, diff --git a/functions/_middleware.ts b/functions/_middleware.ts new file mode 100644 index 0000000000..cfd258bc87 --- /dev/null +++ b/functions/_middleware.ts @@ -0,0 +1,113 @@ +interface Env { + ASSETS: { + fetch: typeof fetch; + }; +} + +const AI_CRAWLER_PATTERNS = [ + 'GPTBot', + 'OAI-SearchBot', + 'ChatGPT-User', + 'ChatGPT-User 2.0', + 'anthropic-ai', + 'OpenAI', + 'ClaudeBot', + 'claude-web', + 'Claude/', + 'Claude-User', + 'anthropic', + 'PerplexityBot', + 'Perplexity-User', + 'Google-Extended', + 'BingBot', + 'Amazonbot', + 'Applebot', + 'Applebot-Extended', + 'FacebookBot', + 'meta-externalagent', + 'LinkedInBot', + 'Bytespider', + 'AI2Bot', + 'CCBot', + 'Diffbot', + 'DuckAssistBot', + 'DuckDuckGo', + 'DeepSeekBot', + 'cohere-ai', + 'omgili', + 'TimpiBot', + 'YouBot', + 'MistralAI-User', + 'ImagesiftBot', + 'Scrapy', + + 'chatgpt', + 'openai', + 'gpt', + 'claude', + 'anthropic', + 'cursor', + 'windsurf', + 'perplexity', + 'copilot', + 'ai-agent', + 'llm-agent', +]; + +function isAICrawler(request: Request): boolean { + // if (!userAgent) return false; + + const userAgent = request.headers.get('user-agent') || ''; + const accept = request.headers.get('accept') || ''; + + const hasHtml = accept.includes('text/html'); + + const prefersNonHtml = + !hasHtml && + (accept.includes('application/json') || + accept.includes('text/plain') || + accept.includes('application/xml')); + + const hasAiUserAgent = AI_CRAWLER_PATTERNS.some((pattern) => userAgent.toLowerCase().includes(pattern.toLowerCase())); + + return prefersNonHtml || hasAiUserAgent + + // const normalizedUA = userAgent.toLowerCase(); + // return AI_CRAWLER_PATTERNS.some((pattern) => normalizedUA.includes(pattern.toLowerCase())); +} + +export const onRequest: PagesFunction = async (context) => { + const { request, next } = context; + + if (isAICrawler(request)) { + const url = new URL(request.url); + const urlPath = url.pathname; + + const markdownPath = `${urlPath}.md`; + + const markdownRequest = new Request(new URL(markdownPath, url.origin), { + method: request.method, + headers: request.headers, + }); + + const response = await context.env.ASSETS.fetch(markdownRequest); + + if (response.ok) { + // Check what content type we actually got + const actualContentType = response.headers.get('content-type'); + console.log(`Fetched ${markdownPath}, got content-type: ${actualContentType}`); + + return new Response(response.body, { + status: 200, + headers: { + 'Content-Type': 'text/markdown; charset=utf-8', + 'Cache-Control': 'public, max-age=3600', + }, + }); + } + + return next(); + } + + return next(); +}; diff --git a/functions/types.d.ts b/functions/types.d.ts new file mode 100644 index 0000000000..86ad944860 --- /dev/null +++ b/functions/types.d.ts @@ -0,0 +1,12 @@ +// TypeScript definitions for Cloudflare Pages Functions +interface EventContext { + request: Request; + env: Env; + params: Record; + data: Record; + next: () => Promise; + waitUntil: (promise: Promise) => void; + passThroughOnException: () => void; +} + +type PagesFunction = (context: EventContext) => Response | Promise; diff --git a/package-lock.json b/package-lock.json index b57e49bc85..128d01fdb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@react-aria/overlays": "^3.29.1", "@react-aria/tooltip": "^3.8.7", "@react-aria/utils": "^3.24.1", + "@signalwire/docusaurus-plugin-llms-txt": "^2.0.0-alpha.2", "clsx": "^2.1.1", "copy-text-to-clipboard": "^3.1.0", "docusaurus-plugin-sass": "^0.2.6", @@ -6511,6 +6512,44 @@ "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", "license": "BSD-3-Clause" }, + "node_modules/@signalwire/docusaurus-plugin-llms-txt": { + "version": "2.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/@signalwire/docusaurus-plugin-llms-txt/-/docusaurus-plugin-llms-txt-2.0.0-alpha.2.tgz", + "integrity": "sha512-jLATcj60UE4/iYtrB4xbBqki9/+WSf2t/BQ2hcszzTnm1Rafl+kW7ykh1TXQSeq97nQaL6zTDzsJYrIdcFig1A==", + "license": "MIT", + "dependencies": { + "fs-extra": "^11.0.0", + "hast-util-select": "^6.0.4", + "hast-util-to-html": "^9.0.5", + "hast-util-to-string": "^3.0.1", + "p-map": "^7.0.2", + "rehype-parse": "^9", + "rehype-remark": "^10", + "remark-gfm": "^4", + "remark-stringify": "^11", + "string-width": "^5.0.0", + "unified": "^11", + "unist-util-visit": "^5" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@docusaurus/core": "^3.0.0" + } + }, + "node_modules/@signalwire/docusaurus-plugin-llms-txt/node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -11667,6 +11706,20 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-embedded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", + "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-from-dom": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", @@ -11749,6 +11802,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-is-body-ok-link": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", + "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-is-element": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", @@ -11762,6 +11828,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-minify-whitespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", + "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-parse-selector": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", @@ -11775,6 +11858,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-is-body-ok-link": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-raw": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", @@ -11855,6 +11955,29 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-jsx-runtime": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", @@ -11882,6 +12005,32 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-mdast": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/hast-util-to-mdast/-/hast-util-to-mdast-10.1.2.tgz", + "integrity": "sha512-FiCRI7NmOvM4y+f5w32jPRzcxDIz+PUqDwEqn1A+1q2cdp3B8Gx7aVrXORdOKjMNDQsD1ogOr896+0jJHW1EFQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "hast-util-to-text": "^4.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-minify-whitespace": "^6.0.0", + "trim-trailing-lines": "^2.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-parse5": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", @@ -11924,6 +12073,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -18919,6 +19084,35 @@ "regjsparser": "bin/parser" } }, + "node_modules/rehype-minify-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-6.0.2.tgz", + "integrity": "sha512-Zk0pyQ06A3Lyxhe9vGtOtzz3Z0+qZ5+7icZ/PL/2x1SHPbKao5oB/g/rlc6BCTajqBb33JcOe71Ye1oFsuYbnw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-raw": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", @@ -18949,6 +19143,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-remark": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-remark/-/rehype-remark-10.0.1.tgz", + "integrity": "sha512-EmDndlb5NVwXGfUa4c9GPK+lXeItTilLhE6ADSaQuHr4JUlKw9MidzGzx4HpqZrNCt6vnHmEifXQiiA+CEnjYQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "hast-util-to-mdast": "^10.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -20702,6 +20913,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/trim-trailing-lines": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz", + "integrity": "sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -20922,6 +21143,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-is": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", diff --git a/package.json b/package.json index f9989b6807..93af9e443b 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,10 @@ "@react-aria/overlays": "^3.29.1", "@react-aria/tooltip": "^3.8.7", "@react-aria/utils": "^3.24.1", + "@signalwire/docusaurus-plugin-llms-txt": "^2.0.0-alpha.2", "clsx": "^2.1.1", - "docusaurus-plugin-sass": "^0.2.6", "copy-text-to-clipboard": "^3.1.0", + "docusaurus-plugin-sass": "^0.2.6", "posthog-docusaurus": "^2.0.4", "prism-react-renderer": "^2.4.1", "react": "^19.1.1", diff --git a/sidebars.ts b/sidebars.ts index e38be5d27a..da2972ced2 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -44,241 +44,183 @@ const sidebars: SidebarsConfig = { className: "firstTitle", items: [ "getting-started/index", - { - type: "doc", - id: "getting-started/quickstart-prismaPostgres", - label: "Quickstart", - }, - { - type: "doc", - id: "getting-started/quickstart-sqlite", - label: "Quickstart", - className: "hidden-sidebar", - }, + // { + // type: "doc", + // id: "getting-started/quickstart-prismaPostgres", + // label: "Quickstart", + // customProps: { + // badge: "5 Min", + // }, + // }, + // { + // type: "doc", + // id: "getting-started/quickstart-sqlite", + // label: "Quickstart", + // className: "hidden-sidebar", + // }, { type: "category", label: "Prisma ORM", collapsed: false, collapsible: false, - link: { - type: "doc", - id: "getting-started/setup-prisma/index", - }, items: [ { type: "category", - label: "Start from scratch", + label: "Quickstart", + collapsed: true, + collapsible: true, + className: "hide-category-badge", link: { type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/index", + id: "getting-started/prisma-orm/quickstart/prisma-postgres", + }, + customProps: { + hideBadge: true, }, items: [ { - type: "category", - label: "Relational databases", + type: "doc", + id: "getting-started/prisma-orm/quickstart/prisma-postgres", + label: "Prisma Postgres", customProps: { - badge: "15 Min", + badge: "5 Min", }, - link: { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-prismaPostgres", + }, + { + type: "doc", + id: "getting-started/prisma-orm/quickstart/mysql", + label: "MySQL", + customProps: { + badge: "5 Min", }, - items: [ - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-prismaPostgres", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-mysql", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-planetscale", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-sqlserver", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-cockroachdb", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgresql", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-node-mysql", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-node-planetscale", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-node-sqlserver", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/relational-databases-node-cockroachdb", - className: "hidden-sidebar", - }, - { - type: "autogenerated", - dirName: - "100-getting-started/02-setup-prisma/100-start-from-scratch/110-relational-databases", - }, - ], }, { - type: "category", - label: "MongoDB", + type: "doc", + id: "getting-started/prisma-orm/quickstart/postgresql", + label: "PostgreSQL", + customProps: { + badge: "5 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-orm/quickstart/sqlite", + label: "SQLite", + customProps: { + badge: "5 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-orm/quickstart/sql-server", + label: "SQL Server", + customProps: { + badge: "5 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-orm/quickstart/planetscale", + label: "PlanetScale", + customProps: { + badge: "5 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-orm/quickstart/cockroachdb", + label: "CockroachDB", customProps: { - badge: "15 Min", + badge: "5 Min", }, - link: { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb", + }, + { + type: "doc", + id: "getting-started/prisma-orm/quickstart/mongodb", + label: "MongoDB", + customProps: { + badge: "5 Min", }, - items: [ - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/mongodb-node-mongodb", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb", - className: "hidden-sidebar", - }, - { - type: "autogenerated", - dirName: - "100-getting-started/02-setup-prisma/100-start-from-scratch/120-mongodb", - }, - ], }, ], }, { type: "category", label: "Add to existing project", + collapsed: true, + collapsible: true, + className: "hide-category-badge", link: { type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/index", + id: "getting-started/prisma-orm/add-to-existing-project/prisma-postgres", + }, + customProps: { + hideBadge: true, }, items: [ { - type: "category", - label: "Relational databases", + type: "doc", + id: "getting-started/prisma-orm/add-to-existing-project/prisma-postgres", + label: "Prisma Postgres", customProps: { - badge: "15 Min", + badge: "5 Min", }, - link: { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql", + }, + { + type: "doc", + id: "getting-started/prisma-orm/add-to-existing-project/mysql", + label: "MySQL", + customProps: { + badge: "5 Min", }, - items: [ - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-mysql", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-sqlserver", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-cockroachdb", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-node-postgresql", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-node-mysql", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-node-planetscale", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-node-sqlserver", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/relational-databases-node-cockroachdb", - className: "hidden-sidebar", - }, - { - type: "autogenerated", - dirName: - "100-getting-started/02-setup-prisma/200-add-to-existing-project/110-relational-databases", - }, - ], }, { - type: "category", - label: "MongoDB", + type: "doc", + id: "getting-started/prisma-orm/add-to-existing-project/postgresql", + label: "PostgreSQL", customProps: { - badge: "15 Min", + badge: "5 Min", }, - link: { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/mongodb-typescript-mongodb", + }, + { + type: "doc", + id: "getting-started/prisma-orm/add-to-existing-project/sqlite", + label: "SQLite", + customProps: { + badge: "5 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-orm/add-to-existing-project/sql-server", + label: "SQL Server", + customProps: { + badge: "5 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-orm/add-to-existing-project/planetscale", + label: "PlanetScale", + customProps: { + badge: "5 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-orm/add-to-existing-project/cockroachdb", + label: "CockroachDB", + customProps: { + badge: "5 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-orm/add-to-existing-project/mongodb", + label: "MongoDB", + customProps: { + badge: "5 Min", }, - items: [ - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/mongodb-node-mongodb", - className: "hidden-sidebar", - }, - { - type: "doc", - id: "getting-started/setup-prisma/add-to-existing-project/mongodb-typescript-mongodb", - className: "hidden-sidebar", - }, - { - type: "autogenerated", - dirName: - "100-getting-started/02-setup-prisma/200-add-to-existing-project/120-mongodb", - }, - ], }, ], }, @@ -294,29 +236,83 @@ const sidebars: SidebarsConfig = { id: "getting-started/prisma-postgres/index", }, items: [ - "getting-started/prisma-postgres/from-the-cli", - "getting-started/prisma-postgres/upgrade-from-early-access", { type: "category", - collapsible: false, + label: "Quickstart", + collapsed: true, + collapsible: true, + className: "hide-category-badge", + link: { + type: "doc", + id: "getting-started/prisma-postgres/quickstart/prisma-orm", + }, + customProps: { + hideBadge: true, + }, + items: [ + { + type: "doc", + id: "getting-started/prisma-postgres/quickstart/prisma-orm", + label: "Prisma ORM", + customProps: { + badge: "5 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-postgres/quickstart/kysely", + label: "Kysely", + customProps: { + badge: "10 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-postgres/quickstart/drizzle-orm", + label: "Drizzle ORM", + customProps: { + badge: "10 Min", + }, + }, + { + type: "doc", + id: "getting-started/prisma-postgres/quickstart/typeorm", + label: "TypeORM", + customProps: { + badge: "10 Min", + }, + }, + ], + }, + { + type: "category", + collapsed: true, + collapsible: true, + className: "hide-category-badge", label: "Import from existing database", link: { type: "doc", id: "getting-started/prisma-postgres/import-from-existing-database-postgresql", }, + customProps: { + hideBadge: true, + }, items: [ { type: "doc", id: "getting-started/prisma-postgres/import-from-existing-database-postgresql", - className: "hidden-sidebar", + label: "PostgreSQL", + className: "sidebar-item-normal-weight", }, { type: "doc", id: "getting-started/prisma-postgres/import-from-existing-database-mysql", - className: "hidden-sidebar", + label: "MySQL", + className: "sidebar-item-normal-weight", }, ], }, + "getting-started/prisma-postgres/from-the-cli", ], }, ], @@ -447,6 +443,7 @@ const sidebars: SidebarsConfig = { "guides/clerk-nextjs", "guides/shopify", "guides/permit-io-access-control", + "guides/betterauth-astro", "guides/betterauth-nextjs", "guides/ai-sdk-nextjs", "guides/authjs-nextjs", @@ -619,5 +616,3 @@ const sidebars: SidebarsConfig = { }; export default sidebars; - - diff --git a/src/components/GettingStarted/index.tsx b/src/components/GettingStarted/index.tsx index 92a0986c82..cfcab301c7 100644 --- a/src/components/GettingStarted/index.tsx +++ b/src/components/GettingStarted/index.tsx @@ -67,6 +67,36 @@ export const SignalStream = ({ color, height, width }: any) => ( ); +export const Plus = ({ color, height, width }: any) => ( + + + +); + +export const Plug = ({ color, height, width }: any) => ( + + + +); + export const PrismaPostgres = ({ color, height, width }: any) => ( { ); }; +export const QuickstartLinkCard = ({ icon, title, desc, link, highlight, children }: any) => { + const linkCardRef = useRef(null); + return ( + +
+ {icon && } +

{title}

+
+ {children ??

{desc}

} + + ); +}; + export const Tab = ({ children, ...props }) => (
{children} diff --git a/src/css/custom.css b/src/css/custom.css index 1aefb1bba6..5ff447caf1 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -1807,4 +1807,24 @@ pre > code { kbd.DocSearch-Commands-Key { padding: 0; +} + +/* Fix sidebar item styling for Import from existing database items */ +.sidebar-item-normal-weight a, +.sidebar-item-normal-weight .menu__link { + font-weight: normal !important; +} + +.sidebar-item-normal-weight a.menu__link--active, +.sidebar-item-normal-weight .menu__link.menu__link--active { + font-weight: 600 !important; +} + +/* More specific selector for nested category items */ +.theme-doc-sidebar-item-category .menu__list .sidebar-item-normal-weight a { + font-weight: normal !important; +} + +.theme-doc-sidebar-item-category .menu__list .sidebar-item-normal-weight a.menu__link--active { + font-weight: 600 !important; } \ No newline at end of file diff --git a/src/css/gettingStarted.module.scss b/src/css/gettingStarted.module.scss index 14fdb997a2..9d78a93d81 100644 --- a/src/css/gettingStarted.module.scss +++ b/src/css/gettingStarted.module.scss @@ -16,8 +16,14 @@ } .borderBox { padding: 24px 24px 32px 24px; + margin-top: 16px; + display: flex; + flex-direction: column; + justify-content: space-between; border-radius: 8px; - background: var(--main-bgd-color); + border: 1px solid var(--border-color); + background: var(--surface-brand-grey-strong); + width: fit-content; a { text-decoration: underline; } @@ -26,7 +32,8 @@ text-align: left; letter-spacing: 0em; line-height: 20px; - font-size: 14px; + font-size: 16px; + margin: 0; :first-child { margin-top: 0; } @@ -34,6 +41,23 @@ margin-bottom: 0; } } + > p { + margin-bottom: 16px; + &:last-child { + margin-bottom: 0; + } + } + pre[class*="language-"] { + background: #121521 !important; + border: 0.7px solid #2d3748; + code span { + font-size: 16px; + color: #e2e8f0 !important; + &::before { + color: #4a5568; + } + } + } } .boxTitle { @@ -45,31 +69,6 @@ letter-spacing: -0.8px; } -.grid { - gap: 16px; - display: grid; - margin-top: 24px; - grid-template-columns: none; - @media (min-width: 600px) { - grid-template-columns: 1fr 1fr; - } - a { - border-color: var(--ifm-btn-border-color); - background: transparent; - color: var(--main-font-color); - &:hover { - border-color: var(--ifm-btn-border-color-active); - background: transparent; - } - } -} - -.separator { - height: 100%; - width: 1px; - border-left: 1px solid var(--ifm-btn-border-color); -} - .linkCardWrapper { border: 1px solid var(--border-color); padding: 20px 24px; @@ -86,15 +85,16 @@ color: inherit; } &.linkCardHighlight { - background: rgba(22, 163, 148, 0.12); - border-color: rgb(22, 163, 148); - &:hover { - // background: #B7F4EE; - border-color: #154f47; - } + border-radius: 8px; + border: 1px solid var(--surface-brand-default); + background: var(--surface-brand-light); } .title { display: inline-flex; + h2 { + font-family: Barlow; + border-bottom: 1px solid var(--main-font-color); + } h6 { font-size: 18px; display: inline-block; @@ -117,22 +117,6 @@ } } -.tab { - padding: 15px; - background-color: var(--main-bgd-color); - border: 1px solid var(--indigo-600); - border-radius: 0px 8px 8px 8px; - font-family: Inter; - font-size: 14px; - font-weight: 400; - line-height: 20px; - letter-spacing: 0em; - text-align: left; - p { - margin-top: 0; - } -} - .squareWrapper { width: 90px; height: 90px; @@ -165,10 +149,14 @@ .list { display: grid; - gap: 16px; margin-top: 16px; - max-width: fit-content; + width: fit-content; grid-template-columns: repeat(2, auto); + gap: 16px; + width: fit-content; + display: flex; + justify-content: flex-start; + &:not(.framedList) { @media (min-width: 1400px) { grid-template-columns: repeat(7, auto); diff --git a/src/data/indexData.ts b/src/data/indexData.ts index 29bc26ad8d..4be0a02a19 100644 --- a/src/data/indexData.ts +++ b/src/data/indexData.ts @@ -125,9 +125,9 @@ export const get_help = [ export const tabs = [ { icon: "fa-solid fa-chart-pyramid", - label: "Use Prisma Postgres", + label: "Use Prisma's managed Postgres", description: - "Get started with your favorite framework and Prisma Postgres. With Prisma Postgres you get an instant, fully hosted high-performance database that includes built-in caching, scales to zero, and integrates deeply with Prisma ORM and Prisma Studio—all backed by a generous free tier.", + "Get started with your favorite framework and Prisma Postgres. With Prisma Postgres you get an instant, fully hosted high-performance database that scales to zero and integrates deeply with Prisma ORM and Prisma Studio—all backed by a generous free tier.", list: [ { url: "/guides/nextjs", @@ -168,35 +168,35 @@ export const tabs = [ "Already have a database? With Prisma ORM and Prisma Data Platform, you can supercharge your existing stack. Add connection pooling and caching with generous free tiers.", list: [ { - url: "/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql", + url: "/getting-started/prisma-orm/add-to-existing-project/postgresql", image: "/img/technologies/postgresqlsimple.svg", tech: "PostgreSQL", }, { - url: "/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale", + url: "/getting-started/prisma-orm/add-to-existing-project/planetscale", image: "/img/technologies/planetscale.svg", imageDark: "/img/technologies/planetscaledark.svg", tech: "Planetscale", }, { - url: "/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-sqlserver", + url: "/getting-started/prisma-orm/add-to-existing-project/sql-server", image: "/img/technologies/sqlserver.svg", tech: "SQL Server", }, { - url: "/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-mysql", + url: "/getting-started/prisma-orm/add-to-existing-project/mysql", image: "/img/technologies/mysqlsimple.svg", tech: "MySQL", }, { - url: "/getting-started/setup-prisma/add-to-existing-project/mongodb-typescript-mongodb", + url: "/getting-started/prisma-orm/add-to-existing-project/mongodb", image: "/img/technologies/mongodbsimple.svg", imageDark: "/img/technologies/mongodbsimple.svg", tech: "MongoDB", }, ], link: { - url: "/getting-started/setup-prisma/add-to-existing-project", + url: "/getting-started/prisma-orm/add-to-existing-project/postgresql", label: "How to migrate to Prisma ORM", icon: "fa-regular fa-book-open", }, diff --git a/src/pages/index.tsx b/src/pages/index.tsx index e242c4ec34..55f2b82ea3 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -54,7 +54,7 @@ function HomepageHowDoISection() { const hiddenCards = how_do_i.slice(3); const location = useLocation(); - + return (
@@ -72,7 +72,7 @@ function HomepageHowDoISection() { {e.tags.map((tag: any) => )}
} {e.time &&
- + {e.time} min. read
}
} @@ -89,7 +89,7 @@ function HomepageHowDoISection() { {e.tags.map((tag: any) => )} } {e.time &&
- + {e.time} min. read
} } @@ -100,7 +100,7 @@ function HomepageHowDoISection() { className={clsx(styles.seeMore, seeMore && styles.clicked)} onClick={() => { setSeeMore(!seeMore) - howRef.current.scrollIntoView({behavior: "smooth", offset: 80}); + howRef.current.scrollIntoView({ behavior: "smooth", offset: 80 }); }} > See {seeMore ? `less` : `more`} @@ -110,7 +110,7 @@ function HomepageHowDoISection() { ); } -const CommunityIcon = ({icon, link, label}: any) => { +const CommunityIcon = ({ icon, link, label }: any) => { const [visibleTooltip, setVisibleTooltip] = useState(false); const iconRef = useRef(null); @@ -161,41 +161,41 @@ function HomepageCommunitySection() { ); } -const TabBox = ({icon, label, description, list, link}: any) => { +const TabBox = ({ icon, label, description, list, link }: any) => { const location = useLocation(); return (
- {icon && } + {icon && } {label}
-

+

- {list && list.length && list.map((l: any, idx: number) => + {list && list.length && list.map((l: any, idx: number) => )}
- + {link.label} - +
) } function HomepageHeroSection() { - const { colorMode } = useColorMode(); + const { colorMode } = useColorMode(); return (
@@ -216,7 +216,7 @@ function HomepageHeroSection() { label="Start with an AI prompt →" color="teal" /> */}
- {tabs && tabs.map((tab: any, idx: number) => + {tabs && tabs.map((tab: any, idx: number) => )}
@@ -241,9 +241,9 @@ function HomepageGetHelpSection() {

{e.title}

-

+

- {e.links.map((link: any) => + {e.links.map((link: any) => {link.label} @@ -272,7 +272,7 @@ export default function Home(): JSX.Element { - + diff --git a/static/_redirects b/static/_redirects index e2c2eb925f..c90e320673 100644 --- a/static/_redirects +++ b/static/_redirects @@ -47,18 +47,18 @@ /reference/tools-and-interfaces/prisma-schema/models /docs/reference/tools-and-interfaces/prisma-schema/data-model # sql -> relational-databases -/getting-started/setup-prisma/start-from-scratch-sql-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch-sql-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgresql -/getting-started/setup-prisma/start-from-scratch-sql-typescript-mysql /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-mysql -/getting-started/setup-prisma/start-from-scratch-sql-node-mysql /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-mysql -/getting-started/setup-prisma/start-from-scratch-prisma-migrate-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch-prisma-migrate-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgresql -/getting-started/setup-prisma/start-from-scratch-prisma-migrate-typescript-mysql /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-mysql -/getting-started/setup-prisma/start-from-scratch-prisma-migrate-node-mysql /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-mysql -/getting-started/setup-prisma/start-from-scratch-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgresql -/getting-started/setup-prisma/start-from-scratch-typescript-mysql /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-mysql -/getting-started/setup-prisma/start-from-scratch-node-mysql /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-mysql +/getting-started/setup-prisma/start-from-scratch-sql-typescript-postgres /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch-sql-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases-node-postgresql +/getting-started/setup-prisma/start-from-scratch-sql-typescript-mysql /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch-sql-node-mysql /docs/getting-started/prisma-orm/start-from-scratch/relational-databases-node-mysql +/getting-started/setup-prisma/start-from-scratch-prisma-migrate-typescript-postgres /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch-prisma-migrate-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases-node-postgresql +/getting-started/setup-prisma/start-from-scratch-prisma-migrate-typescript-mysql /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch-prisma-migrate-node-mysql /docs/getting-started/prisma-orm/start-from-scratch/relational-databases-node-mysql +/getting-started/setup-prisma/start-from-scratch-typescript-postgres /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases-node-postgresql +/getting-started/setup-prisma/start-from-scratch-typescript-mysql /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch-node-mysql /docs/getting-started/prisma-orm/start-from-scratch/relational-databases-node-mysql /reference/tools-and-interfaces/prisma-schema/prisma-schema-file /docs/reference/tools-and-interfaces/prisma-schema /reference/tools-and-interfaces/prisma-client/api /docs/reference/tools-and-interfaces/prisma-client @@ -72,8 +72,8 @@ /more/supported-databases /docs/orm/reference/supported-databases /understand-prisma/introduction /docs/concepts/overview/what-is-prisma /understand-prisma/data-modeling /docs/concepts/overview/what-is-prisma/data-modeling -/getting-started/setup-prisma/start-from-scratch-prisma-migrate /docs/getting-started/setup-prisma/start-from-scratch-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch-sql /docs/getting-started/setup-prisma +/getting-started/setup-prisma/start-from-scratch-prisma-migrate /docs/getting-started/prisma-orm/start-from-scratch-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch-sql /docs/getting-started/prisma-orm /guides/prisma-guides/prisma-migrate-guides /docs/guides/prisma-guides/add-prisma-migrate-to-a-project /guides/prisma-guides/prisma-migrate-guides/add-prisma-migrate-to-a-project /docs/guides/prisma-guides/add-prisma-migrate-to-a-project /concepts/components/prisma-client/distinct /docs/concepts/components/prisma-client/aggregation-grouping-summarizing#select-distinct @@ -119,67 +119,246 @@ /concepts/more/codemod /docs/orm/more/upgrade-guides # postgres -> postgresql -/getting-started/setup-prisma/start-from-scratch-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/connect-your-database-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/using-prisma-migrate-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/install-prisma-client-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/querying-the-database-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/next-steps-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/connect-your-database-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-postgresql -/getting-started/setup-prisma/start-from-scratch/using-prisma-migrate-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-postgresql -/getting-started/setup-prisma/start-from-scratch/install-prisma-client-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-postgresql -/getting-started/setup-prisma/start-from-scratch/querying-the-database-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-postgresql -/getting-started/setup-prisma/start-from-scratch/next-steps-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-node-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-node-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql -/getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgres /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgresql -/getting-started/setup-prisma/add-to-existing-project-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/connect-your-database-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/introspection-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/install-prisma-client-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/querying-the-database-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/next-steps-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/connect-your-database-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/introspection-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/install-prisma-client-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/querying-the-database-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/next-steps-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-node-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql -/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-postgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-postgresql +/getting-started/setup-prisma/start-from-scratch-typescript-postgres /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/connect-your-database-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/connect-your-database-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/using-prisma-migrate-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/install-prisma-client-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/querying-the-database-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/querying-the-database-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/next-steps-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/next-steps-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/connect-your-database-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/connect-your-database-node-postgresql +/getting-started/setup-prisma/start-from-scratch/using-prisma-migrate-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/using-prisma-migrate-node-postgresql +/getting-started/setup-prisma/start-from-scratch/install-prisma-client-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/install-prisma-client-node-postgresql +/getting-started/setup-prisma/start-from-scratch/querying-the-database-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/querying-the-database-node-postgresql +/getting-started/setup-prisma/start-from-scratch/next-steps-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/next-steps-node-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/connect-your-database-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/connect-your-database-node-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/using-prisma-migrate-node-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/install-prisma-client-node-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/querying-the-database-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/querying-the-database-node-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-typescript-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/next-steps-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/next-steps-node-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgres /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgres /docs/getting-started/prisma-orm/start-from-scratch/relational-databases-node-postgresql +/getting-started/setup-prisma/add-to-existing-project-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/connect-your-database-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/connect-your-database-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/introspection-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/introspection-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/install-prisma-client-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/install-prisma-client-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/querying-the-database-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/querying-the-database-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/next-steps-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/next-steps-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/connect-your-database-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/connect-your-database-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/introspection-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/introspection-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/install-prisma-client-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/install-prisma-client-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/querying-the-database-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/querying-the-database-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/next-steps-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/next-steps-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/connect-your-database-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/connect-your-database-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/introspection-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/introspection-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/baseline-your-database-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/baseline-your-database-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/install-prisma-client-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/install-prisma-client-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/querying-the-database-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/querying-the-database-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/evolve-your-schema-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/evolve-your-schema-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/next-steps-typescript-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/next-steps-node-postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-postgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases-node-postgresql + + +/getting-started/quickstart-prismaPostgres* /docs/getting-started/prisma-orm/quickstart/prisma-postgres +/getting-started/quickstart-sqlite* /docs/getting-started/prisma-orm/quickstart/sqlite + + +/getting-started/setup-prisma/start-from-scratch/relational-databases-node-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases-node-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases-node-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases-node-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server +/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-prismaPostgres* /docs/getting-started/prisma-orm/quickstart/prisma-postgres +/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server + + +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-prismaPostgres* /docs/getting-started/prisma-orm/quickstart/prisma-postgres +/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server + + +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-prismaPostgres* /docs/getting-started/prisma-orm/quickstart/prisma-postgres +/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server + + +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-prismaPostgres* /docs/getting-started/prisma-orm/quickstart/prisma-postgres +/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server + + +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-cockroachdb* /docs/getting-started/prisma-orm/quickstart/cockroachdb +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-mysql* /docs/getting-started/prisma-orm/quickstart/mysql +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-planetscale* /docs/getting-started/prisma-orm/quickstart/planetscale +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-postgresql* /docs/getting-started/prisma-orm/quickstart/postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-prismaPostgres* /docs/getting-started/prisma-orm/quickstart/prisma-postgres +/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-sqlserver* /docs/getting-started/prisma-orm/quickstart/sql-server + + +/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps* /docs/getting-started/prisma-orm/quickstart/prisma-postgres +/getting-started/setup-prisma/start-from-scratch/mongodb-node-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database-node-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database-typescript-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema-node-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema-typescript-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client-node-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client-typescript-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb/querying-the-database-node-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb/querying-the-database-typescript-mongodb* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch/mongodb/next-steps* /docs/getting-started/prisma-orm/quickstart/mongodb +/getting-started/setup-prisma/start-from-scratch* /docs/getting-started/prisma-orm/quickstart/prisma-postgres + +# Add to existing project - main pages +/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server +/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server + + +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server + + +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server + + +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server + +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server + + +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-planetscale* /docs/getting-started/prisma-orm/add-to-existing-project/planetscale +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server + + +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-cockroachdb* /docs/getting-started/prisma-orm/add-to-existing-project/cockroachdb +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-mysql* /docs/getting-started/prisma-orm/add-to-existing-project/mysql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-postgresql* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql +/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-sqlserver* /docs/getting-started/prisma-orm/add-to-existing-project/sql-server + +/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps* /docs/getting-started/prisma-orm/add-to-existing-project/prisma-postgres +/getting-started/setup-prisma/add-to-existing-project/mongodb-node-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb-typescript-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database-node-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database-typescript-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb/introspection-node-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb/introspection-typescript-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client-node-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client-typescript-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb/querying-the-database-node-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb/querying-the-database-typescript-mongodb* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project/mongodb/next-steps* /docs/getting-started/prisma-orm/add-to-existing-project/mongodb +/getting-started/setup-prisma/add-to-existing-project* /docs/getting-started/prisma-orm/add-to-existing-project/prisma-postgres + +# Setup prisma parent and middleware +/getting-started/setup-prisma* /docs/getting-started/prisma-orm +/orm/prisma-client/client-extensions/middleware/soft-delete-middleware* /docs/orm/prisma-client/client-extensions/middleware +/orm/prisma-client/client-extensions/middleware/logging-middleware* /docs/orm/prisma-client/client-extensions/middleware +/orm/prisma-client/client-extensions/middleware/session-data-middleware* /docs/orm/prisma-client/client-extensions/middleware /concepts/more/environment-variables /docs/guides/development-environment/environment-variables /concepts/more/environment-variables/managing-env-files-and-setting-variables /docs/guides/development-environment/environment-variables /concepts/more/environment-variables/using-multiple-env-files /docs/guides/development-environment/environment-variables /concepts/more/editor-setup /docs/guides/development-environment/editor-setup /about/about-the-docs /docs/about -/about/style-guide /docs/about/style-guide -/about/style-guide/mdx-examples /docs/about/style-guide/mdx-examples -/about/style-guide/frontmatter /docs/about/style-guide/frontmatter -/about/style-guide/template /docs/about/style-guide/template -/concepts/components/preview-features/sql-server/sql-server-start-from-scratch-typescript /docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-sqlserver +/concepts/components/preview-features/sql-server/sql-server-start-from-scratch-typescript /docs/getting-started/prisma-orm/quickstart/sql-server /concepts/database-connectors/microsoft-sql-server /docs/concepts/database-connectors/sql-server /concepts/components/preview-features/sql-server/sql-server-connection-string /docs/concepts/database-connectors/sql-server /concepts/components/preview-features/sql-server/sql-server-local /docs/concepts/database-connectors/sql-server/sql-server-local @@ -497,7 +676,7 @@ /orm/more/migrating-to-prisma/migrate-from-sequelize /docs/guides/migrate-from-sequelize /orm/more/migrating-to-prisma/migrate-from-mongoose /docs/guides/migrate-from-mongoose /orm/more/migrating-to-prisma/migrate-from-drizzle /docs/guides/migrate-from-drizzle -/getting-started/quickstart /docs/getting-started/quickstart-prismaPostgres +/getting-started/quickstart /docs/getting-started/prisma-orm/quickstart/prisma-postgres /guides/realtime-apps /docs/postgres # move help articles up a level @@ -565,6 +744,8 @@ /postgres/database/error-reference /docs/postgres/database/api-reference/error-reference /postgres/integrations/vscode-extension /postgres/integrations/vscode +/postgres/introduction/getting-started /docs/postgres/getting-started + ### Dynamic redirects ### /faq/* https://v1.prisma.io/docs/1.34/faq/:splat /understand-prisma/* https://v1.prisma.io/docs/1.34/understand-prisma/:splat @@ -604,15 +785,14 @@ /concepts/overview/api-comparisons/* /docs/orm/more/comparisons:splat /concepts/overview/why-prisma/api-comparisons/* /docs/orm/more/comparisons:splat /guides/migrate-to-prisma* /docs/orm/more/migrating-to-prisma:splat -/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-* /docs/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps -/getting-started/setup-prisma/start-from-scratch/mongodb/next-steps-* /docs/getting-started/setup-prisma/start-from-scratch/mongodb/next-steps -/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-* /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps -/getting-started/setup-prisma/add-to-existing-project/mongodb/next-steps-* /docs/getting-started/setup-prisma/add-to-existing-project/mongodb/next-steps -/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-prismaPostgres /docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql +/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps-* /docs/getting-started/prisma-orm/start-from-scratch/relational-databases/next-steps +/getting-started/setup-prisma/start-from-scratch/mongodb/next-steps-* /docs/getting-started/prisma-orm/start-from-scratch/mongodb/next-steps +/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps-* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/relational-databases/next-steps +/getting-started/setup-prisma/add-to-existing-project/mongodb/next-steps-* /docs/getting-started/prisma-orm/add-to-existing-project/postgresql/mongodb/next-steps +/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-prismaPostgres /docs/getting-started/prisma-orm/add-to-existing-project/postgresql /pulse* /docs/postgres -/postgres/getting-started* /docs/postgres/introduction/getting-started /postgres/overview* /docs/postgres/introduction/overview /postgres/caching* /docs/postgres/database/caching @@ -636,5 +816,10 @@ /postgres/database/tooling /docs/postgres/integrations/viewing-data /postgres/integrations/tooling /docs/postgres/integrations/viewing-data +/orm/getting-started/quickstart* /docs/getting-started/prisma-orm/quickstart/prisma-postgres +/orm/getting-started/add-to-existing-project* /docs/getting-started/prisma-orm/add-to-existing-project/prisma-postgres + +/getting-started/prisma-postgres/upgrade-from-early-access* /docs/postgres/getting-started + ### NO REDIRECTS BELOW THIS LINE. ADD REDIRECTS ABOVE THIS SECTION ### diff --git a/static/img/guides/prisma-betterauth-astro-cover.png b/static/img/guides/prisma-betterauth-astro-cover.png new file mode 100644 index 0000000000000000000000000000000000000000..5ac087942410c825d419d73d8bf49089401cee79 GIT binary patch literal 42323 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 literal 0 HcmV?d00001 diff --git a/static/img/technologies/astro.svg b/static/img/technologies/astro.svg new file mode 100644 index 0000000000..e52118199d --- /dev/null +++ b/static/img/technologies/astro.svg @@ -0,0 +1,4 @@ + + + + diff --git a/static/img/technologies/astrodark.svg b/static/img/technologies/astrodark.svg new file mode 100644 index 0000000000..52b76d5509 --- /dev/null +++ b/static/img/technologies/astrodark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/static/img/technologies/drizzle.svg b/static/img/technologies/drizzle.svg new file mode 100644 index 0000000000..fdacf2c789 --- /dev/null +++ b/static/img/technologies/drizzle.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/static/img/technologies/kysely.svg b/static/img/technologies/kysely.svg new file mode 100644 index 0000000000..5ca04a32b0 --- /dev/null +++ b/static/img/technologies/kysely.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/static/img/technologies/remix.svg b/static/img/technologies/remix.svg new file mode 100644 index 0000000000..25faf57061 --- /dev/null +++ b/static/img/technologies/remix.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/static/img/technologies/sequelize.svg b/static/img/technologies/sequelize.svg new file mode 100644 index 0000000000..728f77161e --- /dev/null +++ b/static/img/technologies/sequelize.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/img/technologies/typeorm.svg b/static/img/technologies/typeorm.svg new file mode 100644 index 0000000000..e91fbd55c8 --- /dev/null +++ b/static/img/technologies/typeorm.svg @@ -0,0 +1,4 @@ + + + + From 32e308291541b6a41b0ec6163ec8d5a27689caa6 Mon Sep 17 00:00:00 2001 From: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> Date: Mon, 17 Nov 2025 14:49:21 +0600 Subject: [PATCH 08/23] feat: update .env docs DC-6204 (#7259) --- .../140-debugging.mdx | 7 +- .../200-prisma-cli-reference.mdx | 72 ++++---- .../300-environment-variables-reference.mdx | 94 ++++++++--- .../100-under-the-hood/100-engines.mdx | 154 +++++++++++++----- 4 files changed, 227 insertions(+), 100 deletions(-) diff --git a/content/200-orm/200-prisma-client/700-debugging-and-troubleshooting/140-debugging.mdx b/content/200-orm/200-prisma-client/700-debugging-and-troubleshooting/140-debugging.mdx index a219ebc384..bdb11684f5 100644 --- a/content/200-orm/200-prisma-client/700-debugging-and-troubleshooting/140-debugging.mdx +++ b/content/200-orm/200-prisma-client/700-debugging-and-troubleshooting/140-debugging.mdx @@ -4,7 +4,6 @@ metaTitle: 'Debugging (Reference)' metaDescription: 'This page explains how to enable debugging output for Prisma Client by setting the `DEBUG` environment variable.' --- - You can enable debugging output in Prisma Client and Prisma CLI via the [`DEBUG`](/orm/reference/environment-variables-reference#debug) environment variable. It accepts two namespaces to print debugging output: @@ -13,13 +12,11 @@ You can enable debugging output in Prisma Client and Prisma CLI via the [`DEBUG` - `prisma*`: Prints all debug messages from Prisma Client or CLI - `*`: Prints all debug messages - +:::info Prisma Client can be configured to log warnings, errors and information related to queries sent to the database. See [Configuring logging](/orm/prisma-client/observability-and-logging/logging) for more information. - - - +::: ## Setting the `DEBUG` environment variable diff --git a/content/200-orm/500-reference/200-prisma-cli-reference.mdx b/content/200-orm/500-reference/200-prisma-cli-reference.mdx index 8dd4fff307..31b6eb1914 100644 --- a/content/200-orm/500-reference/200-prisma-cli-reference.mdx +++ b/content/200-orm/500-reference/200-prisma-cli-reference.mdx @@ -377,13 +377,13 @@ generator client { | `--allow-no-models` | No | The `generate` command will generate Prisma Client without generating any models. | | `--watch` | No | The `generate` command will continue to watch the `schema.prisma` file and re-generate Prisma Client on file changes. | - +:::warning **Deprecation Warning** As of Prisma 5.2.0, `--data-proxy` and `--accelerate` are deprecated in favor of `--no-engine` as Prisma Client no longer requires an option to work with Prisma Accelerate. All options are available and work similarly, but we recommend `--no-engine` as it prevents an engine from being downloaded which will greatly impact the size of apps deployed to serverless and edge functions. - +::: #### Arguments @@ -675,32 +675,32 @@ For downloading engines - BINARY_DOWNLOAD_VERSION: For configuring the Query Engine Type - - PRISMA_CLI_QUERY_ENGINE_TYPE: - - PRISMA_CLIENT_ENGINE_TYPE: + - PRISMA_CLI_QUERY_ENGINE_TYPE: (Not supported in Prisma ORM v7) + - PRISMA_CLIENT_ENGINE_TYPE: (Not supported in Prisma ORM v7) For custom engines - - PRISMA_QUERY_ENGINE_BINARY: - - PRISMA_QUERY_ENGINE_LIBRARY: + - PRISMA_QUERY_ENGINE_BINARY: (Not supported in Prisma ORM v7) + - PRISMA_QUERY_ENGINE_LIBRARY: (Not supported in Prisma ORM v7) - PRISMA_SCHEMA_ENGINE_BINARY: - PRISMA_MIGRATION_ENGINE_BINARY: For the "postinstall" npm hook - - PRISMA_GENERATE_SKIP_AUTOINSTALL: - - PRISMA_SKIP_POSTINSTALL_GENERATE: - - PRISMA_GENERATE_IN_POSTINSTALL: + - PRISMA_GENERATE_SKIP_AUTOINSTALL: (Not supported in Prisma ORM v7) + - PRISMA_SKIP_POSTINSTALL_GENERATE: (Not supported in Prisma ORM v7) + - PRISMA_GENERATE_IN_POSTINSTALL: (Not supported in Prisma ORM v7) For "prisma generate" - - PRISMA_GENERATE_DATAPROXY: - - PRISMA_GENERATE_NO_ENGINE: + - PRISMA_GENERATE_DATAPROXY: (Not supported in Prisma ORM v7) + - PRISMA_GENERATE_NO_ENGINE: (Not supported in Prisma ORM v7) For Prisma Client - PRISMA_SHOW_ALL_TRACES: - - PRISMA_CLIENT_NO_RETRY (Binary engine only): + - PRISMA_CLIENT_NO_RETRY (Binary engine only): (Not supported in Prisma ORM v7) For Prisma Migrate - PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK: - - PRISMA_MIGRATE_SKIP_GENERATE: - - PRISMA_MIGRATE_SKIP_SEED: + - PRISMA_MIGRATE_SKIP_GENERATE: (Not supported in Prisma ORM v7) + - PRISMA_MIGRATE_SKIP_SEED: (Not supported in Prisma ORM v7) For Prisma Studio - BROWSER: @@ -815,17 +815,17 @@ npx prisma dev stop mydb* # stops all DBs starting with `mydb` The `db pull` command connects to your database and adds Prisma models to your Prisma schema that reflect the current database schema. - +:::warning **Warning**: The command will overwrite the current `schema.prisma` file with the new schema. Some manual changes or customization can be lost. Be sure to back up your current `schema.prisma` file (or commit your current state to version control to be able to revert any changes) before running `db pull` if it contains important modifications. - +::: - +:::info Introspection with the `db pull` command on the [MongoDB connector](/orm/overview/databases/mongodb) samples the data instead of reading a schema. - +::: #### Prerequisites @@ -1041,17 +1041,17 @@ prisma db seed ### `db execute` - +:::info The `db execute` command is Generally Available in versions 3.13.0 and later. If you're using a version between 3.9.0 and 3.13.0, it is available behind a `--preview-feature` CLI flag. - +::: - +:::warning This command is currently not supported on [MongoDB](/orm/overview/databases/mongodb). - +::: This command applies a SQL script to the database without interacting with the Prisma migrations table. The script takes two inputs: @@ -1117,12 +1117,12 @@ Other options: Prisma Migrate changed from Preview to Generally Available (GA) in 2.19.0. - +:::info **Does not apply for MongoDB**
Instead of `migrate dev` and related commands, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb). -
+::: ### `migrate dev` @@ -1136,11 +1136,11 @@ The `migrate dev` command: 1. Applies all unapplied migrations to the development database and updates the `_prisma_migrations` table 1. Triggers the generation of artifacts (for example, Prisma Client) - +:::warning This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. - +::: See also: @@ -1157,11 +1157,11 @@ See also: | `--name` / `-n` | No | Name the migration (e.g. `prisma migrate dev --name added_job_title`) | | | `--help` / `-h` | No | Displays the help message | | - +:::info If a [schema drift](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database#detecting-schema-drift) is detected while running `prisma migrate dev` using `--create-only`, you will be prompted to reset your database. - +::: #### Arguments @@ -1195,11 +1195,11 @@ This command: 1. Applies all migrations 1. Runs seed scripts - +:::warning This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. - +::: #### Options @@ -1260,11 +1260,11 @@ The `migrate deploy` command applies all pending migrations, and creates the dat - Does **not** reset the database or generate artifacts - Does **not** rely on a shadow database - +:::warning This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. - +::: #### Options @@ -1290,11 +1290,11 @@ The `migrate resolve` command allows you to solve migration history issues in pr Note that this command can only be used with a failed migration. If you try to use it with a successful migration you will receive an error. - +:::warning This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. - +::: #### Options @@ -1326,11 +1326,11 @@ prisma migrate resolve --rolled-back 20201231000000_add_users_table The `prisma migrate status` command looks up the migrations in `./prisma/migrations/*` folder and the entries in the `_prisma_migrations` table and compiles information about the state of the migrations in your database. - +:::warning This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. - +::: For example: diff --git a/content/200-orm/500-reference/300-environment-variables-reference.mdx b/content/200-orm/500-reference/300-environment-variables-reference.mdx index 407c6bf4fe..9bc8dcc2a2 100644 --- a/content/200-orm/500-reference/300-environment-variables-reference.mdx +++ b/content/200-orm/500-reference/300-environment-variables-reference.mdx @@ -6,12 +6,8 @@ sidebar_label: 'Environment variables' tocDepth: 3 --- - - This document describes different environment variables and their use cases. - - ## Prisma Client ### `DEBUG` @@ -63,10 +59,22 @@ See [Studio](/orm/reference/prisma-cli-reference#studio) documentation for more ### `PRISMA_GENERATE_SKIP_AUTOINSTALL` +:::danger Prisma v7 Deprecation + +This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. + +::: + `PRISMA_GENERATE_SKIP_AUTOINSTALL` can be set to a truthy value to skip the auto-install of `prisma` CLI and `@prisma/client` dependencies (if they are missing), if the `prisma-client-js` generator is defined in the Prisma Schema, when using the `prisma generate` command. ### `PRISMA_SKIP_POSTINSTALL_GENERATE` +:::danger Prisma v7 deprecation + +This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. + +::: + `PRISMA_SKIP_POSTINSTALL_GENERATE` can be set to a truthy value to skip the auto-generation of Prisma Client when its `postinstall` hook is triggered by a package manager. The `postinstall` hook of the `@prisma/client` package is triggered when the package is installed, or its version is updated. ### `PRISMA_DISABLE_WARNINGS` @@ -75,21 +83,29 @@ Disables all CLI warnings generated by `logger.warn`. ### `PRISMA_GENERATE_NO_ENGINE` - + + +:::danger Prisma v7 deprecation + +This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. + +::: + +:::info This environment variable is available since version `5.2.0` - +::: `PRISMA_GENERATE_NO_ENGINE` can be set to a truthy value to generate a Prisma Client without an included [query engine](/orm/more/under-the-hood/engines) in order to reduce deployed application size when paired with [Prisma Accelerate](/accelerate). ### `PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK` - +:::info This environment variable is available since version `5.3.0` - +::: `PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK` can be set to a truthy value to disable the [advisory locking](/orm/prisma-migrate/workflows/development-and-production#advisory-locking) used by Prisma Migrate. This might be needed, depending on the database configuration, for example, for a Percona-XtraDB-Cluster or MariaDB Galera Cluster. @@ -127,6 +143,12 @@ HTTPS_PROXY=https://proxy.example.com #### `PRISMA_CLI_QUERY_ENGINE_TYPE` +:::danger[Removed in Prisma v7] + +This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. + +::: + `PRISMA_CLI_QUERY_ENGINE_TYPE` is used to [define the query engine type Prisma CLI downloads and uses](/orm/more/under-the-hood/engines#configuring-the-query-engine). Defaults to `library`, but can be set to `binary`: ```env @@ -135,6 +157,12 @@ PRISMA_CLI_QUERY_ENGINE_TYPE=binary #### `PRISMA_CLIENT_ENGINE_TYPE` +:::danger[Removed in Prisma v7] + +This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. + +::: + `PRISMA_CLIENT_ENGINE_TYPE` is used to [define the query engine type Prisma Client downloads and uses](/orm/more/under-the-hood/engines#configuring-the-query-engine). Defaults to `library`, but can be set to `binary`: ```env @@ -161,11 +189,11 @@ Note: This environment variable used to be available as `PRISMA_BINARIES_MIRROR` #### `PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING` - +:::info This environment variable is available since version `4.16.0` - +::: `PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING` can be can be set to a truthy value to ignore problems around downloading & verifying the integrity (via a checksum file) of the Prisma ORM engines. This is particularly useful when deploying to an offline system environment where the checksum file cannot be downloaded. @@ -182,6 +210,12 @@ By default, all engine files are downloaded when you install Prisma CLI, copied #### `PRISMA_QUERY_ENGINE_BINARY` +:::danger Prisma v7 Deprecation + +This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. + +::: + `PRISMA_QUERY_ENGINE_BINARY` is used to set a custom location for your own query engine binary. ```env @@ -196,6 +230,12 @@ Note: This can only have an effect if the engine type of CLI or Client are set t #### `PRISMA_QUERY_ENGINE_LIBRARY` +:::danger Prisma v7 Deprecation + +This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. + +::: + `PRISMA_QUERY_ENGINE_LIBRARY` is used to set a custom location for your own query engine library. ```env @@ -218,11 +258,11 @@ PRISMA_SCHEMA_ENGINE_BINARY=custom/my-schema-engine-unix #### `PRISMA_MIGRATION_ENGINE_BINARY` - +:::warning **Deprecated**: `PRISMA_MIGRATION_ENGINE_BINARY` variable is deprecated in [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0) because Migration engine was renamed to Schema Engine. - +::: `PRISMA_MIGRATION_ENGINE_BINARY` is used to set a custom location for your own migration engine binary. @@ -232,25 +272,31 @@ PRISMA_MIGRATION_ENGINE_BINARY=custom/my-migration-engine-unix #### `PRISMA_INTROSPECTION_ENGINE_BINARY` +:::danger[Removed in Prisma v7] + +This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. + +::: + `PRISMA_INTROSPECTION_ENGINE_BINARY` is used to set a custom location for your own introspection engine binary. ```env PRISMA_INTROSPECTION_ENGINE_BINARY=custom/my-introspection-engine-unix ``` - +:::warning The Introspection Engine is served by the Migration Engine from [4.9.0](https://github.com/prisma/prisma/releases/tag/4.9.0). Therefore, the `PRISMA_INTROSPECTION_ENGINE` environment variable will not be used. - +::: #### `PRISMA_FMT_BINARY` - +:::danger This functionality has been removed in Prisma CLI version 4.10.0. It only works in earlier versions. - +::: `PRISMA_FMT_BINARY` is used to set a custom location for your own format engine binary. @@ -258,16 +304,22 @@ This functionality has been removed in Prisma CLI version 4.10.0. It only works PRISMA_FMT_BINARY=custom/my-custom-format-engine-unix ``` - +:::warning The `PRISMA_FMT_BINARY` variable is used in versions [4.2.0](https://github.com/prisma/prisma/releases/tag/4.2.0) or lower. - +::: ### CLI Binary Targets #### `PRISMA_CLI_BINARY_TARGETS` +:::danger Prisma v7 Deprecation + +This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. + +::: + `PRISMA_CLI_BINARY_TARGETS` can be used to specify one or more binary targets that Prisma CLI will download during installation (so it must be provided during `npm install` of Prisma CLI and does not affect runtime of Prisma CLI or Prisma Client). Use `PRISMA_CLI_BINARY_TARGETS` if you 1) deploy to a specific platform via an upload of a local project that includes dependencies, and 2) your local environment is different from the target (e.g. AWS Lambda with Node.js 20+ is `rhel-openssl-3.0.x`, and your local environment might be macOS arm64 `darwin-arm64`). Using the `PRISMA_CLI_BINARY_TARGETS` environment variable ensures that the target engine files are also downloaded. @@ -278,4 +330,8 @@ PRISMA_CLI_BINARY_TARGETS=darwin-arm64,rhel-openssl-3.0.x npm install This is the Prisma CLI equivalent for the [`binaryTargets` property of the `generator` block](/orm/prisma-schema/overview/generators#binary-targets), which enables you to define the same setting for Prisma Client. -> **Note**: For Node.js versions earlier than 20, the openssl version was 1.0.x instead of 3.0.x. This is most obvious in AWS Lambda deployments, where the binary target would be `rhel-openssl-1.0.x` instead of `rhel-openssl-3.0.x`. +:::info[Note] + +For Node.js versions earlier than 20, the openssl version was 1.0.x instead of 3.0.x. This is most obvious in AWS Lambda deployments, where the binary target would be `rhel-openssl-1.0.x` instead of `rhel-openssl-3.0.x`. + +::: diff --git a/content/200-orm/800-more/100-under-the-hood/100-engines.mdx b/content/200-orm/800-more/100-under-the-hood/100-engines.mdx index 78a8e65d4e..78d23be5a0 100644 --- a/content/200-orm/800-more/100-under-the-hood/100-engines.mdx +++ b/content/200-orm/800-more/100-under-the-hood/100-engines.mdx @@ -1,73 +1,96 @@ --- title: 'Engines' metaTitle: 'Engines' -metaDescription: "Prisma's query engine manages the communication with the database when using Prisma Client. Learn how it works on this page." +metaDescription: "Prisma's query engine manages the communication with the database when using Prisma ORM. Learn how it works on this page." --- -From a technical perspective, Prisma Client consists of three major components: +:::warning[Prisma ORM v7 is Rust binary-free by default] -- JavaScript client library -- TypeScript type definitions -- A query engine +As of **Prisma ORM v7**, Prisma ORM runs without Rust engines by default. This means: -All of these components are located in the [generated `.prisma/client` folder](/orm/prisma-client/setup-and-configuration/generating-prisma-client#the-prismaclient-npm-package) after you ran `prisma generate`. +- No Rust binary-based query engine binary is included in your generated code +- Queries are compiled to SQL using a TypeScript-based query compiler +- [Driver adapters](/orm/overview/databases/database-drivers#driver-adapters) are required for database connectivity +- The generated code is smaller and more portable across different JavaScript environments -This page covers relevant technical details about the query engine. +This page documents the legacy Rust-based engine architecture. For the modern Rust-free approach (default in v7), see [Prisma ORM without Rust engines](/orm/prisma-client/setup-and-configuration/no-rust-engine). -:::note +::: -As of [v6.16.0](https://pris.ly/release/6.16.0), Prisma ORM can be used without Rust engines in production applications. Learn more [here](/orm/prisma-client/setup-and-configuration/no-rust-engine). +:::info[Default generator in Prisma ORM v7] -**When enabled, your Prisma Client will be generated without a Rust-based query engine binary**: +The `prisma-client` generator is now the default in Prisma ORM v7. It generates TypeScript code into a custom directory you specify (via the `output` field). -```prisma -generator client { - provider = "prisma-client-js" // or "prisma-client" - output = "../src/generated/prisma" - engineType = "client" // no Rust engine -} -``` +Learn more about the [`prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client). -Note that [driver adapters](/orm/overview/databases/database-drivers#driver-adapters) are required if you want to use Prisma ORM without Rust engines. +::: -You can [read about the performance and DX improvements](https://www.prisma.io/blog/prisma-orm-without-rust-latest-performance-benchmarks) of this change on our blog. +From a technical perspective, when using **Rust-based engines** (legacy approach), Prisma Client consists of three major components: -::: +- JavaScript client library +- TypeScript type definitions +- A query engine (Rust-based) + +All of these components are located in the generated output folder after you run `prisma generate`. + +This page covers relevant technical details about the **Rust-based query engine architecture**, which is now optional and primarily used for: +- Legacy `prisma-client-js` generator users +- Users who explicitly set `engineType = "library"` or `engineType = "binary"` with the `prisma-client` generator ## Prisma engines +:::warning + +This section describes the **legacy Rust-based engine architecture**. In Prisma ORM v7, the default architecture uses a TypeScript-based query compiler without Rust engines. + +::: + At the core of each module, there typically is a [Prisma engine](https://github.com/prisma/prisma-engines) that implements the core set of functionality. Engines are implemented in [Rust](https://www.rust-lang.org/) and expose a low-level API that is used by the higher-level interfaces. A Prisma engine is the **direct interface to the database**, any higher-level interfaces always communicate with the database _through_ the engine-layer. -As an example, Prisma Client connects to the [query engine](/orm/more/under-the-hood/engines) in order to read and write data in a database: +As an example, when using Rust-based engines, Prisma Client connects to the query engine in order to read and write data in a database: ![Prisma engine](./typical-flow-query-engine-at-runtime.png) ### Using custom engine libraries or binaries -By default, all engine files are automatically downloaded into the `node_modules/@prisma/engines` folder when you install or update `prisma`, the Prisma CLI package. The [query engine](/orm/more/under-the-hood/engines) is also copied to the generated Prisma Client when you call `prisma generate`. +:::warning + +This section applies **only to Rust-based engines**. Prisma ORM v7 defaults to the TypeScript-based query compiler without Rust engine binaries. + +::: + +When using Rust-based engines, all engine files are automatically downloaded into the `node_modules/@prisma/engines` folder when you install or update `prisma`, the Prisma CLI package. The [query engine](/orm/more/under-the-hood/engines) is also copied to the generated Prisma Client when you call `prisma generate`. + You might want to use a [custom library or binary](https://github.com/prisma/prisma-engines) file if: - Automated download of engine files is not possible. - You have created your own engine library or binary for testing purposes, or for an OS that is not officially supported. -Use the following environment variables to specify custom locations for your binaries: +Use the following environment variables to specify custom locations for your Rust engine binaries: -- [`PRISMA_QUERY_ENGINE_LIBRARY`](/orm/reference/environment-variables-reference#prisma_query_engine_library) (Query engine, library) -- [`PRISMA_QUERY_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_query_engine_binary) (Query engine, binary) +- [`PRISMA_QUERY_ENGINE_LIBRARY`](/orm/reference/environment-variables-reference#prisma_query_engine_library) (Query engine, library) — **Not supported in Prisma ORM v7** +- [`PRISMA_QUERY_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_query_engine_binary) (Query engine, binary) — **Not supported in Prisma ORM v7** - [`PRISMA_SCHEMA_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_schema_engine_binary) (Schema engine) - [`PRISMA_MIGRATION_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_migration_engine_binary) (Migration engine) -- [`PRISMA_INTROSPECTION_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_introspection_engine_binary) (Introspection engine) +- [`PRISMA_INTROSPECTION_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_introspection_engine_binary) (Introspection engine) — **Not supported in Prisma ORM v7** + +:::warning - +**Prisma ORM v7 changes:** -- `PRISMA_MIGRATION_ENGINE_BINARY` variable is deprecated in [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0). -- The Introspection Engine is served by the Migration Engine from [4.9.0](https://github.com/prisma/prisma/releases/tag/4.9.0). Therefore, the `PRISMA_INTROSPECTION_ENGINE` environment variable will not be used. +- `PRISMA_QUERY_ENGINE_LIBRARY` and `PRISMA_QUERY_ENGINE_BINARY` are not supported in Prisma ORM v7. +- `PRISMA_INTROSPECTION_ENGINE_BINARY` is not supported in Prisma ORM v7. + +**Earlier deprecations:** + +- `PRISMA_MIGRATION_ENGINE_BINARY` variable is deprecated in [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0) because the Migration engine was renamed to Schema Engine. +- The Introspection Engine is served by the Schema Engine from [4.9.0](https://github.com/prisma/prisma/releases/tag/4.9.0). Therefore, the `PRISMA_INTROSPECTION_ENGINE` environment variable will not be used. - The `PRISMA_FMT_BINARY` variable is used in versions [4.2.0](https://github.com/prisma/prisma/releases/tag/4.2.0) or lower. - +::: #### Setting the environment variable @@ -157,6 +180,12 @@ Introspection Engine : introspection-core d6ff7119649922b84e413b3b69660e2f49e2dd ### Hosting engines +:::warning + +This section applies **only to Rust-based engines**. Prisma ORM v7 defaults to the TypeScript-based query compiler without Rust engine binaries. + +::: + The [`PRISMA_ENGINES_MIRROR`](/orm/reference/environment-variables-reference#prisma_engines_mirror) environment variable allows you to host engine files via a private server, AWS bucket or other cloud storage. This can be useful if you have a custom OS that requires custom-built engines. @@ -166,6 +195,12 @@ PRISMA_ENGINES_MIRROR=https://my-aws-bucket ## The query engine file +:::warning + +This section applies **only to Rust-based engines**. Prisma ORM v7 defaults to the TypeScript-based query compiler without Rust engine binaries. + +::: + The **query engine file** is different for each operating system. It is named `query-engine-PLATFORM` or `libquery_engine-PLATFORM` where `PLATFORM` corresponds to the name of a compile target. Query engine file extensions depend on the platform as well. As an example, if the query engine must run on a [Darwin]() operating system such as macOS Intel, it is called `libquery_engine-darwin.dylib.node` or `query-engine-darwin`. You can find an overview of all supported platforms [here](/orm/reference/prisma-schema-reference#binarytargets-options). The query engine file is downloaded into the `runtime` directory of the generated Prisma Client when `prisma generate` is called. @@ -174,7 +209,13 @@ Note that the query engine is implemented in Rust. The source code is located in ## The query engine at runtime -By default, Prisma Client loads the query engine as a [Node-API library](https://nodejs.org/api/n-api.html). You can alternatively [configure Prisma to use the query engine compiled as an executable binary](#configuring-the-query-engine), which is run as a sidecar process alongside your application. +:::warning + +This section applies **only to Rust-based engines**. Prisma ORM v7 defaults to the TypeScript-based query compiler without Rust engine binaries. + +::: + +When using Rust-based engines, Prisma Client loads the query engine as a [Node-API library](https://nodejs.org/api/n-api.html) by default. You can alternatively [configure Prisma to use the query engine compiled as an executable binary](#configuring-the-query-engine), which is run as a sidecar process alongside your application. The Node-API library approach is recommended since it reduces the communication overhead between Prisma Client and the query engine. ![Diagram showing the query engine and Node.js at runtime](./query-engine-node-js-at-runtime.png) @@ -201,7 +242,13 @@ The following diagram depicts a "typical flow": ## Responsibilities of the query engine -The query engine has the following responsibilities in an application that uses Prisma Client: +:::warning + +This section applies **only to Rust-based engines**. Prisma ORM v7 defaults to the TypeScript-based query compiler without Rust engine binaries. + +::: + +The Rust-based query engine has the following responsibilities in an application that uses Prisma Client: - manage physical database connections in connection pool - receive incoming queries from the Prisma Client Node.js process @@ -211,7 +258,13 @@ The query engine has the following responsibilities in an application that uses ## Debugging the query engine -You can access the logs of the query engine by setting the [`DEBUG`](/orm/prisma-client/debugging-and-troubleshooting/debugging) environment variable to `engine`: +:::warning + +This section applies only to Rust-based engines. Prisma ORM v7 defaults to the TypeScript-based query compiler without Rust engine binaries. + +::: + +You can access the logs of the Rust-based query engine by setting the [`DEBUG`](/orm/prisma-client/debugging-and-troubleshooting/debugging) environment variable to `engine`: ```terminal export DEBUG="engine" @@ -229,26 +282,47 @@ Learn more about [Debugging](/orm/prisma-client/debugging-and-troubleshooting/de ## Configuring the query engine +:::warning + +The configuration options in this section apply **only to Rust-based engines** used in Prisma ORM v6.19 and earlier. Prisma ORM v7 uses the TypeScript-based query compiler by default and does not use these Rust engine configurations. + +::: + ### Defining the query engine type for Prisma Client -[As described above](#the-query-engine-at-runtime) the default query engine is a Node-API library that is loaded into Prisma Client, but there is also an alternative implementation as an executable binary that runs in its own process. You can configure the query engine type by providing the `engineType` property to the Prisma Client `generator`: +When using Rust-based engines, you can choose between a Node-API library or an executable binary. Configure the query engine type by providing the `engineType` property to the Prisma Client `generator`: ```prisma generator client { - provider = "prisma-client-js" - engineType = "binary" + provider = "prisma-client-js" // or "prisma-client" + engineType = "binary" // or "library" for Rust-based engines } ``` -Valid values for `engineType` are `binary` and `library`. You can also use the environment variable [`PRISMA_CLIENT_ENGINE_TYPE`](/orm/reference/environment-variables-reference#prisma_client_engine_type) instead. +Valid values for `engineType` are: +- `binary` - Executable binary that runs as a sidecar process (Rust-based) +- `library` - Node-API library loaded into Prisma Client (Rust-based, default for v6 and earlier) + +:::warning + +The environment variable `PRISMA_CLIENT_ENGINE_TYPE` is not supported in Prisma ORM v7 because Prisma Client now defaults to the TypeScript-based query compiler without Rust engine binaries. See [Prisma ORM without Rust engines](/orm/prisma-client/setup-and-configuration/no-rust-engine) for more information. - +::: + +:::info[Historical context] - Until Prisma 3.x the default and only engine type available was `binary`, so there was no way to configure the engine type to be used by Prisma Client and Prisma CLI. - From versions [2.20.0](https://github.com/prisma/prisma/releases/2.20.0) to 3.x the `library` engine type was available and used by default by [activating the preview feature flag](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) "`nApi`" or using the `PRISMA_FORCE_NAPI=true` environment variable. +- As of Prisma ORM v7, the TypeScript-based query compiler (no Rust binaries) is the default and `engineType` does not need to be set. - +::: ### Defining the query engine type for Prisma CLI -Prisma CLI also uses its own query engine for its own needs. You can configure it to use the binary version of the query engine by defining the environment variable [`PRISMA_CLI_QUERY_ENGINE_TYPE=binary`](/orm/reference/environment-variables-reference#prisma_cli_query_engine_type). +When using Rust-based engines, Prisma CLI also uses its own query engine. You can configure it to use the binary version of the query engine by defining the environment variable [`PRISMA_CLI_QUERY_ENGINE_TYPE=binary`](/orm/reference/environment-variables-reference#prisma_cli_query_engine_type). + +:::warning + +The environment variable `PRISMA_CLI_QUERY_ENGINE_TYPE` is not supported in Prisma ORM v7 because Prisma CLI now defaults to the TypeScript-based query compiler without Rust engine binaries. See [Prisma ORM without Rust engines](/orm/prisma-client/setup-and-configuration/no-rust-engine) for more information. + +::: From 1db29feec652b3b8bc1f25ec44ee0179b574fdcb Mon Sep 17 00:00:00 2001 From: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> Date: Mon, 17 Nov 2025 15:12:49 +0600 Subject: [PATCH 09/23] fix: clarify config file path better (#7261) --- .../10-overview/04-location.mdx | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/content/200-orm/100-prisma-schema/10-overview/04-location.mdx b/content/200-orm/100-prisma-schema/10-overview/04-location.mdx index b3d89f6a04..297af71b8b 100644 --- a/content/200-orm/100-prisma-schema/10-overview/04-location.mdx +++ b/content/200-orm/100-prisma-schema/10-overview/04-location.mdx @@ -48,7 +48,7 @@ Run prisma generate to generate Prisma Client. If you prefer splitting your Prisma schema into multiple files, you can have a setup that looks as follows: ``` -. +prisma/ ├── migrations ├── models │ ├── posts.prisma @@ -65,7 +65,7 @@ Multi-file Prisma schemas are Generally Available since [v6.7.0](https://pris.ly ### Usage -When using a multi-file Prisma schema, you must always explicitly specify the location of the directory that contains the `.prisma` file with your `datasource` block. +When using a multi-file Prisma schema, you must always explicitly specify the location of the directory that contains your schema files (including the main `schema.prisma` file with your `generator` block). You can do this in either of three ways: @@ -79,14 +79,21 @@ You can do this in either of three ways: } } ``` -- set the `schema` property in [`prisma.config.ts`](/orm/reference/prisma-config-reference#schema): +- set the `schema` property in [`prisma.config.ts`](/orm/reference/prisma-config-reference#schema) ( for Prisma ORM v7): ```ts - import path from 'node:path' - import type { PrismaConfig } from 'prisma' - - export default { - schema: path.join('prisma'), - } satisfies PrismaConfig + import { defineConfig, env } from 'prisma/config' + import 'dotenv/config' + + export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + seed: 'tsx prisma/seed.ts', + }, + datasource: { + url: env('DATABASE_URL'), + }, + }) ``` :::note @@ -95,29 +102,40 @@ You can do this in either of three ways: ::: -All examples above assume that your `datasource` block is defined in a `.prisma` file inside the `prisma` directory. +:::warning -You also must place the `migrations` directory next to the `.prisma` file that defines the `datasource` block. +The `schema.prisma` file (which contains your `generator` block) must be located in the same directory that you specify in your schema configuration. For example, if you configure `schema: 'prisma'`, your `schema.prisma` file must be at `prisma/schema.prisma`, not in a subdirectory like `prisma/models/schema.prisma`. -For example, assuming `schema.prisma` defines the `datasource`, here's how how need to place the migrations folder: +::: + +You also must place the `migrations` directory at the same level as your `schema.prisma` file. + +For example, assuming `schema.prisma` defines the `generator` block, here's the correct directory structure: ``` -# `migrations` and `schema.prisma` must be on the same level -. +# All files must be inside the `prisma/` directory +# `migrations` and `schema.prisma` must be at the same level +prisma/ ├── migrations ├── models │ ├── posts.prisma │ └── users.prisma -└── schema.prisma +└── schema.prisma # Contains generator block ``` +:::info + +If your schema files are in a `prisma/` directory (as shown above), the Prisma CLI commands like `prisma generate` and `prisma migrate dev` will work without additional configuration, as `./prisma/schema.prisma` is a default location. + +::: + ### Tips for multi-file Prisma Schema We've found that a few patterns work well with this feature and will help you get the most out of it: - Organize your files by domain: group related models into the same file. For example, keep all user-related models in `user.prisma` while post-related models go in `post.prisma`. - Use clear naming conventions: schema files should be named clearly and succinctly. Use names like `user.prisma` and `post.prisma` and not `myModels.prisma` or `CommentFeaturesSchema.prisma`. -- Have an obvious "main" schema file: while you can now have as many schema files as you want, you'll still need a place where you define `datasource` and `generator` blocks. We recommend having a single schema file that's obviously the "main" file so that these blocks are easy to find. `main.prisma`, `schema.prisma`, and `base.prisma` are a few we've seen that work well. +- Have an obvious "main" schema file: while you can now have as many schema files as you want, you'll still need a place where you define your `generator` block. We recommend having a single schema file that's obviously the "main" file so that this block is easy to find. `main.prisma`, `schema.prisma`, and `base.prisma` are a few we've seen that work well. ### Examples From 8d21ba4fb7da186434fe268348dcc6de99b0068c Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Mon, 17 Nov 2025 15:25:41 +0530 Subject: [PATCH 10/23] Update ORM docs (#7260) * update * use pg adapter instead of accelerate * update * add dotenv in prisma.config.ts * fix warning note * update * update --- .../100-introduction/100-what-is-prisma.mdx | 40 +++++-- .../100-introduction/300-data-modeling.mdx | 4 +- .../300-prisma-in-your-stack/01-rest.mdx | 3 +- .../300-prisma-in-your-stack/03-fullstack.mdx | 3 +- .../04-is-prisma-an-orm.mdx | 12 ++- .../500-databases/200-database-drivers.mdx | 8 +- .../500-databases/300-postgresql.mdx | 29 ++++- .../050-overview/500-databases/400-mysql.mdx | 27 ++++- .../050-overview/500-databases/500-sqlite.mdx | 8 +- .../500-databases/600-mongodb.mdx | 16 +-- .../500-databases/800-sql-server/index.mdx | 29 ++++- .../500-databases/840-cockroachdb.mdx | 31 ++++-- .../500-databases/850-planetscale.mdx | 19 ++-- .../500-databases/880-supabase.mdx | 7 +- .../050-overview/500-databases/890-neon.mdx | 9 +- .../050-overview/500-databases/900-turso.mdx | 2 +- .../050-overview/600-beyond-prisma-orm.mdx | 2 +- .../100-prisma-schema/10-overview/index.mdx | 5 +- .../20-data-model/10-models.mdx | 42 ++++---- .../20-relations/100-one-to-one-relations.mdx | 4 +- .../200-one-to-many-relations.mdx | 4 +- .../300-many-to-many-relations.mdx | 4 +- .../410-referential-actions/index.mdx | 28 ++--- .../20-relations/420-relation-mode.mdx | 18 ++-- .../20-data-model/20-relations/index.mdx | 8 +- .../20-data-model/30-indexes.mdx | 23 ++-- .../20-data-model/40-views.mdx | 1 + .../20-data-model/50-database-mapping.mdx | 4 +- .../20-data-model/60-multi-schema.mdx | 2 +- .../65-externally-managed-tables.mdx | 3 +- .../70-unsupported-database-features.mdx | 5 +- .../20-data-model/80-table-inheritance.mdx | 6 +- .../005-introduction.mdx | 9 +- .../010-generating-prisma-client.mdx | 21 ++-- .../015-instantiate-prisma-client.mdx | 4 +- .../100-connection-management.mdx | 6 +- .../115-connection-pool.mdx | 14 +-- .../050-databases-connections/index.mdx | 13 ++- .../200-read-replicas.mdx | 2 +- .../300-no-rust-engine.mdx | 44 ++++---- .../100-queries/030-crud.mdx | 22 ++-- .../100-queries/037-relation-queries.mdx | 3 +- .../100-queries/050-filtering-and-sorting.mdx | 7 +- .../056-aggregation-grouping-summarizing.mdx | 8 +- .../100-queries/058-transactions.mdx | 38 +++---- .../100-queries/060-full-text-search.mdx | 10 +- .../100-queries/061-custom-validation.mdx | 10 +- .../100-queries/062-computed-fields.mdx | 6 +- .../100-queries/064-custom-models.mdx | 6 +- .../100-queries/070-case-sensitivity.mdx | 4 +- .../150-using-raw-sql/100-typedsql.mdx | 1 + .../150-using-raw-sql/200-raw-queries.mdx | 20 ++-- .../150-using-raw-sql/300-safeql.mdx | 8 +- .../057-composite-types.mdx | 22 ++-- .../080-null-and-undefined.mdx | 15 +-- .../100-working-with-json-fields.mdx | 39 +++---- .../200-working-with-scalar-lists-arrays.mdx | 16 +-- ...ing-with-composite-ids-and-constraints.mdx | 8 +- .../300-client-extensions/100-model.mdx | 8 +- .../300-client-extensions/110-client.mdx | 8 +- .../300-client-extensions/120-query.mdx | 8 +- .../300-client-extensions/130-result.mdx | 4 +- .../300-client-extensions/index.mdx | 4 +- .../830-prisma-type-system.mdx | 1 - .../400-type-safety/index.mdx | 4 +- .../450-testing/100-unit-testing.mdx | 4 +- .../450-testing/150-integration-testing.mdx | 4 +- .../201-serverless/300-deploy-to-vercel.mdx | 2 +- .../400-deploy-to-aws-lambda.mdx | 2 +- .../301-edge/450-deploy-to-cloudflare.mdx | 75 ++++++++++--- .../301-edge/485-deploy-to-vercel.mdx | 99 ++++++++++++----- .../301-edge/550-deploy-to-deno-deploy.mdx | 36 +++---- ...y-database-changes-with-prisma-migrate.mdx | 4 +- .../130-logging.mdx | 8 +- .../240-metrics.mdx | 11 +- .../250-opentelemetry-tracing.mdx | 9 +- ...245-troubleshooting-binary-size-issues.mdx | 3 +- .../050-getting-started.mdx | 1 - .../005-overview.mdx | 4 +- .../200-shadow-database.mdx | 10 +- .../300-workflows/10-seeding.mdx | 10 +- .../110-native-database-types.mdx | 7 +- .../120-native-database-functions.mdx | 8 +- .../20-prototyping-your-schema.mdx | 8 +- .../300-workflows/200-troubleshooting.mdx | 4 +- .../300-workflows/30-baselining.mdx | 4 +- .../40-customizing-migrations.mdx | 4 +- .../300-workflows/50-squashing-migrations.mdx | 12 +-- .../60-generating-down-migrations.mdx | 8 +- .../70-patching-and-hotfixing.mdx | 8 +- .../80-unsupported-database-features.mdx | 4 +- .../90-development-and-production.mdx | 8 +- .../050-prisma-client-reference.mdx | 101 +++++++++--------- .../100-prisma-schema-reference.mdx | 67 ++++++------ .../200-prisma-cli-reference.mdx | 40 +++---- .../500-reference/250-error-reference.mdx | 4 +- .../300-environment-variables-reference.mdx | 1 - .../325-prisma-config-reference.mdx | 1 + .../500-reference/380-connection-urls.mdx | 1 - .../050-client-preview-features.mdx | 3 +- .../100-under-the-hood/100-engines.mdx | 5 +- .../101-jsonprotocol-changes.mdx | 4 +- .../600-upgrading-to-prisma-5/index.mdx | 12 +-- .../700-upgrading-to-prisma-4.mdx | 4 +- .../150-referential-actions.mdx | 8 +- .../800-upgrading-to-prisma-3/index.mdx | 8 +- .../200-upgrading-versions/900-codemods.mdx | 4 +- .../200-upgrading-versions/index.mdx | 4 +- .../250-upgrading-to-use-preview-features.mdx | 4 +- .../08-upgrade-from-mongodb-beta.mdx | 20 ++-- .../800-more/350-ai-tools/100-cursor.mdx | 6 +- .../800-more/350-ai-tools/200-tabnine.mdx | 10 +- .../800-more/350-ai-tools/300-windsurf.mdx | 6 +- .../350-ai-tools/400-github-copilot.mdx | 2 +- ...ompletion-in-graphql-resolvers-with-js.mdx | 6 +- .../300-implicit-to-explicit-conversion.mdx | 2 +- .../400-nextjs-help.mdx | 4 +- ...-comparing-columns-through-raw-queries.mdx | 20 ++-- .../600-vercel-caching-issue.mdx | 4 +- .../700-netlify-caching-issue.mdx | 4 +- .../800-check-constraints.mdx | 14 +-- .../900-prisma-nuxt-module.mdx | 23 ++-- ...50-typescript-performance-optimization.mdx | 4 +- package-lock.json | 36 ++++++- 124 files changed, 913 insertions(+), 675 deletions(-) diff --git a/content/200-orm/050-overview/100-introduction/100-what-is-prisma.mdx b/content/200-orm/050-overview/100-introduction/100-what-is-prisma.mdx index ea7fd22348..af317b3dad 100644 --- a/content/200-orm/050-overview/100-introduction/100-what-is-prisma.mdx +++ b/content/200-orm/050-overview/100-introduction/100-what-is-prisma.mdx @@ -41,11 +41,11 @@ Every project that uses a tool from the Prisma ORM toolkit starts with a [Prisma ```prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model Post { @@ -101,10 +101,36 @@ model User { In this schema, you configure three things: -- **Data source**: Specifies your database connection (via an environment variable) +- **Data source**: Specifies your database connection. Database connection URLs are configured in `prisma.config.ts`. - **Generator**: Indicates that you want to generate Prisma Client - **Data model**: Defines your application models +### Configuring database connections + +Database connection URLs are configured in a `prisma.config.ts` file. Create a `prisma.config.ts` file in your project root: + +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + seed: 'tsx ./prisma/seed.ts', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +:::info + +When using Prisma CLI commands, environment variables are not automatically loaded. You'll need to use a package like `dotenv` to load environment variables from a `.env` file, or ensure your environment variables are set in your shell. + +::: + ### The Prisma schema data model On this page, the focus is on the data model. You can learn more about [Data sources](/orm/prisma-schema/overview/data-sources) and [Generators](/orm/prisma-schema/overview/generators) on the respective docs pages. @@ -142,9 +168,9 @@ Then, you can run `prisma generate`: npx prisma generate ``` -The `prisma generate` command reads your Prisma schema and _generates_ Prisma Client code. The code is [generated into the `node_modules/.prisma/client` folder by default](/orm/prisma-client/setup-and-configuration/generating-prisma-client#the-prismaclient-npm-package). +The `prisma generate` command reads your Prisma schema and _generates_ Prisma Client code. The code is generated into the path specified in the `output` field of your generator block (e.g., `./generated` as shown in the schema example above). -After you change your data model, you'll need to manually re-generate Prisma Client by running `prisma generate` to ensure the code inside `node_modules/.prisma/client` gets updated. +After you change your data model, you'll need to manually re-generate Prisma Client by running `prisma generate` to ensure the generated code gets updated. #### Using Prisma Client to send queries to your database @@ -156,7 +182,7 @@ Once Prisma Client has been generated, you can import it in your code and send q ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' const prisma = new PrismaClient() ``` @@ -165,7 +191,7 @@ const prisma = new PrismaClient() ```js -const { PrismaClient } = require('@prisma/client') +const { PrismaClient } = require('./generated/client') const prisma = new PrismaClient() ``` diff --git a/content/200-orm/050-overview/100-introduction/300-data-modeling.mdx b/content/200-orm/050-overview/100-introduction/300-data-modeling.mdx index af5cd1a998..107ddf045b 100644 --- a/content/200-orm/050-overview/100-introduction/300-data-modeling.mdx +++ b/content/200-orm/050-overview/100-introduction/300-data-modeling.mdx @@ -211,9 +211,9 @@ export type User = { In addition to the generated types, Prisma Client also provides a data access API that you can use once you've installed the `@prisma/client` package: ```js -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' // or -// const { PrismaClient } = require('@prisma/client') +// const { PrismaClient } = require('../prisma/generated/client') const prisma = new PrismaClient() diff --git a/content/200-orm/050-overview/300-prisma-in-your-stack/01-rest.mdx b/content/200-orm/050-overview/300-prisma-in-your-stack/01-rest.mdx index 5b7c5e3442..0b3c249fb0 100644 --- a/content/200-orm/050-overview/300-prisma-in-your-stack/01-rest.mdx +++ b/content/200-orm/050-overview/300-prisma-in-your-stack/01-rest.mdx @@ -43,7 +43,8 @@ datasource db { } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model Post { diff --git a/content/200-orm/050-overview/300-prisma-in-your-stack/03-fullstack.mdx b/content/200-orm/050-overview/300-prisma-in-your-stack/03-fullstack.mdx index df9b99e3ed..f0942db1e5 100644 --- a/content/200-orm/050-overview/300-prisma-in-your-stack/03-fullstack.mdx +++ b/content/200-orm/050-overview/300-prisma-in-your-stack/03-fullstack.mdx @@ -41,7 +41,8 @@ datasource db { } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model Post { diff --git a/content/200-orm/050-overview/300-prisma-in-your-stack/04-is-prisma-an-orm.mdx b/content/200-orm/050-overview/300-prisma-in-your-stack/04-is-prisma-an-orm.mdx index 9ae264f8c9..f642ebd85c 100644 --- a/content/200-orm/050-overview/300-prisma-in-your-stack/04-is-prisma-an-orm.mdx +++ b/content/200-orm/050-overview/300-prisma-in-your-stack/04-is-prisma-an-orm.mdx @@ -228,11 +228,11 @@ As an example, here's a Prisma schema for a blog: ```prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model Post { @@ -308,7 +308,8 @@ datasource db { } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } ``` @@ -338,7 +339,8 @@ datasource db { } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model Post { @@ -380,7 +382,7 @@ So far, the article covered the concepts behind Prisma ORM, its implementation o Accessing the database with Prisma Client happens through the query methods it exposes. All queries return plain old JavaScript objects. Given the blog schema from above, fetching a user looks as follows: ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() diff --git a/content/200-orm/050-overview/500-databases/200-database-drivers.mdx b/content/200-orm/050-overview/500-databases/200-database-drivers.mdx index 323f9ca92c..822925c2ad 100644 --- a/content/200-orm/050-overview/500-databases/200-database-drivers.mdx +++ b/content/200-orm/050-overview/500-databases/200-database-drivers.mdx @@ -18,7 +18,7 @@ As of [v6.15.0](https://pris.ly/release/6.16.0), Prisma ORM can be used without ```prisma generator client { - provider = "prisma-client-js" // or "prisma-client" + provider = "prisma-client" output = "../src/generated/prisma" engineType = "client" // no Rust engine } @@ -102,7 +102,7 @@ Earlier versions of Prisma ORM required you to first instantiate the driver itse ```typescript import { createClient } from '@libsql/client' import { PrismaLibSQL } from '@prisma/adapter-libsql' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' // Old way of using driver adapters (before 6.6.0) const driver = createClient({ @@ -137,7 +137,7 @@ When using Prisma ORM's built-in drivers, the connection string is read from the On the other hand, when using a driver adapter, the connection string needs to be provided in your _application code_ when the driver adapter is set up initially. Here is how this is done for the `pg` driver and the `@prisma/adapter-pg` adapter: ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' import { PrismaPg } from '@prisma/adapter-pg' const adapter = new PrismaPg({ connectionString: env.DATABASE_URL }) @@ -154,7 +154,7 @@ Let's assume you had `output` in your Prisma schema set to `../src/generated/cli ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" output = "../src/generated/client" } ``` diff --git a/content/200-orm/050-overview/500-databases/300-postgresql.mdx b/content/200-orm/050-overview/500-databases/300-postgresql.mdx index fc4144ba28..52ead2eb8d 100644 --- a/content/200-orm/050-overview/500-databases/300-postgresql.mdx +++ b/content/200-orm/050-overview/500-databases/300-postgresql.mdx @@ -25,14 +25,33 @@ To connect to a PostgreSQL database server, you need to configure a [`datasource ```prisma file=schema.prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` +The database connection URL is configured in `prisma.config.ts`: + +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +:::info + +When using Prisma CLI commands, environment variables are not automatically loaded. You'll need to use a package like `dotenv` to load environment variables from a `.env` file, or ensure your environment variables are set in your shell. + +::: + The fields passed to the `datasource` block are: - `provider`: Specifies the `postgresql` data source connector. -- `url`: Specifies the [connection URL](#connection-url) for the PostgreSQL database server. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL. +- The `url` field is configured in `prisma.config.ts` and specifies the [connection URL](#connection-url) for the PostgreSQL database server. ## Using the `node-postgres` driver @@ -56,7 +75,7 @@ Now, when you instantiate Prisma Client, you need to pass an instance of Prisma ```ts import { PrismaPg } from '@prisma/adapter-pg' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const connectionString = `${process.env.DATABASE_URL}` @@ -105,11 +124,11 @@ The following components make up the _base URL_ of your database, they are alway | Password | `PASSWORD` | Password for your database user | | Database | `DATABASE` | Name of the [database](https://www.postgresql.org/docs/12/manage-ag-overview.html) you want to use, e.g. `mydb` | - +:::info You must [percentage-encode special characters](/orm/reference/connection-urls#special-characters). - +::: #### Arguments diff --git a/content/200-orm/050-overview/500-databases/400-mysql.mdx b/content/200-orm/050-overview/500-databases/400-mysql.mdx index d9b7033275..18e7214e5f 100644 --- a/content/200-orm/050-overview/500-databases/400-mysql.mdx +++ b/content/200-orm/050-overview/500-databases/400-mysql.mdx @@ -16,14 +16,33 @@ To connect to a MySQL database server, you need to configure a [`datasource`](/o ```prisma file=schema.prisma showLineNumbers datasource db { provider = "mysql" - url = env("DATABASE_URL") } ``` +The database connection URL is configured in `prisma.config.ts`: + +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +:::info + +When using Prisma CLI commands, environment variables are not automatically loaded. You'll need to use a package like `dotenv` to load environment variables from a `.env` file, or ensure your environment variables are set in your shell. + +::: + The fields passed to the `datasource` block are: - `provider`: Specifies the `mysql` data source connector, which is used both for MySQL and MariaDB. -- `url`: Specifies the [connection URL](#connection-url) for the MySQL database server. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL. +- The `url` field is configured in `prisma.config.ts` and specifies the [connection URL](#connection-url) for the MySQL database server. ## Using the `mariadb` driver @@ -83,11 +102,11 @@ The following components make up the _base URL_ of your database, they are alway | Password | `PASSWORD` | Password for your database user | | Database | `DATABASE` | Name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) you want to use, e.g. `mydb` | - +:::info You must [percentage-encode special characters](/orm/reference/connection-urls#special-characters). - +::: #### Arguments diff --git a/content/200-orm/050-overview/500-databases/500-sqlite.mdx b/content/200-orm/050-overview/500-databases/500-sqlite.mdx index db904f7aa8..1e27d3911b 100644 --- a/content/200-orm/050-overview/500-databases/500-sqlite.mdx +++ b/content/200-orm/050-overview/500-databases/500-sqlite.mdx @@ -46,10 +46,10 @@ npm install @prisma/adapter-better-sqlite3 Now, when you instantiate Prisma Client, you need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: ```ts -import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3'; +import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'; import { PrismaClient } from './generated/prisma'; -const adapter = new PrismaBetterSQLite3({ +const adapter = new PrismaBetterSqlite3({ url: "file:./prisma/dev.db" }); const prisma = new PrismaClient({ adapter }); @@ -64,10 +64,10 @@ By default, driver adapters store `DateTime` values as **ISO 8601 strings**, whi However, if you need **100% backward compatibility** with Prisma ORM's native SQLite driver (for example, when migrating an existing database), you should use the `unixepoch-ms` format, which stores timestamps as the number of milliseconds since the Unix epoch: ```ts -import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3'; +import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'; import { PrismaClient } from './generated/prisma'; -const adapter = new PrismaBetterSQLite3({ +const adapter = new PrismaBetterSqlite3({ url: "file:./prisma/dev.db" }, { timestampFormat: 'unixepoch-ms' diff --git a/content/200-orm/050-overview/500-databases/600-mongodb.mdx b/content/200-orm/050-overview/500-databases/600-mongodb.mdx index 0e519206ff..a88868ec91 100644 --- a/content/200-orm/050-overview/500-databases/600-mongodb.mdx +++ b/content/200-orm/050-overview/500-databases/600-mongodb.mdx @@ -12,11 +12,11 @@ codeStyle: false This guide discusses the concepts behind using Prisma ORM and MongoDB, explains the commonalities and differences between MongoDB and other database providers, and leads you through the process for configuring your application to integrate with MongoDB using Prisma ORM. - +:::info To connect Prisma ORM with MongoDB, refer to our [Getting Started documentation](/getting-started/prisma-orm/quickstart/mongodb). - +::: @@ -70,11 +70,11 @@ This section provides instructions for how to carry out tasks that require steps Migrating your database over time is an important part of the development cycle. During development, you will need to update your Prisma schema (for example, to add new fields), then update the data in your development environment’s database, and eventually push both the updated schema and the new data to the production database. - +:::info When using MongoDB, be aware that the “coupling” between your schema and the database is purposefully designed to be less rigid than with SQL databases; MongoDB will not enforce the schema, so you have to verify data integrity. - +::: These iterative tasks of updating the schema and the database can result in inconsistencies between your schema and the actual data in the database. Let’s look at one scenario where this can happen, and then examine several strategies for you and your team to consider for handling these inconsistencies. @@ -385,11 +385,11 @@ The fields passed to the `datasource` block are: - `provider`: Specifies the `mongodb` data source connector. - `url`: Specifies the [connection URL](#connection-url) for the MongoDB server. In this case, an [environment variable is used](/orm/more/development-environment/environment-variables) to provide the connection URL. - +:::warning The MongoDB database connector uses transactions to support nested writes. Transactions **require** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. - +::: ## Connection details @@ -417,11 +417,11 @@ The following components make up the _base URL_ of your database: | Port | `PORT` | Port on which your database server is running, e.g. `1234`. If none is provided the default `27017` is used. | | Database | `DATABASE` | Name of the database to use. If none is specified but the `authSource` option is set then the `authSource` database name is used. If neither the database in the connection string nor the `authSource` option is specified then it defaults to `admin` | - +:::info You must [percentage-encode special characters](/orm/reference/connection-urls#special-characters). - +::: #### Arguments diff --git a/content/200-orm/050-overview/500-databases/800-sql-server/index.mdx b/content/200-orm/050-overview/500-databases/800-sql-server/index.mdx index b118b92b32..86e02b41ac 100644 --- a/content/200-orm/050-overview/500-databases/800-sql-server/index.mdx +++ b/content/200-orm/050-overview/500-databases/800-sql-server/index.mdx @@ -15,14 +15,33 @@ To connect to a Microsoft SQL Server database, you need to configure a [`datasou ```prisma file=schema.prisma showLineNumbers datasource db { provider = "sqlserver" - url = env("DATABASE_URL") } ``` +The database connection URL is configured in `prisma.config.ts`: + +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +:::info + +When using Prisma CLI commands, environment variables are not automatically loaded. You'll need to use a package like `dotenv` to load environment variables from a `.env` file, or ensure your environment variables are set in your shell. + +::: + The fields passed to the `datasource` block are: - `provider`: Specifies the `sqlserver` data source connector. -- `url`: Specifies the [connection URL](#connection-details) for the Microsoft SQL Server database. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL. +- The `url` field is configured in `prisma.config.ts` and specifies the [connection URL](#connection-details) for the Microsoft SQL Server database. ## Using the `node-mssql` driver @@ -47,7 +66,7 @@ Now, when you instantiate Prisma Client, you need to pass an instance of Prisma ```ts import { PrismaMssql } from '@prisma/adapter-mssql' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const config = { server: 'localhost', @@ -75,7 +94,7 @@ The following example uses SQL authentication (username and password) with an en sqlserver://HOST[:PORT];database=DATABASE;user=USER;password=PASSWORD;encrypt=true ``` - +:::warning Note: If you are using any of the following characters in your connection string, [you will need to escape them](https://learn.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver16#escaping-values-in-the-connection-url). @@ -89,7 +108,7 @@ To escape these characters, use curly braces `{}` around values that contain spe sqlserver://HOST[:PORT];database=DATABASE;user={MyServer/MyUser};password={ThisIsA:SecurePassword;};encrypt=true ``` - +::: ### Arguments diff --git a/content/200-orm/050-overview/500-databases/840-cockroachdb.mdx b/content/200-orm/050-overview/500-databases/840-cockroachdb.mdx index ca6984dd09..beb30d2655 100644 --- a/content/200-orm/050-overview/500-databases/840-cockroachdb.mdx +++ b/content/200-orm/050-overview/500-databases/840-cockroachdb.mdx @@ -12,11 +12,11 @@ This guide discusses the concepts behind using Prisma ORM and CockroachDB, expla - +:::info The CockroachDB connector is generally available in versions `3.14.0` and later. It was first added as a [Preview feature](/orm/reference/preview-features) in version [`3.9.0`](https://github.com/prisma/prisma/releases/tag/3.9.0) with support for Introspection, and Prisma Migrate support was added in [`3.11.0`](https://github.com/prisma/prisma/releases/tag/3.11.0). - +::: ## What is CockroachDB? @@ -99,20 +99,39 @@ To connect to a CockroachDB database server, you need to configure a [`datasourc ```prisma file=schema.prisma showLineNumbers datasource db { provider = "cockroachdb" - url = env("DATABASE_URL") } ``` +The database connection URL is configured in `prisma.config.ts`: + +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +:::info + +When using Prisma CLI commands, environment variables are not automatically loaded. You'll need to use a package like `dotenv` to load environment variables from a `.env` file, or ensure your environment variables are set in your shell. + +::: + The fields passed to the `datasource` block are: - `provider`: Specifies the `cockroachdb` data source connector. -- `url`: Specifies the [connection URL](#connection-details) for the CockroachDB database server. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL. +- The `url` field is configured in `prisma.config.ts` and specifies the [connection URL](#connection-details) for the CockroachDB database server. - +:::info While `cockroachdb` and `postgresql` connectors are similar, it is mandatory to use the `cockroachdb` connector instead of `postgresql` when connecting to a CockroachDB database from version 5.0.0. - +::: ## Connection details diff --git a/content/200-orm/050-overview/500-databases/850-planetscale.mdx b/content/200-orm/050-overview/500-databases/850-planetscale.mdx index d325915dc1..d642075e1e 100644 --- a/content/200-orm/050-overview/500-databases/850-planetscale.mdx +++ b/content/200-orm/050-overview/500-databases/850-planetscale.mdx @@ -37,11 +37,11 @@ PlanetScale's branching model and design for scalability means that there are al - **Creating indexes on foreign keys.** When [emulating relations in Prisma ORM](#option-1-emulate-relations-in-prisma-client) (i.e. when _not_ using foreign key constraints on the database-level), you will need to create dedicated indexes on foreign keys. In a standard MySQL database, if a table has a column with a foreign key constraint, an index is automatically created on that column. When PlanetScale is configured to not use foreign key constraints, these indexes are [currently](https://github.com/prisma/prisma/issues/10611) not created when Prisma Client emulates relations, which can lead to issues with queries not being well optimized. To avoid this, you can create indexes in Prisma ORM. For more information, see [How to create indexes on foreign keys](#2-create-indexes-on-foreign-keys). - **Making schema changes with `db push`.** When you merge a development branch into your production branch, PlanetScale will automatically compare the two schemas and generate its own schema diff. This means that Prisma ORM's [`prisma migrate`](/orm/prisma-migrate) workflow, which generates its own history of migration files, is not a natural fit when working with PlanetScale. These migration files may not reflect the actual schema changes run by PlanetScale when the branch is merged. - + :::warning We recommend not using `prisma migrate` when making schema changes with PlanetScale. Instead, we recommend that you use the `prisma db push` command. - + ::: For an example of how this works, see [How to make schema changes with `db push`](#how-to-make-schema-changes-with-db-push) @@ -70,16 +70,15 @@ To enable emulation of relations in Prisma Client, set the `relationMode` field ```prisma file=schema.prisma datasource db { provider = "mysql" - url = env("DATABASE_URL") relationMode = "prisma" } ``` - +:::info The ability to set the relation mode was introduced as part of the `referentialIntegrity` preview feature in Prisma ORM version 3.1.1, and is generally available in Prisma ORM versions 4.8.0 and later.

The `relationMode` field was renamed in Prisma ORM version 4.5.0, and was previously named `referentialIntegrity`. -
+::: If you use relations in your Prisma schema with the default `"foreignKeys"` option for the `relationMode` field, PlanetScale will error and Prisma ORM output the [P3021 error message](/orm/reference/error-reference#p3021) when it tries to create foreign keys. (In versions before 2.27.0 it will output a raw database error.) @@ -132,11 +131,11 @@ You can then add this change to your schema [using `db push`](#how-to-make-schem In versions 4.7.0 and later, Prisma ORM warns you if you have a relation with no index on the relation scalar field. For more information, see [Index validation](/orm/prisma-schema/data-model/relations/relation-mode#index-validation). - +:::warning One issue to be aware of is that [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) cannot have an index added in this way. If query speed or cost is an issue, you may instead want to use an [explicit many-to-many relation](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations) in this case. - +::: ### Option 2: Enable foreign key constraints in the PlanetScale database settings @@ -269,8 +268,8 @@ In order to use the shard key attributes, you need to specify the `shardKeys` Pr ```prisma generator client { - provider = "prisma-client-js" - output = "../generated/prisma" + provider = "prisma-client" + output = "./generated/prisma" previewFeatures = ["shardKeys"] } ``` @@ -336,7 +335,7 @@ Update your Prisma Client instance to use the PlanetScale serverless driver: ```ts import { PrismaPlanetScale } from '@prisma/adapter-planetscale' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/prisma/client' import dotenv from 'dotenv' import { fetch as undiciFetch } from 'undici' diff --git a/content/200-orm/050-overview/500-databases/880-supabase.mdx b/content/200-orm/050-overview/500-databases/880-supabase.mdx index 9f338d42d4..b17558b8fa 100644 --- a/content/200-orm/050-overview/500-databases/880-supabase.mdx +++ b/content/200-orm/050-overview/500-databases/880-supabase.mdx @@ -64,19 +64,16 @@ You can then update your `schema.prisma` to use the new direct URL: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "postgresql" - url = env("DATABASE_URL") - //add-next-line - directUrl = env("DIRECT_URL") } ``` More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields). - +:::info We strongly recommend using connection pooling with Supavisor in addition to `DIRECT_URL`. You will gain the great developer experience of the Prisma CLI while also allowing for connections to be pooled regardless of your deployment strategy. While this is not strictly necessary for every app, serverless solutions will inevitably require connection pooling. - +::: ## Getting started with Supabase diff --git a/content/200-orm/050-overview/500-databases/890-neon.mdx b/content/200-orm/050-overview/500-databases/890-neon.mdx index d5be0b9d74..046bc1674d 100644 --- a/content/200-orm/050-overview/500-databases/890-neon.mdx +++ b/content/200-orm/050-overview/500-databases/890-neon.mdx @@ -63,19 +63,16 @@ You can then update your `schema.prisma` to use the new direct URL: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "postgresql" - url = env("DATABASE_URL") - //add-next-line - directUrl = env("DIRECT_URL") } ``` More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields). - +:::info We strongly recommend using the pooled connection string in your `DATABASE_URL` environment variable. You will gain the great developer experience of the Prisma CLI while also allowing for connections to be pooled regardless of deployment strategy. While this is not strictly necessary for every app, serverless solutions will inevitably require connection pooling. - +::: ## Resolving connection timeouts @@ -129,7 +126,7 @@ npm install @prisma/adapter-neon Update your Prisma Client instance: ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' import { PrismaNeon } from '@prisma/adapter-neon' import dotenv from 'dotenv' diff --git a/content/200-orm/050-overview/500-databases/900-turso.mdx b/content/200-orm/050-overview/500-databases/900-turso.mdx index df54ae82b0..0408350fd3 100644 --- a/content/200-orm/050-overview/500-databases/900-turso.mdx +++ b/content/200-orm/050-overview/500-databases/900-turso.mdx @@ -92,7 +92,7 @@ npm install @prisma/adapter-libsql Update your Prisma Client instance: ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' import { PrismaLibSQL } from '@prisma/adapter-libsql' const adapter = new PrismaLibSQL({ diff --git a/content/200-orm/050-overview/600-beyond-prisma-orm.mdx b/content/200-orm/050-overview/600-beyond-prisma-orm.mdx index bcb0a883e0..d3640fb297 100644 --- a/content/200-orm/050-overview/600-beyond-prisma-orm.mdx +++ b/content/200-orm/050-overview/600-beyond-prisma-orm.mdx @@ -33,7 +33,7 @@ Scale to millions of queries per day without infrastructure changes. Efficiently Accelerate integrates seamlessly with your Prisma ORM project through the `@prisma/extension-accelerate` client extension. Get started quickly with our [setup guide](/accelerate/getting-started) and instantly access full edge environment support, connection pooling, and global caching. ```tsx -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' import { withAccelerate } from '@prisma/extension-accelerate' // 1. Extend your Prisma Client with the Accelerate extension diff --git a/content/200-orm/100-prisma-schema/10-overview/index.mdx b/content/200-orm/100-prisma-schema/10-overview/index.mdx index 447ed608e5..462d421657 100644 --- a/content/200-orm/100-prisma-schema/10-overview/index.mdx +++ b/content/200-orm/100-prisma-schema/10-overview/index.mdx @@ -37,11 +37,11 @@ The following is an example of a Prisma Schema that specifies: ```prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model User { @@ -144,7 +144,6 @@ Environment variables can be accessed using the `env()` function: ```prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` diff --git a/content/200-orm/100-prisma-schema/20-data-model/10-models.mdx b/content/200-orm/100-prisma-schema/20-data-model/10-models.mdx index f8b2711c3e..381faa1962 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/10-models.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/10-models.mdx @@ -20,11 +20,11 @@ The following schema describes a blogging platform - the data model definition i ```prisma highlight=10-46;normal datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } //highlight-start @@ -189,7 +189,7 @@ const user = await prisma.user.create({ ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient({}) @@ -679,11 +679,11 @@ model User { The `firstName_lastName` field will now be named `fullName` instead. - +:::info Refer to the documentation on [working with composite IDs](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints) to learn how to interact with a composite ID in Prisma Client. - +::: ##### `@unique` fields as unique identifiers @@ -700,12 +700,12 @@ model User { } ``` - +:::info **Constraint names in relational databases**
You can optionally define a [custom primary key constraint name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) in the underlying database. -
+::: #### Defining IDs in MongoDB @@ -739,12 +739,12 @@ model User { } ``` - +:::warning **MongoDB does not support `@@id`**
MongoDB does not support composite IDs, which means you cannot identify a model with a `@@id` block. -
+::: ### Defining a default value @@ -799,11 +799,11 @@ Default values can be: - [Functions](#using-functions), such as [`now()`](/orm/reference/prisma-schema-reference#now) or [`uuid()`](/orm/reference/prisma-schema-reference#uuid) - JSON data. Note that JSON needs to be enclosed with double-quotes inside the `@default` attribute, e.g.: `@default("[]")`. If you want to provide a JSON object, you need to enclose it with double-quotes and then escape any internal double quotes using a backslash, e.g.: `@default("{ \"hello\": \"world\" }")`. - +:::info Refer to the [attribute function reference documentation](/orm/reference/prisma-schema-reference#attribute-functions) for information about connector support for functions. - +::: ### Defining a unique field @@ -877,12 +877,12 @@ model Post {
- +:::info **Constraint names in relational databases**
You can optionally define a [custom unique constraint name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) in the underlying database. -
+::: By default, the name of this field in Prisma Client queries will be `authorId_title`. @@ -905,11 +905,11 @@ model Post { The `authorId_title` field will now be named `authorTitle` instead. - +:::info Refer to the documentation on [working with composite unique identifiers](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints) to learn how to interact with a composite unique constraints in Prisma Client. - +::: #### Composite type unique constraints @@ -966,12 +966,12 @@ model Post { } ``` - +:::info **Index names in relational databases**
You can optionally define a [custom index name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) in the underlying database. -
+::: #### Defining composite type indexes @@ -1067,17 +1067,17 @@ enum Role { ## Defining composite types - +:::info Composite types were added in version `3.10.0` under the `mongodb` Preview feature flag and are in General Availability since version `3.12.0`. - +::: - +:::warning Composite types are currently only available on MongoDB. - +::: Composite types (known as [embedded documents](https://www.mongodb.com/docs/manual/data-modeling/#embedded-data) in MongoDB) provide support for embedding records inside other records, by allowing you to define new object types. Composite types are structured and typed in a similar way to [models](#defining-models). diff --git a/content/200-orm/100-prisma-schema/20-data-model/20-relations/100-one-to-one-relations.mdx b/content/200-orm/100-prisma-schema/20-data-model/20-relations/100-one-to-one-relations.mdx index 4d92e087ae..35fbb79f3d 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/20-relations/100-one-to-one-relations.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/20-relations/100-one-to-one-relations.mdx @@ -102,11 +102,11 @@ model Profile {
- +:::warning In MySQL, you can create a foreign key with only an index on the referenced side, and not a unique constraint. In Prisma ORM versions 4.0.0 and later, if you introspect a relation of this type it will trigger a validation error. To fix this, you will need to add a `@unique` constraint to the referenced field. - +::: ## Multi-field relations in relational databases diff --git a/content/200-orm/100-prisma-schema/20-data-model/20-relations/200-one-to-many-relations.mdx b/content/200-orm/100-prisma-schema/20-data-model/20-relations/200-one-to-many-relations.mdx index 3472d120d9..080681c7d4 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/20-relations/200-one-to-many-relations.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/20-relations/200-one-to-many-relations.mdx @@ -100,11 +100,11 @@ model Post {
- +:::warning In MySQL, you can create a foreign key with only an index on the referenced side, and not a unique constraint. In Prisma ORM versions 4.0.0 and later, if you introspect a relation of this type it will trigger a validation error. To fix this, you will need to add a `@unique` constraint to the referenced field. - +::: ## Multi-field relations in relational databases diff --git a/content/200-orm/100-prisma-schema/20-data-model/20-relations/300-many-to-many-relations.mdx b/content/200-orm/100-prisma-schema/20-data-model/20-relations/300-many-to-many-relations.mdx index 587c78fbbe..d90f6a1fc9 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/20-relations/300-many-to-many-relations.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/20-relations/300-many-to-many-relations.mdx @@ -347,11 +347,11 @@ Implicit m-n relations: - You cannot use a [multi-field ID](/orm/reference/prisma-schema-reference#id-1) - You cannot use a `@unique` in place of an `@id` - + :::info To use either of these features, you must use an [explicit m-n instead](#explicit-many-to-many-relations). - + ::: #### Conventions for relation tables in implicit m-n relations diff --git a/content/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/index.mdx b/content/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/index.mdx index bbef7dc445..8d3a16d497 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/index.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/index.mdx @@ -11,7 +11,7 @@ Referential actions determine what happens to a record when your application del From version 2.26.0, you can define referential actions on the relation fields in your Prisma schema. This allows you to define referential actions like cascading deletes and cascading updates at a Prisma ORM level. - +:::info **Version differences** @@ -19,7 +19,7 @@ From version 2.26.0, you can define referential actions on the relation fields i - If you use a version between 2.26.0 and 3.0.0, you can use referential actions as described on this page, but you must [enable the preview feature flag](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `referentialActions`. - If you use version 2.25.0 or earlier, you can configure cascading deletes manually in your database. - +::: In the following example, adding `onDelete: Cascade` to the `author` field on the `Post` model means that deleting the `User` record will also delete all related `Post` records. @@ -50,12 +50,12 @@ If you do not specify a referential action, Prisma ORM [uses a default](#referen - +:::danger If you upgrade from a version earlier than 2.26.0: It is extremely important that you check the [upgrade paths for referential actions](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/referential-actions) section. Prisma ORM's support of referential actions **removes the safety net in Prisma Client that prevents cascading deletes at runtime**. If you use the feature _without upgrading your database_, the [old default action](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/referential-actions#prisma-orm-2x-default-referential-actions) - `ON DELETE CASCADE` - becomes active. This might result in cascading deletes that you did not expect. - +::: ## What are referential actions? @@ -265,11 +265,11 @@ model User { `User`s with posts **cannot** be deleted. The `User`'s `id` **cannot** be changed. - +:::warning The `Restrict` action is **not** available on [Microsoft SQL Server](/orm/overview/databases/sql-server) and triggers a schema validation error. Instead, you can use [`NoAction`](#noaction), which produces the same result and is compatible with SQL Server. - +::: ### `NoAction` @@ -281,11 +281,11 @@ The `NoAction` action is similar to `Restrict`, the difference between the two i - **SQL Server**: When a referenced record is deleted or modified, an error is raised. See [the SQL Server docs](https://learn.microsoft.com/en-us/sql/relational-databases/tables/graph-edge-constraints?view=sql-server-ver15#on-delete-referential-actions-on-edge-constraints) for more information. - **MongoDB** (in preview from version 3.6.0): When a record is modified or deleted, nothing is done to any related records. - +:::warning If you are [managing relations in Prisma Client](/orm/prisma-schema/data-model/relations/relation-mode#emulate-relations-in-prisma-orm-with-the-prisma-relation-mode) rather than using foreign keys in the database, you should be aware that currently Prisma ORM only implements the referential actions. Foreign keys also create constraints, which make it impossible to manipulate data in a way that would violate these constraints: instead of executing the query, the database responds with an error. These constraints will not be created if you emulate referential integrity in Prisma Client, so if you set the referential action to `NoAction` there will be no checks to prevent you from breaking the referential integrity. - +::: #### Example usage @@ -389,11 +389,11 @@ When you run an Introspection, Prisma ORM compares all the foreign keys in the d After introspecting, you can review the non-default clauses in your schema. The most important clause to review is `onDelete`, which defaults to `Cascade` in 2.25.0 and earlier. - +:::warning If you are using either the [`delete()`](/orm/prisma-client/queries/crud#delete-a-single-record) or [`deleteMany()`](/orm/prisma-client/queries/crud#delete-all-records) methods, **[cascading deletes](#how-to-use-cascading-deletes) will now be performed** as the `referentialActions` preview feature **removed the safety net in Prisma Client that previously prevented cascading deletes at runtime**. Be sure to check your code and make any adjustments accordingly. - +::: Make sure you are happy with every case of `onDelete: Cascade` in your schema. If not, either: @@ -426,12 +426,12 @@ model User { When running a [Migration](/orm/prisma-migrate) (or the [`prisma db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) command) the [new defaults](#referential-action-defaults) will be applied to your database. - +:::info Unlike when you run an Introspect for the first time, the new referential actions clause and property, will **not** automatically be added to your prisma schema by the Prisma VSCode extension. You will have to manually add them if you wish to use anything other than the new defaults. - +::: Explicitly defining referential actions in your Prisma schema is optional. If you do not explicitly define a referential action for a relation, Prisma ORM uses the [new defaults](#referential-action-defaults). @@ -472,7 +472,7 @@ Prior to upgrading and enabling the referential actions **preview feature**, the > "The change you are trying to make would violate the required relation '\{relation_name}' between the \{model_a_name\} and \{model_b_name\} models." ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() @@ -500,7 +500,7 @@ To make sure you are checking for the correct errors in your code, modify your c > "Foreign key constraint failed on the field: \{field_name\}" ```ts highlight=14;delete|15;add -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() diff --git a/content/200-orm/100-prisma-schema/20-data-model/20-relations/420-relation-mode.mdx b/content/200-orm/100-prisma-schema/20-data-model/20-relations/420-relation-mode.mdx index 99aa146c36..cb4c8092f6 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/20-relations/420-relation-mode.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/20-relations/420-relation-mode.mdx @@ -75,11 +75,11 @@ In this case, the foreign key constraint on the `authorId` column of the `Post` Some databases, such as MongoDB or [PlanetScale](/orm/overview/databases/planetscale#differences-to-consider), do not support foreign keys. Additionally, in some cases developers may prefer not to use foreign keys in their relational database that usually does support foreign keys. For these situations, Prisma ORM offers [the `prisma` relation mode](#emulate-relations-in-prisma-orm-with-the-prisma-relation-mode), which emulates some properties of relations in relational databases. When you use Prisma Client with the `prisma` relation mode enabled, the behavior of queries is identical or similar, but referential actions and some constraints are handled by the Prisma engine rather than in the database. - +:::warning There are performance implications to emulation of referential integrity and referential actions in Prisma Client. In cases where the underlying database supports foreign keys, it is usually the preferred choice. - +::: ## How to set the relation mode in your Prisma schema @@ -88,17 +88,16 @@ To set the relation mode, add the `relationMode` field in the `datasource` block ```prisma file=schema.prisma highlight=4,9;add showLineNumbers datasource db { provider = "mysql" - url = env("DATABASE_URL") //add-next-line relationMode = "prisma" } ``` - +:::info The ability to set the relation mode was introduced as part of the `referentialIntegrity` preview feature in Prisma ORM version 3.1.1, and is generally available in Prisma ORM versions 4.8.0 and later.

The `relationMode` field was renamed in Prisma ORM version 4.5.0, and was previously named `referentialIntegrity`. -
+::: For relational databases, the available options are: @@ -107,11 +106,11 @@ For relational databases, the available options are: For MongoDB, the only available option is the `prisma` relation mode. This mode is also active if no `relationMode` is explicitly set in the `datasource` block. - +:::warning If you switch between relation modes, Prisma ORM will add or remove foreign keys to your database next time you apply changes to your schema with Prisma Migrate or `db push`. See [Switch between relation modes](#switch-between-relation-modes) for more information. - +::: ## Handle relations in your relational database with the `foreignKeys` relation mode @@ -147,12 +146,12 @@ The `prisma` relation mode emulates some foreign key constraints and referential The `prisma` relation mode is the default option for the MongoDB connector. It should also be set if you use a relational database that does not support foreign keys. For example, [if you use PlanetScale](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client) without foreign key constraints, you should use the `prisma` relation mode. - +:::warning There are performance implications to emulation of referential integrity in Prisma Client, because it uses additional database queries to maintain referential integrity. In cases where the underlying database can handle referential integrity with foreign keys, it is usually the preferred choice. - +::: Emulation of relations is only available for Prisma Client queries and does not apply to raw queries. @@ -213,7 +212,6 @@ If you do not add the index manually, queries might require full table scans. Th ```prisma file=schema.prisma showLineNumbers datasource db { provider = "mysql" - url = env("DATABASE_URL") relationMode = "prisma" } diff --git a/content/200-orm/100-prisma-schema/20-data-model/20-relations/index.mdx b/content/200-orm/100-prisma-schema/20-data-model/20-relations/index.mdx index 74653921e4..40caa28bd8 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/20-relations/index.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/20-relations/index.mdx @@ -299,17 +299,17 @@ model Category { - +:::info This schema is the same as the [example data model](/orm/prisma-schema/data-model/models) but has all [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields) removed (except for the required [relation scalar fields](/orm/prisma-schema/data-model/relations#relation-scalar-fields)) so you can focus on the [relation fields](#relation-fields). - +::: - +:::info This example uses [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations). These relations do not require the `@relation` attribute unless you need to [disambiguate relations](#disambiguating-relations). - +::: Notice that the syntax is slightly different between relational databases and MongoDB - particularly for [many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations). diff --git a/content/200-orm/100-prisma-schema/20-data-model/30-indexes.mdx b/content/200-orm/100-prisma-schema/20-data-model/30-indexes.mdx index 66ac00544d..b1891cbe30 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/30-indexes.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/30-indexes.mdx @@ -11,11 +11,11 @@ Prisma ORM allows configuration of database indexes, unique constraints and prim Version `3.6.0` also introduces support for introspection and migration of full text indexes in MySQL and MongoDB through a new `@@fulltext` attribute, available through the `fullTextIndex` Preview feature. - +:::warning If you are upgrading from a version earlier than 4.0.0, these changes to index configuration and full text indexes might be **breaking changes** if you have a database that already uses these features. See [Upgrading from previous versions](#upgrading-from-previous-versions) for more information on how to upgrade. - +::: @@ -189,11 +189,11 @@ The GIN index stores composite values, such as arrays or `JsonB` data. This is u An indexed field can define the operator class, which defines the operators handled by the index. - +:::warning Indexes using a function (such as `to_tsvector`) to determine the indexed value are not yet supported by Prisma ORM. Indexes defined in this way will not be visible with `prisma db pull`. - +::: As an example, the following model adds a `Gin` index to the `value` field, with `JsonbPathOps` as the class of operators allowed to use the index: @@ -460,11 +460,11 @@ A table can have at most one clustered index. ### Upgrading from previous versions - +:::warning These index configuration changes can be **breaking changes** when activating the functionality for certain, existing Prisma schemas for existing databases. After enabling the preview features required to use them, run `prisma db pull` to introspect the existing database to update your Prisma schema before using Prisma Migrate again. - +::: A breaking change can occur in the following situations: @@ -479,11 +479,11 @@ In each of the cases above unwanted changes to your database can be prevented by The `fullTextIndex` preview feature provides support for introspection and migration of full text indexes in MySQL and MongoDB in version 3.6.0 and later. This can be configured using the `@@fulltext` attribute. Existing full text indexes in the database are added to your Prisma schema after introspecting with `db pull`, and new full text indexes added in the Prisma schema are created in the database when using Prisma Migrate. This also prevents validation errors in some database schemas that were not working before. - +:::warning For now we do not enable the full text search commands in Prisma Client for MongoDB; the progress can be followed in the [MongoDB](https://github.com/prisma/prisma/issues/9413) issue. - +::: ### Enabling the `fullTextIndex` preview feature @@ -491,7 +491,8 @@ To enable the `fullTextIndex` preview feature, add the `fullTextIndex` feature f ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["fullTextIndex"] } ``` @@ -534,10 +535,10 @@ model Post { ### Upgrading from previous versions - +:::warning This can be a **breaking change** when activating the functionality for certain, existing Prisma schemas for existing databases. After enabling the preview features required to use them, run `prisma db pull` to introspect the existing database to update your Prisma schema before using Prisma Migrate again. - +::: Earlier versions of Prisma ORM converted full text indexes using the `@@index` attribute rather than the `@@fulltext` attribute. After enabling the `fullTextIndex` preview feature, run `prisma db pull` to convert these indexes to `@@fulltext` before migrating again with Prisma Migrate. If you do not do this, the existing indexes will be dropped instead and normal indexes will be created in their place. diff --git a/content/200-orm/100-prisma-schema/20-data-model/40-views.mdx b/content/200-orm/100-prisma-schema/20-data-model/40-views.mdx index ab3467c8dd..f2c479674f 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/40-views.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/40-views.mdx @@ -31,6 +31,7 @@ Support for views is currently in an early preview. To enable the `views` previe ```prisma file=schema.prisma highlight=3;add showLineNumbers generator client { provider = "prisma-client" + output = "./generated" //add-next-line previewFeatures = ["views"] } diff --git a/content/200-orm/100-prisma-schema/20-data-model/50-database-mapping.mdx b/content/200-orm/100-prisma-schema/20-data-model/50-database-mapping.mdx index 0bd8d6550c..87fa788746 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/50-database-mapping.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/50-database-mapping.mdx @@ -80,11 +80,11 @@ You can optionally use the `map` argument to explicitly define the **underlying When introspecting a database, the `map` argument will _only_ be rendered in the schema if the name _differs_ from Prisma ORM's [default constraint naming convention for indexes and constraints](#prisma-orms-default-naming-conventions-for-indexes-and-constraints). - +:::danger If you use Prisma Migrate in a version earlier than 2.29.0 and want to maintain your existing constraint and index names after upgrading to a newer version, **do not** immediately run `prisma migrate` or `prisma db push`. This will **change any underlying constraint name that does not follow Prisma ORM's convention**. Follow the [upgrade path that allows you to maintain existing constraint and index names](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/named-constraints#option-1-i-want-to-maintain-my-existing-constraint-and-index-names). - +::: ### Use cases for named constraints diff --git a/content/200-orm/100-prisma-schema/20-data-model/60-multi-schema.mdx b/content/200-orm/100-prisma-schema/20-data-model/60-multi-schema.mdx index 213aca8ec7..6c8568acbe 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/60-multi-schema.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/60-multi-schema.mdx @@ -28,11 +28,11 @@ To use multiple database schemas in your Prisma schema file, add the names of yo ```prisma file=schema.prisma generator client { provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") //add-next-line schemas = ["base", "shop"] } diff --git a/content/200-orm/100-prisma-schema/20-data-model/65-externally-managed-tables.mdx b/content/200-orm/100-prisma-schema/20-data-model/65-externally-managed-tables.mdx index bf14f9c00f..f5dfaf0e10 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/65-externally-managed-tables.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/65-externally-managed-tables.mdx @@ -137,7 +137,8 @@ Assume you have the following Prisma schema which only contains the `posts` tabl ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" // ... } diff --git a/content/200-orm/100-prisma-schema/20-data-model/70-unsupported-database-features.mdx b/content/200-orm/100-prisma-schema/20-data-model/70-unsupported-database-features.mdx index 5c5476d85c..cc27bd16c3 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/70-unsupported-database-features.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/70-unsupported-database-features.mdx @@ -58,18 +58,19 @@ In Prisma ORM versions 4.5.0 and later, you can then activate the extension by d ```prisma file=schema.prisma highlight=3,9;add showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" //add-next-line previewFeatures = ["postgresqlExtensions"] } datasource db { provider = "postgresql" - url = env("DATABASE_URL") //add-next-line extensions = [pgcrypto] } ``` +``` In earlier versions of Prisma ORM, you must instead run a SQL command to activate the extension: diff --git a/content/200-orm/100-prisma-schema/20-data-model/80-table-inheritance.mdx b/content/200-orm/100-prisma-schema/20-data-model/80-table-inheritance.mdx index 5824300c6b..e3aad67fde 100644 --- a/content/200-orm/100-prisma-schema/20-data-model/80-table-inheritance.mdx +++ b/content/200-orm/100-prisma-schema/20-data-model/80-table-inheritance.mdx @@ -141,7 +141,7 @@ When querying for videos and articles like that, TypeScript will still only reco If you want to have type safety for these objects, you need to define dedicated types for them. You can do this, for example, by using the generated `Activity` type and the TypeScript `Omit` utility type to remove properties from it: ```ts -import { Activity } from '@prisma/client' +import { Activity } from '../prisma/generated/client' type Video = Omit type Article = Omit @@ -272,7 +272,7 @@ import { Video as VideoDB, Article as ArticleDB, Activity, -} from '@prisma/client' +} from '../prisma/generated/client' type Video = Omit type Article = Omit @@ -281,7 +281,7 @@ type Article = Omit Once these types are defined, you can define mapping functions to convert the types you receive from the queries above into the desired `Video` and `Article` types. Here's the example for the `Video` type: ```ts -import { Prisma, Video as VideoDB, Activity } from '@prisma/client' +import { Prisma, Video as VideoDB, Activity } from '../prisma/generated/client' type Video = Omit diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx index 99beeecfb0..972efafea5 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx @@ -46,12 +46,11 @@ In order to set up Prisma Client, you need a [Prisma schema file](/orm/prisma-sc ```prisma file=schema.prisma datasource db { - url = env("DATABASE_URL") provider = "postgresql" } generator client { - provider = "prisma-client-js" + provider = "prisma-client" output = "../src/generated/prisma" } @@ -154,15 +153,15 @@ const newUser = await prisma.user.create({ const users = await prisma.user.findMany() ``` - +:::info All Prisma Client methods return an instance of [`PrismaPromise`](/orm/reference/prisma-client-reference#prismapromise-behavior) which only executes when you call `await` or `.then()` or `.catch()`. - +::: ### 5. Evolving your application -Whenever you make changes to your database that are reflected in the Prisma schema, you need to manually re-generate Prisma Client to update the generated code in the `node_modules/.prisma/client` directory: +Whenever you make changes to your database that are reflected in the Prisma schema, you need to manually re-generate Prisma Client to update the generated code in your output directory: ``` prisma generate diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx index 8e7d257bf2..daa48991e7 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx @@ -18,7 +18,8 @@ If Prisma ORM's Rust engine binaries cause large bundle sizes, slow builds, or d ```prisma generator client { - provider = "prisma-client-js" // or "prisma-client" + provider = "prisma-client" + output = "./generated" engineType = "client" } ``` @@ -49,14 +50,14 @@ To generate and instantiate Prisma Client: ```prisma generator client { - provider = "prisma-client-js" - output = "app/generated/prisma/client" + provider = "prisma-client" + output = "./generated" } ``` :::note - Feel free to customize the output location to match your application. Common directories are `app`, `src`, or even the root of your project. + Feel free to customize the output location to match your application. Common directories are `prisma`, `src`, or even the root of your project. ::: @@ -69,13 +70,13 @@ To generate and instantiate Prisma Client: 1. Generate Prisma Client with the following command: ```terminal - prisma generate + npx prisma generate ``` 1. You can now [instantiate Prisma Client](/orm/prisma-client/setup-and-configuration/instantiate-prisma-client) in your code: ```ts - import { PrismaClient } from 'app/generated/prisma/client' + import { PrismaClient } from './prisma/generated/client' const prisma = new PrismaClient() // use `prisma` in your application to read and write data in your DB ``` @@ -100,8 +101,8 @@ You can also specify a custom `output` path on the `generator` configuration, fo ```prisma generator client { - provider = "prisma-client-js" - output = "../src/generated/client" + provider = "prisma-client" + output = "../src/generated/" } ``` @@ -147,6 +148,10 @@ To load environment variables in your Prisma application, you can use the `prism import { defineConfig, env } from "prisma/config"; export default defineConfig({ + schema: "prisma/schema.prisma", + migrations: { + path: "prisma/migrations" + }, datasource: { url: env("DATABASE_URL"), }, diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/015-instantiate-prisma-client.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/015-instantiate-prisma-client.mdx index 5b913ccb38..48da945dac 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/015-instantiate-prisma-client.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/015-instantiate-prisma-client.mdx @@ -12,7 +12,7 @@ The following example demonstrates how to import and instantiate your [generated ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() ``` @@ -22,7 +22,7 @@ const prisma = new PrismaClient() ```js -const { PrismaClient } = require('@prisma/client') +const { PrismaClient } = require('../prisma/generated/client') const prisma = new PrismaClient() ``` diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/100-connection-management.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/100-connection-management.mdx index 241f4a247b..a3722e27f9 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/100-connection-management.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/100-connection-management.mdx @@ -67,7 +67,7 @@ One scenario where you should call `$disconnect()` explicitly is where a script: The following script creates a new instance of `PrismaClient`, performs a task, and then disconnects - which closes the connection pool: ```ts highlight=19;normal -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() const emailService = new EmailService() @@ -94,11 +94,11 @@ If the above script runs multiple times in the context of a long-running applica ## Exit hooks - +:::info From Prisma ORM 5.0.0, the `beforeExit` hook only applies to the [binary Query Engine](/orm/more/under-the-hood/engines#configuring-the-query-engine). - +::: The `beforeExit` hook runs when Prisma ORM is triggered externally (e.g. via a `SIGINT` signal) to shut down, and allows you to run code _before_ Prisma Client disconnects - for example, to issue queries as part of a graceful shutdown of a service: diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/115-connection-pool.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/115-connection-pool.mdx index ba25506e73..24ca0d50ee 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/115-connection-pool.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/115-connection-pool.mdx @@ -29,7 +29,7 @@ As of [v6.16.0](https://pris.ly/release/6.16.0), Prisma ORM can be used without ```prisma generator client { - provider = "prisma-client-js" // or "prisma-client" + provider = "prisma-client" output = "../src/generated/prisma" engineType = "client" // no Rust engine } @@ -96,7 +96,7 @@ For example, consider the following Prisma Client instance and invocation: ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient({ log: ['info'], @@ -121,11 +121,11 @@ prisma:info Starting a postgresql pool with 21 connections. When the `PrismaClient` class was instantiated, the logging notified `stdout` that a connection pool with 21 connections was started. - +:::warning Note that the output generated by `log: ['info']` can change in any release without notice. Be aware of this in case you are relying on the output in your application or a tool that you're building. - +::: If you need even more insights into the size of your connection pool and the amount of in-use and idle connection, you can use the [metrics](/orm/prisma-client/observability-and-logging/metrics) feature (which is currently in Preview). @@ -135,7 +135,7 @@ Consider the following example: ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() @@ -193,11 +193,11 @@ main() - +:::info For more details on what is available in the metrics output, see the [About metrics](/orm/prisma-client/observability-and-logging/metrics#about-metrics) section. - +::: ### Connection pool timeout diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx index 4f9daf7d74..d94e3e2e48 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx @@ -14,11 +14,11 @@ Databases can handle a limited number of concurrent connections. Each connection The way your application **manages connections** also impacts performance. This guide describes how to approach connection management in [serverless environments](#serverless-environments-faas) and [long-running processes](#long-running-processes). - +:::warning This guide focuses on **relational databases** and how to configure and tune the Prisma ORM connection pool (MongoDB uses the MongoDB driver connection pool). - +::: @@ -61,7 +61,7 @@ In **long-running** applications, we recommend that you: To re-use a single instance, create a module that exports a `PrismaClient` object: ```ts file=client.ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' let prisma = new PrismaClient() @@ -93,7 +93,7 @@ Frameworks like [Next.js](https://nextjs.org/) support hot reloading of changed As a workaround, you can store `PrismaClient` as a global variable in development environments only, as global variables are not reloaded: ```ts file=client.ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const globalForPrisma = globalThis as unknown as { prisma: PrismaClient } @@ -223,7 +223,7 @@ If the `connection_limit` is 1, this function is forced to send queries **serial Instantiate `PrismaClient` [outside the scope of the function handler](https://github.com/prisma/e2e-tests/blob/5d1041d3f19245d3d237d959eca94d1d796e3a52/platforms/serverless-lambda/index.ts#L3) to increase the chances of reuse. As long as the handler remains 'warm' (in use), the connection is potentially reusable: ```ts highlight=3;normal -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const client = new PrismaClient() @@ -273,7 +273,7 @@ As of [v6.16.0](https://pris.ly/release/6.16.0), Prisma ORM can be used without ```prisma generator client { - provider = "prisma-client-js" // or "prisma-client" + provider = "prisma-client" output = "../src/generated/prisma" engineType = "client" // no Rust engine } @@ -353,7 +353,6 @@ You can then update your `schema.prisma` to use the new direct URL: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "postgresql" - url = env("DATABASE_URL") //add-next-line directUrl = env("DIRECT_URL") } diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/200-read-replicas.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/200-read-replicas.mdx index ef695f72d3..619d0a798d 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/200-read-replicas.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/200-read-replicas.mdx @@ -26,7 +26,7 @@ Initialize the extension by extending your Prisma Client instance and provide th ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' import { readReplicas } from '@prisma/extension-read-replicas' const prisma = new PrismaClient().$extends( diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/300-no-rust-engine.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/300-no-rust-engine.mdx index a23c2016fd..348a0e6fc3 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/300-no-rust-engine.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/300-no-rust-engine.mdx @@ -100,7 +100,7 @@ Finally, instantiate Prisma Client which you can do using the driver adapter and ```typescript import { PrismaPg } from '@prisma/adapter-pg' -import { PrismaClient } from './generated/prisma' +import { PrismaClient } from '../generated/prisma/client' const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) @@ -108,16 +108,16 @@ const prisma = new PrismaClient({ adapter }) ```typescript -import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3'; -import { PrismaClient } from './generated/prisma'; +import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'; +import { PrismaClient } from '../generated/prisma/client'; -const adapter = new PrismaBetterSQLite3({ url: process.env.DATABASE_URL }) +const adapter = new PrismaBetterSqlite3({ url: process.env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }); ``` ```typescript -import { PrismaClient } from './generated/prisma' +import { PrismaClient } from '../generated/prisma/client' import { PrismaD1 } from '@prisma/adapter-d1' export interface Env { @@ -141,7 +141,7 @@ export default { ```typescript import { PrismaMariaDb } from '@prisma/adapter-mariadb'; -import { PrismaClient } from './generated/prisma'; +import { PrismaClient } from '../generated/prisma/client'; const adapter = new PrismaMariaDb({ host: "localhost", @@ -154,7 +154,7 @@ const prisma = new PrismaClient({ adapter }); ```typescript import { PrismaPlanetScale } from '@prisma/adapter-planetscale' -import { PrismaClient } from './generated/prisma' +import { PrismaClient } from '../generated/prisma/client' import { fetch as undiciFetch } from 'undici' const adapter = new PrismaPlanetScale({ url: process.env.DATABASE_URL, fetch: undiciFetch }) @@ -164,7 +164,7 @@ const prisma = new PrismaClient({ adapter }) ```typescript import { PrismaMSSQL } from '@prisma/adapter-mssql'; -import { PrismaClient } from './generated/prisma'; +import { PrismaClient } from '../generated/prisma/client'; const sqlConfig = { user: process.env.DB_USER, @@ -189,7 +189,7 @@ const prisma = new PrismaClient({ adapter }); ```typescript import { PrismaPg } from '@prisma/adapter-pg' -import { PrismaClient } from './generated/prisma' +import { PrismaClient } from '../generated/prisma/client' const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) @@ -197,7 +197,7 @@ const prisma = new PrismaClient({ adapter }) ```typescript -import { PrismaClient } from './generated/prisma' +import { PrismaClient } from '../generated/prisma/client' import { PrismaNeon } from '@prisma/adapter-neon' import dotenv from 'dotenv' @@ -241,7 +241,7 @@ npx prisma generate Import and instantiate Prisma Client with the Accelerate extension: ```typescript -import { PrismaClient } from "./generated/prisma"; +import { PrismaClient } from "../generated/prisma/client"; import { withAccelerate } from "@prisma/extension-accelerate"; const prisma = new PrismaClient().$extends(withAccelerate()); @@ -268,7 +268,7 @@ Usage of the new architecture requires the `driverAdapters` and `queryCompiler` ```prisma file=schema.prisma generator client { - provider = "prisma-client-js" // or `prisma-client` + provider = "prisma-client" previewFeatures = ["queryCompiler", "driverAdapters"] output = "../generated/prisma" } @@ -337,7 +337,7 @@ Finally, you need to instantiate Prisma Client which you can do using the driver ```typescript import { PrismaPg } from '@prisma/adapter-pg' -import { PrismaClient } from './generated/prisma' +import { PrismaClient } from '../generated/prisma/client' const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) @@ -345,16 +345,16 @@ const prisma = new PrismaClient({ adapter }) ```typescript -import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3'; -import { PrismaClient } from './generated/prisma'; +import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'; +import { PrismaClient } from '../generated/prisma/client'; -const adapter = new PrismaBetterSQLite3({ url: process.env.DATABASE_URL }) +const adapter = new PrismaBetterSqlite3({ url: process.env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }); ``` ```typescript -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../generated/prisma/client' import { PrismaD1 } from '@prisma/adapter-d1' export interface Env { @@ -378,7 +378,7 @@ export default { ```typescript import { PrismaMariaDb } from '@prisma/adapter-mariadb'; -import { PrismaClient } from './generated/prisma'; +import { PrismaClient } from '../generated/prisma/client'; const adapter = new PrismaMariaDb({ host: "localhost", @@ -391,7 +391,7 @@ const prisma = new PrismaClient({ adapter }); ```typescript import { PrismaPlanetScale } from '@prisma/adapter-planetscale' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../generated/prisma/client' import { fetch as undiciFetch } from 'undici' const adapter = new PrismaPlanetScale({ url: process.env.DATABASE_URL, fetch: undiciFetch }) @@ -401,7 +401,7 @@ const prisma = new PrismaClient({ adapter }) ```typescript import { PrismaMSSQL } from '@prisma/adapter-mssql'; -import { PrismaClient } from './generated/prisma'; +import { PrismaClient } from '../generated/prisma/client'; const sqlConfig = { user: process.env.DB_USER, @@ -426,7 +426,7 @@ const prisma = new PrismaClient({ adapter }); ```typescript import { PrismaPg } from '@prisma/adapter-pg' -import { PrismaClient } from './generated/prisma' +import { PrismaClient } from '../generated/prisma/client' const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) @@ -434,7 +434,7 @@ const prisma = new PrismaClient({ adapter }) ```typescript -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../generated/prisma/client' import { PrismaNeon } from '@prisma/adapter-neon' import dotenv from 'dotenv' diff --git a/content/200-orm/200-prisma-client/100-queries/030-crud.mdx b/content/200-orm/200-prisma-client/100-queries/030-crud.mdx index 09dba52754..81c9d1a780 100644 --- a/content/200-orm/200-prisma-client/100-queries/030-crud.mdx +++ b/content/200-orm/200-prisma-client/100-queries/030-crud.mdx @@ -32,11 +32,11 @@ All examples are based on the following schema: ```prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model ExtendedProfile { @@ -191,7 +191,7 @@ The user's `id` is auto-generated, and your schema determines [which fields are The following example produces an identical result, but creates a `UserCreateInput` variable named `user` _outside_ the context of the `create()` query. After completing a simple check ("Should posts be included in this `create()` query?"), the `user` variable is passed into the query: ```ts -import { PrismaClient, Prisma } from '@prisma/client' +import { PrismaClient, Prisma } from '../prisma/generated/client' const prisma = new PrismaClient() @@ -260,11 +260,11 @@ const createMany = await prisma.user.createMany({ - +:::warning Note `skipDuplicates` is not supported when using MongoDB, SQLServer, or SQLite. - +::: `createMany()` uses a single `INSERT INTO` statement with multiple values, which is generally more efficient than a separate `INSERT` per row: @@ -788,19 +788,19 @@ const upsertUser = await prisma.user.upsert({ - +:::info From version 4.6.0, Prisma Client carries out upserts with database native SQL commands where possible. [Learn more](/orm/reference/prisma-client-reference#database-upserts). - +::: Prisma Client does not have a `findOrCreate()` query. You can use `upsert()` as a workaround. To make `upsert()` behave like a `findOrCreate()` method, provide an empty `update` parameter to `upsert()`. - +:::warning A limitation to using `upsert()` as a workaround for `findOrCreate()` is that `upsert()` will only accept unique model fields in the `where` condition. So it's not possible to use `upsert()` to emulate `findOrCreate()` if the `where` condition contains non-unique fields. - +::: ### Update a number field @@ -867,11 +867,11 @@ Be aware that this query will fail if the user has any related records (such as ### Cascading deletes (deleting related records) - +:::warning In [2.26.0](https://github.com/prisma/prisma/releases/tag/2.26.0) and later it is possible to do cascading deletes using the **preview feature** [referential actions](/orm/prisma-schema/data-model/relations/referential-actions). - +::: The following query uses [`delete()`](/orm/reference/prisma-client-reference#delete) to delete a single `User` record: diff --git a/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx b/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx index 7a8fab2b4f..daffbf41a1 100644 --- a/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx +++ b/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx @@ -30,7 +30,8 @@ Because the `relationLoadStrategy` option is currently in Preview, you need to e ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["relationJoins"] } ``` diff --git a/content/200-orm/200-prisma-client/100-queries/050-filtering-and-sorting.mdx b/content/200-orm/200-prisma-client/100-queries/050-filtering-and-sorting.mdx index 813f6605b6..2953162267 100644 --- a/content/200-orm/200-prisma-client/100-queries/050-filtering-and-sorting.mdx +++ b/content/200-orm/200-prisma-client/100-queries/050-filtering-and-sorting.mdx @@ -11,11 +11,11 @@ Prisma Client supports [filtering](#filtering) with the `where` query option, an Prisma Client allows you to filter records on any combination of model fields, [including related models](#filter-on-relations), and supports a variety of [filter conditions](#filter-conditions-and-operators). - +:::warning Some filter conditions use the SQL operators `LIKE` and `ILIKE` which may cause unexpected behavior in your queries. Please refer to [our filtering FAQs](#filtering-faqs) for more information. - +::: The following query: @@ -394,7 +394,8 @@ This feature is further explain in [the PostgreSQL documentation](https://www.po ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["fullTextSearchPostgres"] } ``` diff --git a/content/200-orm/200-prisma-client/100-queries/056-aggregation-grouping-summarizing.mdx b/content/200-orm/200-prisma-client/100-queries/056-aggregation-grouping-summarizing.mdx index c0695ef1ab..76a8e709af 100644 --- a/content/200-orm/200-prisma-client/100-queries/056-aggregation-grouping-summarizing.mdx +++ b/content/200-orm/200-prisma-client/100-queries/056-aggregation-grouping-summarizing.mdx @@ -350,11 +350,11 @@ const userCount = await prisma.user.count() ### Count relations - +:::info This feature is generally available in version [3.0.1](https://github.com/prisma/prisma/releases/3.0.1) and later. To use this feature in versions before 3.0.1 the [Preview feature](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `selectRelationCount` will need to be enabled. - +::: To return a count of relations (for example, a user's post count), use the `_count` parameter with a nested `select` as shown: @@ -491,11 +491,11 @@ const usersWithCount = await prisma.user.findMany({ #### Filter the relation count - +:::info This feature is generally available in version `4.16.0` and later. To use this feature in versions [`4.3.0`](https://github.com/prisma/prisma/releases/tag/4.3.0) to [`4.15.0`](https://github.com/prisma/prisma/releases/tag/4.15.0) the [Preview feature](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `filteredRelationCount` will need to be enabled. - +::: Use `where` to filter the fields returned by the `_count` output type. You can do this on [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields), [relation fields](/orm/prisma-schema/data-model/models#relation-fields) and fields of a [composite type](/orm/prisma-schema/data-model/models#defining-composite-types). diff --git a/content/200-orm/200-prisma-client/100-queries/058-transactions.mdx b/content/200-orm/200-prisma-client/100-queries/058-transactions.mdx index 63b93505b5..7f717070a9 100644 --- a/content/200-orm/200-prisma-client/100-queries/058-transactions.mdx +++ b/content/200-orm/200-prisma-client/100-queries/058-transactions.mdx @@ -13,11 +13,11 @@ A database transaction refers to a sequence of read/write operations that are _g ## Transactions overview - +:::info Before Prisma ORM version 4.4.0, you could not set isolation levels on transactions. The isolation level in your database configuration always applied. - +::: Developers take advantage of the safety guarantees provided by the database by wrapping the operations in a transaction. These guarantees are often summarized using the ACID acronym: @@ -199,23 +199,23 @@ await prisma.$transaction( Sometimes you need more control over what queries execute within a transaction. Interactive transactions are meant to provide you with an escape hatch. - +:::info Interactive transactions have been generally available from version 4.7.0. If you use interactive transactions in preview from version 2.29.0 to 4.6.1 (inclusive), you need to add the `interactiveTransactions` preview feature to the generator block of your Prisma schema. - +::: To use interactive transactions, you can pass an async function into [`$transaction`](#transaction-api). The first argument passed into this async function is an instance of Prisma Client. Below, we will call this instance `tx`. Any Prisma Client call invoked on this `tx` instance is encapsulated into the transaction. - +:::warning **Use interactive transactions with caution**. Keeping transactions open for a long time hurts database performance and can even cause deadlocks. Try to avoid performing network requests and executing slow queries inside your transaction functions. We recommend you get in and out as quick as possible! - +::: #### Example @@ -235,7 +235,7 @@ In the example below, Alice and Bob each have $100 in their account. If they try Alice is expected to be able to make 1 transfer for $100 while the other transfer would be rejected. This would result in Alice having $0 and Bob having $200. ```tsx -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() function transfer(from: string, to: string, amount: number) { @@ -336,21 +336,21 @@ const prisma = new PrismaClient({ ### Transaction isolation level - +:::info This feature is not available on MongoDB, because MongoDB does not support isolation levels. - +::: You can set the transaction [isolation level](https://www.prisma.io/dataguide/intro/database-glossary#isolation-levels) for transactions. - +:::info This is available in the following Prisma ORM versions for interactive transactions from version 4.2.0, for sequential operations from version 4.4.0. In versions before 4.2.0 (for interactive transactions), or 4.4.0 (for sequential operations), you cannot configure the transaction isolation level at a Prisma ORM level. Prisma ORM does not explicitly set the isolation level, so the [isolation level configured in your database](#database-specific-information-on-isolation-levels) is used. - +::: #### Set the isolation level @@ -428,12 +428,12 @@ CockroachDB and SQLite only support the `Serializable` isolation level. ### Transaction timing issues - +:::info - The solution in this section does not apply to MongoDB, because MongoDB does not support [isolation levels](https://www.prisma.io/dataguide/intro/database-glossary#isolation-levels). - The timing issues discussed in this section do not apply to CockroachDB and SQLite, because these databases only support the highest `Serializable` isolation level. - +::: When two or more transactions run concurrently in certain [isolation levels](https://www.prisma.io/dataguide/intro/database-glossary#isolation-levels), timing issues can cause write conflicts or deadlocks, such as the violation of unique constraints. For example, consider the following sequence of events where Transaction A and Transaction B both attempt to execute a `deleteMany` and a `createMany` operation: @@ -453,7 +453,7 @@ To avoid transaction write conflicts and deadlocks on a transaction: 2. In your application code, add a retry around your transaction to handle any P2034 errors, as shown in this example: ```ts - import { Prisma, PrismaClient } from '@prisma/client' + import { Prisma, PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() async function main() { @@ -1170,13 +1170,13 @@ If a ❌ conflict occurs (someone else has changed the record since you read it) This section describes how to build your own optimistic concurrency control. See also: Plans for [application-level optimistic concurrency control on GitHub](https://github.com/prisma/prisma/issues/4988) - +:::info - If you use version 4.4.0 or earlier, you cannot use optimistic concurrency control on `update` operations, because you cannot filter on non-unique fields. The `version` field you need to use with optimistic concurrency control is a non-unique field. - Since version 5.0.0 you are able to [filter on non-unique fields in `update` operations](/orm/reference/prisma-client-reference#filter-on-non-unique-fields-with-userwhereuniqueinput) so that optimistic concurrency control is being used. The feature was also available via the Preview flag `extendedWhereUnique` from versions 4.5.0 to 4.16.2. - +::: #### When to use optimistic concurrency control @@ -1324,7 +1324,7 @@ In the example below, Alice and Bob each have $100 in their account. If they try The expected outcome would be for Alice to make 1 transfer for $100 and the other transfer would be rejected. This would result in Alice having $0 and Bob having $200. ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() async function transfer(from: string, to: string, amount: number) { @@ -1378,14 +1378,14 @@ If the application encounters an error along the way, the async function will th You can learn more about interactive transactions in this [section](#interactive-transactions). - +:::warning **Use interactive transactions with caution**. Keeping transactions open for a long time hurts database performance and can even cause deadlocks. Try to avoid performing network requests and executing slow queries inside your transaction functions. We recommend you get in and out as quick as possible! - +::: ## Conclusion diff --git a/content/200-orm/200-prisma-client/100-queries/060-full-text-search.mdx b/content/200-orm/200-prisma-client/100-queries/060-full-text-search.mdx index ef473c95b8..814a66938a 100644 --- a/content/200-orm/200-prisma-client/100-queries/060-full-text-search.mdx +++ b/content/200-orm/200-prisma-client/100-queries/060-full-text-search.mdx @@ -21,7 +21,8 @@ The full-text search API is currently a Preview feature. To enable this feature, ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["fullTextSearchPostgres"] } ``` @@ -165,11 +166,11 @@ For the full range of supported operations, see the [MySQL full text search docu ## Sorting results by `_relevance` - +:::warning Sorting by relevance is only available for PostgreSQL and MySQL. - +::: In addition to [Prisma Client's default `orderBy` behavior](/orm/reference/prisma-client-reference#orderby), full-text search also adds sorting by relevance to a given string or strings. As an example, if you wanted to order posts by their relevance to the term `'database'` in their title, you could use the following: @@ -199,7 +200,8 @@ In the following example, one full text index is added to the `content` field of ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model Blog { diff --git a/content/200-orm/200-prisma-client/100-queries/061-custom-validation.mdx b/content/200-orm/200-prisma-client/100-queries/061-custom-validation.mdx index ecc05879aa..959781b8db 100644 --- a/content/200-orm/200-prisma-client/100-queries/061-custom-validation.mdx +++ b/content/200-orm/200-prisma-client/100-queries/061-custom-validation.mdx @@ -19,18 +19,18 @@ You can use any validation library you'd like. The Node.js ecosystem offers a nu This example adds runtime validation when creating and updating values using a Zod schema to check that the data passed to Prisma Client is valid. - +:::warning Query extensions do not currently work for nested operations. In this example, validations are only run on the top level data object passed to methods such as `prisma.product.create()`. Validations implemented this way do not automatically run for [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes). - +::: ```ts copy -import { PrismaClient, Prisma } from '@prisma/client' +import { PrismaClient, Prisma } from '../prisma/generated/client' import { z } from 'zod' /** @@ -114,11 +114,11 @@ main() ```prisma copy datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model Product { diff --git a/content/200-orm/200-prisma-client/100-queries/062-computed-fields.mdx b/content/200-orm/200-prisma-client/100-queries/062-computed-fields.mdx index a923a0aff8..d1f525afb8 100644 --- a/content/200-orm/200-prisma-client/100-queries/062-computed-fields.mdx +++ b/content/200-orm/200-prisma-client/100-queries/062-computed-fields.mdx @@ -19,7 +19,7 @@ The following example illustrates how to create a [Prisma Client extension](/orm ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient().$extends({ result: { @@ -68,11 +68,11 @@ main() ```prisma copy datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model User { diff --git a/content/200-orm/200-prisma-client/100-queries/064-custom-models.mdx b/content/200-orm/200-prisma-client/100-queries/064-custom-models.mdx index 4d5a576e1f..a51ed1c994 100644 --- a/content/200-orm/200-prisma-client/100-queries/064-custom-models.mdx +++ b/content/200-orm/200-prisma-client/100-queries/064-custom-models.mdx @@ -24,7 +24,7 @@ The following example demonstrates how to create a Prisma Client extension that ```tsx import bcrypt from 'bcryptjs' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient().$extends({ model: { @@ -67,11 +67,11 @@ async function main() { ```prisma file="prisma/schema.prisma" copy datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } model User { diff --git a/content/200-orm/200-prisma-client/100-queries/070-case-sensitivity.mdx b/content/200-orm/200-prisma-client/100-queries/070-case-sensitivity.mdx index c1bc22a362..8a7ce985d0 100644 --- a/content/200-orm/200-prisma-client/100-queries/070-case-sensitivity.mdx +++ b/content/200-orm/200-prisma-client/100-queries/070-case-sensitivity.mdx @@ -24,11 +24,11 @@ If you use the MongoDB connector, [Prisma Client](/orm/prisma-client/queries) us ## Database collation and case sensitivity - +:::info In the context of Prisma Client, the following section refers to relational database connectors only. - +::: Collation specifies how data is **sorted and compared** in a database, which includes casing. Collation is something you choose when you set up a database. diff --git a/content/200-orm/200-prisma-client/150-using-raw-sql/100-typedsql.mdx b/content/200-orm/200-prisma-client/150-using-raw-sql/100-typedsql.mdx index 5f3b7cb471..ab961eb88d 100644 --- a/content/200-orm/200-prisma-client/150-using-raw-sql/100-typedsql.mdx +++ b/content/200-orm/200-prisma-client/150-using-raw-sql/100-typedsql.mdx @@ -42,6 +42,7 @@ To start using TypedSQL in your Prisma project, follow these steps: Starting with Prisma 6.12.0, you can configure a custom location for your SQL files using the Prisma config file. Create a `prisma.config.ts` file in your project root and specify the `typedSql.path` option: ```typescript title="prisma.config.ts" + import 'dotenv/config' import { defineConfig } from 'prisma/config' export default defineConfig({ diff --git a/content/200-orm/200-prisma-client/150-using-raw-sql/200-raw-queries.mdx b/content/200-orm/200-prisma-client/150-using-raw-sql/200-raw-queries.mdx index e0ff6126d1..557e2b0b73 100644 --- a/content/200-orm/200-prisma-client/150-using-raw-sql/200-raw-queries.mdx +++ b/content/200-orm/200-prisma-client/150-using-raw-sql/200-raw-queries.mdx @@ -59,11 +59,11 @@ const email = "emelie@prisma.io"; const result = await prisma.$queryRaw(Prisma.sql`SELECT * FROM User WHERE email = ${email}`); ``` - +:::warning If you use string building to incorporate untrusted input into queries passed to this method, then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion. The preferred mechanism would be to include the text of the query at the point that you run this method. For more information on this risk and also examples of how to prevent it, see the [SQL injection prevention](#sql-injection-prevention) section below. - +::: #### Considerations @@ -182,13 +182,13 @@ Note that if you use `$queryRawUnsafe` in conjunction with user inputs, you risk The `$queryRawUnsafe()` method allows you to pass a raw string (or template string) to the database. - +:::warning If you use this method with user inputs (in other words, `SELECT * FROM table WHERE columnx = ${userInput}`), then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion.

Wherever possible you should use the `$queryRaw` method instead. When used correctly `$queryRaw` method is significantly safer but note that the `$queryRaw` method can also be made vulnerable in certain circumstances. For more information, see the [SQL injection prevention](#sql-injection-prevention) section below. -
+::: The following query returns all fields for each record in the `User` table: @@ -234,11 +234,11 @@ const result: number = await prisma.$executeRaw`UPDATE User SET active = ${active} WHERE emailValidated = ${emailValidated};`; ``` - +:::warning If you use string building to incorporate untrusted input into queries passed to this method, then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion. The preferred mechanism would be to include the text of the query at the point that you run this method. For more information on this risk and also examples of how to prevent it, see the [SQL injection prevention](#sql-injection-prevention) section below. - +::: #### Considerations @@ -292,13 +292,13 @@ $executeRaw(query: TemplateStringsArray | Prisma.Sql, ...values: an The `$executeRawUnsafe()` method allows you to pass a raw string (or template string) to the database. Like `$executeRaw`, it does **not** return database records, but returns the number of rows affected. - +:::warning If you use this method with user inputs (in other words, `SELECT * FROM table WHERE columnx = ${userInput}`), then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion.

Wherever possible you should use the `$executeRaw` method instead. When used correctly `$executeRaw` method is significantly safer but note that the `$executeRaw` method can also be made vulnerable in certain circumstances. For more information, see the [SQL injection prevention](#sql-injection-prevention) section below. -
+::: The following example uses a template string to update records in the database. It then returns a count of the number of records that were updated: @@ -333,14 +333,14 @@ $executeRawUnsafe(query: string, ...values: any[]): PrismaPromise +:::info **Feature availability:** - In v3.14.x and v3.15.x, raw query type mapping was available with the preview feature `improvedQueryRaw`. We made raw query type mapping [Generally Available](/orm/more/releases#generally-available-ga) in version 4.0.0, so you do not need to use `improvedQueryRaw` in version 4.0.0 or later. - Before version 4.0.0, raw query type mapping was not available for SQLite. - +::: As an example, take a raw query that selects columns with `BigInt`, `Bytes`, `Decimal` and `Date` types from a table: diff --git a/content/200-orm/200-prisma-client/150-using-raw-sql/300-safeql.mdx b/content/200-orm/200-prisma-client/150-using-raw-sql/300-safeql.mdx index a899de290a..8ea9723ded 100644 --- a/content/200-orm/200-prisma-client/150-using-raw-sql/300-safeql.mdx +++ b/content/200-orm/200-prisma-client/150-using-raw-sql/300-safeql.mdx @@ -44,20 +44,20 @@ If you haven't already, enable the `postgresqlExtensions` Preview feature and ad ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" //add-next-line previewFeatures = ["postgresqlExtensions"] } datasource db { provider = "postgresql" - url = env("DATABASE_URL") //add-next-line extensions = [postgis] } ``` - +:::warning If you are not using a hosted database provider, you will likely need to install the `postgis` extension. Refer to [PostGIS's docs](http://postgis.net/documentation/getting_started/#installing-postgis) to learn more about how to get started with PostGIS. If you're using Docker Compose, you can use the following snippet to set up a PostgreSQL database that has PostGIS installed: @@ -78,7 +78,7 @@ volumes: db_data: ``` - +::: Next, create a migration and execute a migration to enable the extension: diff --git a/content/200-orm/200-prisma-client/200-special-fields-and-types/057-composite-types.mdx b/content/200-orm/200-prisma-client/200-special-fields-and-types/057-composite-types.mdx index fb67569058..0d6b0b6c56 100644 --- a/content/200-orm/200-prisma-client/200-special-fields-and-types/057-composite-types.mdx +++ b/content/200-orm/200-prisma-client/200-special-fields-and-types/057-composite-types.mdx @@ -7,11 +7,11 @@ tocDepth: 3 - +:::warning Composite types are only available with MongoDB. - +::: [Composite types](/orm/prisma-schema/data-model/models#defining-composite-types), known as [embedded documents](https://www.mongodb.com/docs/manual/data-modeling/#embedded-data) in MongoDB, allow you to embed records within other records. @@ -322,11 +322,11 @@ const product = prisma.product.findFirst({ ## Creating records with composite types using `create` and `createMany` - +:::info -When you create a record with a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types). +When you create a record with a composite type that has a unique constraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types). - +::: Composite types can be created within a `create` or `createMany` method using the `set` operation. For example, you can use `set` within `create` to create an `Address` composite type inside an `Order`: @@ -462,11 +462,11 @@ const product = await prisma.product.createMany({ ## Changing composite types within `update` and `updateMany` - +:::info -When you update a record with a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types). +When you update a record with a composite type that has a unique constraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types). - +::: Composite types can be set, updated or removed within an `update` or `updateMany` method. The following section describes the operations available for updating a single type or multiple types at once, and gives examples of each. @@ -629,11 +629,11 @@ const product = prisma.product.update({ ## Upserting composite types with `upsert` - +:::info -When you create or update the values in a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types). +When you create or update the values in a composite type that has a unique constraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types). - +::: To create or update a composite type, use the `upsert` method. You can use the same composite operations as the `create` and `update` methods above. diff --git a/content/200-orm/200-prisma-client/200-special-fields-and-types/080-null-and-undefined.mdx b/content/200-orm/200-prisma-client/200-special-fields-and-types/080-null-and-undefined.mdx index 6af305057d..8fa599d870 100644 --- a/content/200-orm/200-prisma-client/200-special-fields-and-types/080-null-and-undefined.mdx +++ b/content/200-orm/200-prisma-client/200-special-fields-and-types/080-null-and-undefined.mdx @@ -23,7 +23,8 @@ To enable this feature, add the following to your Prisma schema: ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["strictUndefinedChecks"] } ``` @@ -234,11 +235,11 @@ const users = await prisma.user.findMany() This query will select every row from the `User` table. - +:::info -**Note**: Using `undefined` as the value of any key in a Prisma Client query's parameter object will cause Prisma ORM to act as if that key was not provided at all. +Using `undefined` as the value of any key in a Prisma Client query's parameter object will cause Prisma ORM to act as if that key was not provided at all. - +::: Although this section's examples focused on the `findMany` function, the same concepts apply to any function that can affect multiple records, such as `updateMany` and `deleteMany`. @@ -246,11 +247,11 @@ Although this section's examples focused on the `findMany` function, the same co This section will cover how `undefined` and `null` values affect the behavior of queries that interact with or create a single record in a database. - +:::warning -**Note**: `null` is not a valid filter value in a `findUnique()` query. +`null` is not a valid filter value in a `findUnique()` query. - +::: The query behavior when using `null` and `undefined` in the filter criteria of a query that affects a single record is very similar to the behaviors described in the previous section. diff --git a/content/200-orm/200-prisma-client/200-special-fields-and-types/100-working-with-json-fields.mdx b/content/200-orm/200-prisma-client/200-special-fields-and-types/100-working-with-json-fields.mdx index ad796c8c04..131008b323 100644 --- a/content/200-orm/200-prisma-client/200-special-fields-and-types/100-working-with-json-fields.mdx +++ b/content/200-orm/200-prisma-client/200-special-fields-and-types/100-working-with-json-fields.mdx @@ -142,13 +142,13 @@ const getUsers = await prisma.user.findMany({ You can also filter rows by the data inside a `Json` field. We call this **advanced `Json` filtering**. This functionality is supported by [PostgreSQL](/orm/overview/databases/postgresql) and [MySQL](/orm/overview/databases/mysql) only with [different syntaxes for the `path` option](#path-syntax-depending-on-database). - +:::warning PostgreSQL does not support [filtering on object key values in arrays](#filtering-on-object-key-value-inside-array). - +::: - +:::info The availability of advanced `Json` filtering depends on your Prisma version: @@ -156,7 +156,7 @@ The availability of advanced `Json` filtering depends on your Prisma version: - From v2.23.0, but before v4.0.0: advanced `Json` filtering is a [preview feature](/orm/reference/preview-features/client-preview-features). Add `previewFeatures = ["filterJson"]` to your schema. [Learn more](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature). - Before v2.23.0: you can [filter on the exact `Json` field value](#filter-on-exact-field-value), but you cannot use the other features described in this section. - +::: ### `path` syntax depending on database @@ -430,11 +430,11 @@ const getUsers = await prisma.user.findMany({ }) ``` - +:::info -**Note**: In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value. +In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value. - +:::
@@ -488,11 +488,11 @@ const getUsers = await prisma.user.findMany({ }) ``` - +:::info -**Note**: In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value. +In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value. - +::: @@ -654,11 +654,11 @@ const getUsers = await prisma.user.findMany({ Depending on your provider, you can filter on the key value of an object inside an array. - +:::warning Filtering on object key values within an array is **only** supported by the [MySQL database connector](/orm/overview/databases/mysql). However, you can still [filter on the presence of entire JSON objects](#json-object-arrays). - +::: In the following example, the value of `extendedPetsData` is an array of objects with a nested `insurances` array, which contains two objects: @@ -886,19 +886,19 @@ To differentiate between these possibilities, we've introduced three _null enums - `DbNull`: Represents the `NULL` value in the database. - `AnyNull`: Represents both `null` JSON values and `NULL` database values. (Only when filtering) - +:::info From v4.0.0, `JsonNull`, `DbNull`, and `AnyNull` are objects. Before v4.0.0, they were strings. - +::: - +:::info - When filtering using any of the _null enums_ you can not use a shorthand and leave the `equals` operator off. - These _null enums_ do not apply to MongoDB because there the difference between a JSON `null` and a database `NULL` does not exist. - The _null enums_ do not apply to the `array_contains` operator in all databases because there can only be a JSON `null` within a JSON array. Since there cannot be a database `NULL` within a JSON array, `{ array_contains: null }` is not ambiguous. - +::: For example: @@ -968,11 +968,11 @@ prisma.log.findMany({ }) ``` - +:::info These _null enums_ do not apply to MongoDB because MongoDB does not differentiate between a JSON `null` and a database `NULL`. They also do not apply to the `array_contains` operator in all databases because there can only be a JSON `null` within a JSON array. Since there cannot be a database `NULL` within a JSON array, `{ array_contains: null }` is not ambiguous. - +::: ## Typed `Json` Fields @@ -986,7 +986,8 @@ Prisma's `Json` fields are untyped by default. To add strong typing, you can use ```prisma file=schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } generator json { diff --git a/content/200-orm/200-prisma-client/200-special-fields-and-types/200-working-with-scalar-lists-arrays.mdx b/content/200-orm/200-prisma-client/200-special-fields-and-types/200-working-with-scalar-lists-arrays.mdx index 6682d03c9d..ec198230d8 100644 --- a/content/200-orm/200-prisma-client/200-special-fields-and-types/200-working-with-scalar-lists-arrays.mdx +++ b/content/200-orm/200-prisma-client/200-special-fields-and-types/200-working-with-scalar-lists-arrays.mdx @@ -59,12 +59,12 @@ const createdUser = await prisma.user.create({ ## Unsetting the value of a scalar list - +:::warning This method is available on MongoDB only in versions [3.11.1](https://github.com/prisma/prisma/releases/tag/3.11.1) and later. - +::: The following example demonstrates how to [`unset`](/orm/reference/prisma-client-reference#unset) the value of a scalar list (`coinflips`): @@ -83,7 +83,7 @@ Unlike `set: null`, `unset` removes the list entirely. ## Adding items to a scalar list - +:::warning Available for: @@ -91,7 +91,7 @@ Available for: - CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later - MongoDB in versions [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0) and later - +::: Use the [`push`](/orm/reference/prisma-client-reference#push) method to add a single value to a scalar list: @@ -137,7 +137,7 @@ if (user) { ## Filtering scalar lists - +:::warning Available for: @@ -145,7 +145,7 @@ Available for: - CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later - MongoDB in versions [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0) and later - +::: Use [scalar list filters](/orm/reference/prisma-client-reference#scalar-list-filters) to filter for records with scalar lists that match a specific condition. The following example returns all posts where the tags list includes `databases` _and_ `typescript`: @@ -161,14 +161,14 @@ const posts = await prisma.post.findMany({ ### `NULL` values in arrays - +:::warning This section applies to: - PostgreSQL in versions [2.15.0](https://github.com/prisma/prisma/releases/tag/2.15.0) and later - CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later - +::: When using scalar list filters with a relational database connector, array fields with a `NULL` value are not considered by the following conditions: diff --git a/content/200-orm/200-prisma-client/200-special-fields-and-types/300-working-with-composite-ids-and-constraints.mdx b/content/200-orm/200-prisma-client/200-special-fields-and-types/300-working-with-composite-ids-and-constraints.mdx index d687f60a12..568682f30a 100644 --- a/content/200-orm/200-prisma-client/200-special-fields-and-types/300-working-with-composite-ids-and-constraints.mdx +++ b/content/200-orm/200-prisma-client/200-special-fields-and-types/300-working-with-composite-ids-and-constraints.mdx @@ -9,12 +9,12 @@ tocDepth: 2 Composite IDs and compound unique constraints can be defined in your Prisma schema using the [`@@id`](/orm/reference/prisma-schema-reference#id-1) and [`@@unique`](/orm/reference/prisma-schema-reference#unique-1) attributes. - +:::warning **MongoDB does not support `@@id`**
MongoDB does not support composite IDs, which means you cannot identify a model with a `@@id` attribute. -
+::: A composite ID or compound unique constraint uses the combined values of two fields as a primary key or identifier in your database table. In the following example, the `postId` field and `userId` field are used as a composite ID for a `Like` table: @@ -101,11 +101,11 @@ const like = await prisma.like.findUnique({ }) ``` - +:::info Note composite ID and compound unique constraint keys are only available as filter options for _unique_ queries such as `findUnique()` and `findUniqueOrThrow`. See the [section](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints#where-you-can-use-compound-ids-and-unique-constraints) above for a list of places these fields may be used. - +::: ## Deleting records by a compound ID or unique constraint diff --git a/content/200-orm/200-prisma-client/300-client-extensions/100-model.mdx b/content/200-orm/200-prisma-client/300-client-extensions/100-model.mdx index d293617e46..4af89011b1 100644 --- a/content/200-orm/200-prisma-client/300-client-extensions/100-model.mdx +++ b/content/200-orm/200-prisma-client/300-client-extensions/100-model.mdx @@ -7,11 +7,11 @@ toc_max_heading_level: 4 - +:::info Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. - +::: You can use the `model` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to add custom methods to your models. @@ -134,11 +134,11 @@ const prisma = new PrismaClient().$extends({ ## Get the current model name at runtime - +:::info This feature is available from version 4.9.0. - +::: You can get the name of the current model at runtime with `Prisma.getExtensionContext(this).$name`. You might use this to write out the model name to a log, to send the name to another service, or to branch your code based on the model. diff --git a/content/200-orm/200-prisma-client/300-client-extensions/110-client.mdx b/content/200-orm/200-prisma-client/300-client-extensions/110-client.mdx index 5aad99108e..5b1672e143 100644 --- a/content/200-orm/200-prisma-client/300-client-extensions/110-client.mdx +++ b/content/200-orm/200-prisma-client/300-client-extensions/110-client.mdx @@ -7,11 +7,11 @@ toc_max_heading_level: 4 - +:::info Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. - +::: You can use the `client` [Prisma Client extensions](/orm/prisma-client/client-extensions) component to add top-level methods to Prisma Client. @@ -36,11 +36,11 @@ The following example uses the `client` component to add two methods to Prisma C - `$log` outputs a message. - `$totalQueries` returns the number of queries executed by the current client instance. It uses the [metrics](/orm/prisma-client/observability-and-logging/metrics) feature to collect this information. - +:::info To use metrics in your project, you must enable the `metrics` feature flag in the `generator` block of your `schema.prisma` file. [Learn more](/orm/prisma-client/observability-and-logging/metrics#2-enable-the-feature-flag-in-the-prisma-schema-file). - +::: ```ts const prisma = new PrismaClient().$extends({ diff --git a/content/200-orm/200-prisma-client/300-client-extensions/120-query.mdx b/content/200-orm/200-prisma-client/300-client-extensions/120-query.mdx index 9c408e7620..26bb67e1b4 100644 --- a/content/200-orm/200-prisma-client/300-client-extensions/120-query.mdx +++ b/content/200-orm/200-prisma-client/300-client-extensions/120-query.mdx @@ -7,11 +7,11 @@ toc_max_heading_level: 4 - +:::info Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. - +::: You can use the `query` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to hook into the query life-cycle and modify an incoming query or its result. @@ -254,11 +254,11 @@ const prisma = new PrismaClient().$extends({ }) ``` - +:::info We include the above example to show that this is possible. However, for performance reasons we recommend that you use the [`result` component type](/orm/prisma-client/client-extensions/result) to override existing fields. The `result` component type usually gives better performance in this situation because it computes only on access. The `query` component type computes after query execution. - +::: ## Wrap a query into a batch transaction diff --git a/content/200-orm/200-prisma-client/300-client-extensions/130-result.mdx b/content/200-orm/200-prisma-client/300-client-extensions/130-result.mdx index a413790ec3..66eedda8c7 100644 --- a/content/200-orm/200-prisma-client/300-client-extensions/130-result.mdx +++ b/content/200-orm/200-prisma-client/300-client-extensions/130-result.mdx @@ -7,11 +7,11 @@ toc_max_heading_level: 4 - +:::info Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. - +::: You can use the `result` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to add custom fields and methods to query results. diff --git a/content/200-orm/200-prisma-client/300-client-extensions/index.mdx b/content/200-orm/200-prisma-client/300-client-extensions/index.mdx index d0bb657074..50e60c8a44 100644 --- a/content/200-orm/200-prisma-client/300-client-extensions/index.mdx +++ b/content/200-orm/200-prisma-client/300-client-extensions/index.mdx @@ -7,11 +7,11 @@ toc_max_heading_level: 4 - +:::info Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. - +::: You can use Prisma Client extensions to add functionality to your models, result objects, and queries, or to add client-level methods. diff --git a/content/200-orm/200-prisma-client/400-type-safety/830-prisma-type-system.mdx b/content/200-orm/200-prisma-client/400-type-safety/830-prisma-type-system.mdx index 17a6241106..b7d4854e2b 100644 --- a/content/200-orm/200-prisma-client/400-type-safety/830-prisma-type-system.mdx +++ b/content/200-orm/200-prisma-client/400-type-safety/830-prisma-type-system.mdx @@ -17,7 +17,6 @@ Prisma ORM uses _types_ to define the kind of data that a field can hold. To mak ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model Post { diff --git a/content/200-orm/200-prisma-client/400-type-safety/index.mdx b/content/200-orm/200-prisma-client/400-type-safety/index.mdx index caa214ec6e..9271036924 100644 --- a/content/200-orm/200-prisma-client/400-type-safety/index.mdx +++ b/content/200-orm/200-prisma-client/400-type-safety/index.mdx @@ -233,11 +233,11 @@ We recommend using the "safe" `Input` types whenever possible. ## Type utilities - +:::info This feature is available from Prisma ORM version 4.9.0 upwards. - +::: To help you create highly type-safe applications, Prisma Client provides a set of type utilities that tap into input and output types. These types are fully dynamic, which means that they adapt to any given model and schema. You can use them to improve the auto-completion and developer experience of your projects. diff --git a/content/200-orm/200-prisma-client/450-testing/100-unit-testing.mdx b/content/200-orm/200-prisma-client/450-testing/100-unit-testing.mdx index 931d78b14c..1d8e5060bf 100644 --- a/content/200-orm/200-prisma-client/450-testing/100-unit-testing.mdx +++ b/content/200-orm/200-prisma-client/450-testing/100-unit-testing.mdx @@ -37,11 +37,11 @@ This guide will cover two approaches to mocking Prisma Client, a singleton insta npm install jest-mock-extended@2.0.4 --save-dev ``` - +:::danger At the time of writing, this guide uses `jest-mock-extended` version `^2.0.4`. - +::: ### Singleton diff --git a/content/200-orm/200-prisma-client/450-testing/150-integration-testing.mdx b/content/200-orm/200-prisma-client/450-testing/150-integration-testing.mdx index 25dcff2e82..de0d154efe 100644 --- a/content/200-orm/200-prisma-client/450-testing/150-integration-testing.mdx +++ b/content/200-orm/200-prisma-client/450-testing/150-integration-testing.mdx @@ -122,11 +122,11 @@ The `docker-compose.yml` file defines the following: DATABASE_URL="postgresql://prisma:prisma@localhost:5433/tests" ``` - +:::info The above `.env.test` file is used as part of a multiple `.env` file setup. Checkout the [using multiple .env files.](/orm/more/development-environment/environment-variables) section to learn more about setting up your project with multiple `.env` files - +::: 3. To create the container in a detached state so that you can continue to use the terminal tab, run the following command: diff --git a/content/200-orm/200-prisma-client/500-deployment/201-serverless/300-deploy-to-vercel.mdx b/content/200-orm/200-prisma-client/500-deployment/201-serverless/300-deploy-to-vercel.mdx index f5717fed5f..baedae6a6b 100644 --- a/content/200-orm/200-prisma-client/500-deployment/201-serverless/300-deploy-to-vercel.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/201-serverless/300-deploy-to-vercel.mdx @@ -148,7 +148,7 @@ Use `attachDatabasePool` together with [Prisma's driver adapters](/orm/overview/ import { Pool } from 'pg' import { attachDatabasePool } from '@vercel/functions' import { PrismaPg } from '@prisma/adapter-pg' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' const pool = new Pool({ connectionString: process.env.POSTGRES_URL }) diff --git a/content/200-orm/200-prisma-client/500-deployment/201-serverless/400-deploy-to-aws-lambda.mdx b/content/200-orm/200-prisma-client/500-deployment/201-serverless/400-deploy-to-aws-lambda.mdx index fc386c5aa4..0d17dffc3a 100644 --- a/content/200-orm/200-prisma-client/500-deployment/201-serverless/400-deploy-to-aws-lambda.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/201-serverless/400-deploy-to-aws-lambda.mdx @@ -357,7 +357,7 @@ While SST supports `.env` files, [it is not recommended](https://v2.sst.dev/conf The SST guide [available here](https://v2.sst.dev/config#overview) is a step-by-step guide to get started with `Config`. Assuming you have created a new secret called `DATABASE_URL` and have [bound that secret to your app](https://v2.sst.dev/config#bind-the-config), you can set up `PrismaClient` with the following: ```ts file=prisma.ts showLineNumbers -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' import { Config } from 'sst/node/config' const globalForPrisma = global as unknown as { prisma: PrismaClient } diff --git a/content/200-orm/200-prisma-client/500-deployment/301-edge/450-deploy-to-cloudflare.mdx b/content/200-orm/200-prisma-client/500-deployment/301-edge/450-deploy-to-cloudflare.mdx index c12f9ddf1e..9ebbb0b4ac 100644 --- a/content/200-orm/200-prisma-client/500-deployment/301-edge/450-deploy-to-cloudflare.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/301-edge/450-deploy-to-cloudflare.mdx @@ -73,7 +73,7 @@ npm i @prisma/extension-accelerate And extend `PrismaClient` with the extension in your application code: ```typescript -import { PrismaClient } from "@prisma/client/edge"; +import { PrismaClient } from "./generated/client"; import { withAccelerate } from "@prisma/extension-accelerate"; export interface Env { @@ -123,15 +123,26 @@ If your application uses PostgreSQL, we recommend using [Prisma Postgres](/postg ### Setting your database connection URL as an environment variable -First, ensure that the `DATABASE_URL` is set as the `url` of the `datasource` in your Prisma schema: +First, ensure that your `datasource` block in your Prisma schema is configured correctly. Database connection URLs are configured in `prisma.config.ts`: ```prisma datasource db { provider = "postgresql" // this might also be `mysql` or another value depending on your database - url = env("DATABASE_URL") } ``` +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + #### Development When using your Worker in **development**, you can configure your database connection via the [`.dev.vars` file](https://developers.cloudflare.com/workers/configuration/secrets/#local-development-with-secrets) locally. @@ -253,19 +264,31 @@ If you don't have a project to deploy, follow the instructions in the [Prerequis ::: -First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `DATABASE_URL` environment variable: +First, ensure that the database connection is configured properly. Database connection URLs are configured in `prisma.config.ts`: ```prisma file=schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + Next, you need to set the `DATABASE_URL` environment variable to the value of your database connection string. You'll do this in a file called `.dev.vars` used by Cloudflare: ```bash file=.dev.vars @@ -328,7 +351,7 @@ npm run env -- npx prisma migrate dev --name init Here is a sample code snippet that you can use to instantiate `PrismaClient` and send a query to your database: ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' import { PrismaPg } from '@prisma/adapter-pg' export default { @@ -412,16 +435,28 @@ First, ensure that the database connection is configured properly. In your Prism ```prisma file=schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "mysql" - url = env("DATABASE_URL") relationMode = "prisma" // required for PlanetScale (as by default foreign keys are disabled) } ``` +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + Next, you need to set the `DATABASE_URL` environment variable to the value of your database connection string. You'll do this in a file called `.dev.vars` used by Cloudflare: ```bash file=.dev.vars @@ -470,7 +505,7 @@ npm run env -- npx prisma db push Here is a sample code snippet that you can use to instantiate `PrismaClient` and send a query to your database: ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' import { PrismaPlanetScale } from '@prisma/adapter-planetscale' export default { @@ -538,19 +573,31 @@ If you don't have a project to deploy, follow the instructions in the [Prerequis ::: -First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `DATABASE_URL` environment variable: +First, ensure that the database connection is configured properly. Database connection URLs are configured in `prisma.config.ts`: ```prisma file=schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + Next, you need to set the `DATABASE_URL` environment variable to the value of your database connection string. You'll do this in a file called `.dev.vars` used by Cloudflare: ```bash file=.dev.vars @@ -599,7 +646,7 @@ npm run env -- npx prisma migrate dev --name init Here is a sample code snippet that you can use to instantiate `PrismaClient` and send a query to your database: ```ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' import { PrismaNeon } from '@prisma/adapter-neon' export default { diff --git a/content/200-orm/200-prisma-client/500-deployment/301-edge/485-deploy-to-vercel.mdx b/content/200-orm/200-prisma-client/500-deployment/301-edge/485-deploy-to-vercel.mdx index bab4e03d21..f5d06377d7 100644 --- a/content/200-orm/200-prisma-client/500-deployment/301-edge/485-deploy-to-vercel.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/301-edge/485-deploy-to-vercel.mdx @@ -87,15 +87,26 @@ If your application uses PostgreSQL, we recommend using [Prisma Postgres](/postg ### Setting your database connection URL as an environment variable -First, ensure that the `DATABASE_URL` is set as the `url` of the `datasource` in your Prisma schema: +First, ensure that your `datasource` block in your Prisma schema is configured correctly. Database connection URLs are configured in `prisma.config.ts`: ```prisma datasource db { provider = "postgresql" // this might also be `mysql` or another value depending on your database - url = env("DATABASE_URL") } ``` +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + #### Development When in **development**, you can configure your database connection via the `DATABASE_URL` environment variable (e.g. [using `.env` files](/orm/more/development-environment/environment-variables)). @@ -159,13 +170,17 @@ model User { If you are using Vercel Postgres, you need to: - use the `@prisma/adapter-neon` database adapter because Vercel Postgres uses [Neon](https://neon.tech/) under the hood -- be aware that Vercel by default calls the environment variable for the database connection string `POSTGRES_PRISMA_URL` while the default name used in the Prisma docs is typically `DATABASE_URL`; using Vercel's naming, you need to set the following fields on your `datasource` block: - ```prisma - datasource db { - provider = "postgresql" - url = env("POSTGRES_PRISMA_URL") // uses connection pooling - directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection - } +- be aware that Vercel by default calls the environment variable for the database connection string `POSTGRES_PRISMA_URL` while the default name used in the Prisma docs is typically `DATABASE_URL`; using Vercel's naming, you need to configure these in `prisma.config.ts`: + ```ts file=prisma.config.ts + import { defineConfig, env } from 'prisma/config' + + export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('POSTGRES_PRISMA_URL'), // uses connection pooling + directUrl: env('POSTGRES_URL_NON_POOLING'), // uses a direct connection + }, + }) ``` #### 1. Configure Prisma schema & database connection @@ -176,20 +191,32 @@ If you don't have a project to deploy, follow the instructions in the [Prerequis ::: -First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `POSTGRES_PRISMA_URL` and the `directUrl` to the `POSTGRES_URL_NON_POOLING` environment variable: +First, ensure that the database connection is configured properly. Database connection URLs are configured in `prisma.config.ts`: ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { - provider = "postgresql" - url = env("POSTGRES_PRISMA_URL") // uses connection pooling - directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection + provider = "postgresql" } ``` +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('POSTGRES_PRISMA_URL'), // uses connection pooling + directUrl: env('POSTGRES_URL_NON_POOLING'), // uses a direct connection + }, +}) +``` + Next, you need to set the `POSTGRES_PRISMA_URL` and `POSTGRES_URL_NON_POOLING` environment variable to the values of your database connection. If you ran `npx prisma init`, you can use the `.env` file that was created by this command to set these: @@ -246,7 +273,7 @@ Here is a sample code snippet that you can use to instantiate `PrismaClient` and ```ts file=app/api/edge/route.ts showLineNumbers import { NextResponse } from 'next/server' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' import { PrismaNeon } from '@prisma/adapter-neon' export const runtime = 'nodejs' // can also be set to 'edge' @@ -301,20 +328,32 @@ If you don't have a project to deploy, follow the instructions in the [Prerequis ::: -First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `DATABASE_URL` environment variable: +First, ensure that the database connection is configured properly. Database connection URLs are configured in `prisma.config.ts`: ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "mysql" - url = env("DATABASE_URL") relationMode = "prisma" // required for PlanetScale (as by default foreign keys are disabled) } ``` +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + Next, you need to set the `DATABASE_URL` environment variable in your `.env` file that's used both by Prisma and Next.js to read your env vars: ```bash file=.env @@ -368,7 +407,7 @@ Here is a sample code snippet that you can use to instantiate `PrismaClient` and ```ts file=app/api/edge/route.ts showLineNumbers import { NextResponse } from 'next/server' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' import { PrismaPlanetScale } from '@prisma/adapter-planetscale' export const runtime = 'nodejs' // can also be set to 'edge' @@ -423,19 +462,31 @@ If you don't have a project to deploy, follow the instructions in the [Prerequis ::: -First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `DATABASE_URL` environment variable: +First, ensure that the database connection is configured properly. Database connection URLs are configured in `prisma.config.ts`: ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` +```ts file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + Next, you need to set the `DATABASE_URL` environment variable in your `.env` file that's used both by Prisma and Next.js to read your env vars: ```bash file=.env showLineNumbers @@ -489,7 +540,7 @@ Here is a sample code snippet that you can use to instantiate `PrismaClient` and ```ts file=app/api/edge/route.ts showLineNumbers import { NextResponse } from 'next/server' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' import { PrismaNeon } from '@prisma/adapter-neon' export const runtime = 'nodejs' // can also be set to 'edge' @@ -540,7 +591,7 @@ Use `attachDatabasePool` together with [Prisma's driver adapters](/orm/overview/ import { Pool } from 'pg' import { attachDatabasePool } from '@vercel/functions' import { PrismaPg } from '@prisma/adapter-pg' -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from './generated/client' const pool = new Pool({ connectionString: process.env.POSTGRES_URL }) diff --git a/content/200-orm/200-prisma-client/500-deployment/301-edge/550-deploy-to-deno-deploy.mdx b/content/200-orm/200-prisma-client/500-deployment/301-edge/550-deploy-to-deno-deploy.mdx index 24c7af9c08..88c15dfb4c 100644 --- a/content/200-orm/200-prisma-client/500-deployment/301-edge/550-deploy-to-deno-deploy.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/301-edge/550-deploy-to-deno-deploy.mdx @@ -10,12 +10,6 @@ With this guide, you can learn how to build and deploy a simple application to [ This guide covers the use of Prisma CLI with Deno CLI, Deno Deploy, Prisma Client, and Prisma Postgres. -:::info - -This guide demonstrates how to deploy an application to Deno Deploy with a Prisma Postgres database, but you can also use [your own database with Prisma Accelerate](/accelerate/getting-started#prerequisites). - -::: - :::tip Use Prisma ORM without Rust binaries If Prisma ORM's Rust engine binaries cause large bundle sizes, slow builds, or deployment issues (for example, in serverless or edge environments), you can use it without them using this configuration of your `generator` block: @@ -70,7 +64,7 @@ This command: - Connects your CLI to your [Prisma Data Platform](https://console.prisma.io) account. If you're not logged in or don't have an account, your browser will open to guide you through creating a new account or signing into your existing one. - Creates a `prisma` directory containing a `schema.prisma` file for your database models. -- Creates a `.env` file with your `DATABASE_URL` (e.g., for Prisma Postgres it should have something similar to `DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..."`). +- Creates a `.env` file with your `DATABASE_URL` (e.g., `DATABASE_URL="postgresql://user:password@host:5432/database"`). Edit the `prisma/schema.prisma` file to define a `Log` model, add a custom `output` path and [the `prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client) with `deno` as the `runtime`: @@ -88,7 +82,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -107,16 +100,11 @@ enum Level { //add-end ``` -Then, install Prisma Client: +Then, install Prisma Client and the Postgres adapter: ```terminal deno install npm:@prisma/client -``` - -Then, install [the Client extension](https://www.npmjs.com/package/@prisma/extension-accelerate) required to use Prisma Postgres: - -```terminal -deno install npm:@prisma/extension-accelerate +deno install npm:@prisma/adapter-pg ``` Prisma Client does not read `.env` files by default on Deno, so you must also install `dotenv-cli` locally: @@ -146,10 +134,12 @@ You can now create a local Deno application. Create `index.ts` in the root folde ```ts file=index.ts import { serve } from "https://deno.land/std@0.140.0/http/server.ts"; -import { withAccelerate } from "npm:@prisma/extension-accelerate"; -import { PrismaClient } from "./generated/prisma/client.ts"; +import { PrismaPg } from "npm:@prisma/adapter-pg"; +import { PrismaClient } from "../generated/prisma/client.ts"; -const prisma = new PrismaClient().$extends(withAccelerate()); +const connectionString = `${Deno.env.get("DATABASE_URL")}`; +const adapter = new PrismaPg({ connectionString }); +const prisma = new PrismaClient({ adapter }); async function handler(request: Request) { // Ignore /favicon.ico requests: @@ -253,10 +243,12 @@ Add the following code in your `index.ts` file: ```ts file=index.ts import { serve } from "https://deno.land/std@0.140.0/http/server.ts"; -import { withAccelerate } from "npm:@prisma/extension-accelerate"; -import { PrismaClient } from "./generated/prisma/client.ts"; +import { PrismaPg } from "npm:@prisma/adapter-pg"; +import { PrismaClient } from "../generated/prisma/client.ts"; -const prisma = new PrismaClient().$extends(withAccelerate()); +const connectionString = `${Deno.env.get("DATABASE_URL")}`; +const adapter = new PrismaPg({ connectionString }); +const prisma = new PrismaClient({ adapter }); async function handler(request: Request) { // Ignore /favicon.ico requests: @@ -310,4 +302,4 @@ This rebuilds the deployment, which now works because the environment variable h ## Summary -You successfully deployed a Deno application that you created in TypeScript, which uses Prisma Client connecting to a Prisma Postgres database. +You successfully deployed a Deno application that you created in TypeScript, which uses Prisma Client with the Postgres adapter to connect to a Postgres database. diff --git a/content/200-orm/200-prisma-client/500-deployment/550-deploy-database-changes-with-prisma-migrate.mdx b/content/200-orm/200-prisma-client/500-deployment/550-deploy-database-changes-with-prisma-migrate.mdx index 7cae20ec3e..d3ddf28ec3 100644 --- a/content/200-orm/200-prisma-client/500-deployment/550-deploy-database-changes-with-prisma-migrate.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/550-deploy-database-changes-with-prisma-migrate.mdx @@ -12,12 +12,12 @@ To apply pending migrations to staging, testing, or production environments, run npx prisma migrate deploy ``` - +:::info This guide **does not apply for MongoDB**.
Instead of `migrate deploy`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb). -
+::: Exactly when to run `prisma migrate deploy` depends on your platform. For example, a simplified [Heroku](/orm/prisma-client/deployment/traditional/deploy-to-heroku) workflow includes: diff --git a/content/200-orm/200-prisma-client/600-observability-and-logging/130-logging.mdx b/content/200-orm/200-prisma-client/600-observability-and-logging/130-logging.mdx index a0c46bb2d7..8466e68656 100644 --- a/content/200-orm/200-prisma-client/600-observability-and-logging/130-logging.mdx +++ b/content/200-orm/200-prisma-client/600-observability-and-logging/130-logging.mdx @@ -13,17 +13,17 @@ Prisma Client supports two types of logging: - Logging to [stdout](https://en.wikipedia.org/wiki/Standard_streams) (default) - Event-based logging (use [`$on()`](/orm/reference/prisma-client-reference#on) method to [subscribe to events](#event-based-logging)) - +:::info You can also use the `DEBUG` environment variable to enable debugging output in Prisma Client. See [Debugging](/orm/prisma-client/debugging-and-troubleshooting/debugging) for more information. - +::: - +:::info If you want a detailed insight into your Prisma Client's performance at the level of individual operations, see [Tracing](/orm/prisma-client/observability-and-logging/opentelemetry-tracing). - +:::
diff --git a/content/200-orm/200-prisma-client/600-observability-and-logging/240-metrics.mdx b/content/200-orm/200-prisma-client/600-observability-and-logging/240-metrics.mdx index cff5a46155..65b0680781 100644 --- a/content/200-orm/200-prisma-client/600-observability-and-logging/240-metrics.mdx +++ b/content/200-orm/200-prisma-client/600-observability-and-logging/240-metrics.mdx @@ -98,7 +98,8 @@ In the `generator` block of your `schema.prisma` file, enable the `metrics` feat ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["metrics"] } ``` @@ -297,12 +298,12 @@ Each histogram "bucket" has two values. The first one is the upper bound of the You can send JSON-formatted metrics to [StatsD](https://github.com/statsd/statsd) to visualize your metrics data over time. - +:::info Note: You must provide counter metrics to StatsD as a series of values that are incremented or decremented from a previous retrieval of the metrics. However, Prisma Client's counter metrics return absolute values. Therefore, you must convert your counter metrics to a series of incremented and decremented values and send them to StatsD as gauge data. In the code example below, we convert counter metrics into incremented and decremented gauge data in `diffHistograms`. - +::: In the following example, we send metrics to StatsD every 10 seconds. This timing aligns with the default 10s flush rate of StatsD. @@ -512,7 +513,7 @@ For more information, read the Prometheus documentation on [metric types](https: In the majority of cases, Prometheus must scrape an endpoint to retrieve metrics. The following example shows how to send data with `Express.js`: ```js -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' import express, { Request, Response } from 'express' const app = express() @@ -532,7 +533,7 @@ app.listen(port, () => { The following example shows how to combine Prisma Client metrics with other Prometheus client libraries that are also served with a REST API endpoint in conjunction with `Express.js`: ```js -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' import express, { Request, Response } from 'express' import prom from 'prom-client' diff --git a/content/200-orm/200-prisma-client/600-observability-and-logging/250-opentelemetry-tracing.mdx b/content/200-orm/200-prisma-client/600-observability-and-logging/250-opentelemetry-tracing.mdx index f1b866c7d3..c3803e14ad 100644 --- a/content/200-orm/200-prisma-client/600-observability-and-logging/250-opentelemetry-tracing.mdx +++ b/content/200-orm/200-prisma-client/600-observability-and-logging/250-opentelemetry-tracing.mdx @@ -96,7 +96,8 @@ Tracing was added in version `4.2.0` of Prisma ORM as a Preview feature. For ver ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["tracing"] } ``` @@ -295,12 +296,12 @@ As an example, take the following Prisma schema: ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { @@ -468,7 +469,7 @@ registerTracing({ }) // You must import any dependencies after you register tracing. -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' import async from 'express-async-handler' import express from 'express' ``` diff --git a/content/200-orm/200-prisma-client/700-debugging-and-troubleshooting/245-troubleshooting-binary-size-issues.mdx b/content/200-orm/200-prisma-client/700-debugging-and-troubleshooting/245-troubleshooting-binary-size-issues.mdx index 01ecf50d9b..9d65481b98 100644 --- a/content/200-orm/200-prisma-client/700-debugging-and-troubleshooting/245-troubleshooting-binary-size-issues.mdx +++ b/content/200-orm/200-prisma-client/700-debugging-and-troubleshooting/245-troubleshooting-binary-size-issues.mdx @@ -11,7 +11,8 @@ As of [v6.16.0](https://pris.ly/release/6.16.0), you can resolve these issues by ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" engineType = "client" } ```` diff --git a/content/200-orm/300-prisma-migrate/050-getting-started.mdx b/content/200-orm/300-prisma-migrate/050-getting-started.mdx index 20aa70d447..48f5ac3122 100644 --- a/content/200-orm/300-prisma-migrate/050-getting-started.mdx +++ b/content/200-orm/300-prisma-migrate/050-getting-started.mdx @@ -17,7 +17,6 @@ To get started with Prisma Migrate in a development environment: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { diff --git a/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/005-overview.mdx b/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/005-overview.mdx index f458f09c12..8fba5dfbf8 100644 --- a/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/005-overview.mdx +++ b/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/005-overview.mdx @@ -9,11 +9,11 @@ hide_table_of_contents: true
- +:::info **Does not apply for MongoDB**
Instead of `migrate dev` and related commands, use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) for [MongoDB](/orm/overview/databases/mongodb). -
+::: Prisma Migrate enables you to: diff --git a/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/200-shadow-database.mdx b/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/200-shadow-database.mdx index bfcec4db00..765ed01f61 100644 --- a/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/200-shadow-database.mdx +++ b/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/200-shadow-database.mdx @@ -13,17 +13,17 @@ The shadow database is a second, _temporary_ database that is **created and dele * If your database does not allow creation and deleting of databases (e.g. in a cloud-hosted environment), you need to [create and configure the shadow database manually](#cloud-hosted-shadow-databases-must-be-created-manually). - +:::warning The shadow database is **not** required in production, and is not used by production-focused commands such as `prisma migrate resolve` and `prisma migrate deploy`. - +::: - +:::note A shadow database is never used for MongoDB as `migrate dev` is not used there. - +:::
@@ -86,7 +86,6 @@ In some cases it might make sense (e.g. when [creating and dropping databases is ```prisma highlight=4;normal datasource db { provider = "postgresql" - url = env("DATABASE_URL") //highlight-next-line shadowDatabaseUrl = env("SHADOW_DATABASE_URL") } @@ -105,7 +104,6 @@ Some cloud providers do not allow you to drop and create databases with SQL. Som ```prisma highlight=4;normal datasource db { provider = "postgresql" - url = env("DATABASE_URL") //highlight-next-line shadowDatabaseUrl = env("SHADOW_DATABASE_URL") } diff --git a/content/200-orm/300-prisma-migrate/300-workflows/10-seeding.mdx b/content/200-orm/300-prisma-migrate/300-workflows/10-seeding.mdx index baf2358905..0b186e2444 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/10-seeding.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/10-seeding.mdx @@ -27,7 +27,7 @@ Prisma ORM's integrated seeding functionality expects a command in the `"seed"` ```
- +:::info With TypeScript,`ts-node` does transpiling and typechecking by default; typechecking can be disabled with the following flag `--transpile-only`. @@ -36,7 +36,7 @@ Example: This can be useful to reduce memory usage (RAM) and increase execution speed of the seed script. - +:::
@@ -100,7 +100,7 @@ Here we suggest some specific seed scripts for different situations. You are fre Create some new users and posts in your `seed.ts` file: ```js file=seed.ts - import { PrismaClient } from '@prisma/client' + import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() async function main() { const alice = await prisma.user.upsert({ @@ -198,12 +198,12 @@ Here we suggest some specific seed scripts for different situations. You are fre 2. In the `seed.js` file, import Prisma Client, initialize it and create some records. As an example, take the following Prisma schema with a `User` and `Post` model: ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { diff --git a/content/200-orm/300-prisma-migrate/300-workflows/110-native-database-types.mdx b/content/200-orm/300-prisma-migrate/300-workflows/110-native-database-types.mdx index ba21b41f1f..81357ea4b3 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/110-native-database-types.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/110-native-database-types.mdx @@ -32,18 +32,17 @@ Comments and Prisma ORM-level functions (`uuid()` and `cuid()`) do not map to da Each Prisma ORM type maps to a default underlying database type - for example, the PostgreSQL connector maps `String` to `text` by default. [Native database type attributes](/orm/prisma-schema/data-model/models#native-types-mapping) determines which _specific_ native type should be created in the database. - +:::info -**Note**: Some Prisma ORM types only map to a single native type. +Some Prisma ORM types only map to a single native type. - +::: In the following example, the `name` and `title` fields have a `@db.VarChar(X)` type attribute: ```prisma highlight=8,14;normal datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { diff --git a/content/200-orm/300-prisma-migrate/300-workflows/120-native-database-functions.mdx b/content/200-orm/300-prisma-migrate/300-workflows/120-native-database-functions.mdx index 42cde2be6e..511016c829 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/120-native-database-functions.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/120-native-database-functions.mdx @@ -10,24 +10,24 @@ In PostgreSQL, some [native database functions](/orm/prisma-schema/data-model/un To use a PostgreSQL extension, you must install it on the file system of your database server and then activate the extension. If you use Prisma Migrate, this must be done as part of a migration. - +:::warning Do not activate extensions outside a migration file if you use Prisma Migrate. The [shadow database](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database) requires the same extensions. Prisma Migrate creates and deletes the shadow database automatically, so the only way to activate an extension is to include it in a migration file. - +::: In Prisma ORM versions 4.5.0 and later, you can activate the extension by declaring it in your Prisma schema with the [`postgresqlExtensions` preview feature](/orm/prisma-schema/postgresql-extensions): ```prisma file=schema.prisma highlight=3,9;add showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" //add-next-line previewFeatures = ["postgresqlExtensions"] } datasource db { provider = "postgresql" - url = env("DATABASE_URL") //add-next-line extensions = [pgcrypto] } diff --git a/content/200-orm/300-prisma-migrate/300-workflows/20-prototyping-your-schema.mdx b/content/200-orm/300-prisma-migrate/300-workflows/20-prototyping-your-schema.mdx index e019dc32a6..1ffac88301 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/20-prototyping-your-schema.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/20-prototyping-your-schema.mdx @@ -53,12 +53,12 @@ The following scenario demonstrates how to use `db push` to synchronize a new sc ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { @@ -176,12 +176,12 @@ The following scenario demonstrates how to use `db push` to prototype a change t ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { diff --git a/content/200-orm/300-prisma-migrate/300-workflows/200-troubleshooting.mdx b/content/200-orm/300-prisma-migrate/300-workflows/200-troubleshooting.mdx index 01d04f10c9..90014f2d77 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/200-troubleshooting.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/200-troubleshooting.mdx @@ -11,12 +11,12 @@ This guide describes how to resolve issues with Prisma Migrate in a development - [Production troubleshooting](/orm/prisma-migrate/workflows/patching-and-hotfixing) - [Patching / hotfixing production databases](/orm/prisma-migrate/workflows/patching-and-hotfixing) - +:::warning This guide **does not apply for MongoDB**.
Instead of `migrate dev`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb). -
+::: diff --git a/content/200-orm/300-prisma-migrate/300-workflows/30-baselining.mdx b/content/200-orm/300-prisma-migrate/300-workflows/30-baselining.mdx index 930c3afdb1..caec87136d 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/30-baselining.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/30-baselining.mdx @@ -16,12 +16,12 @@ Baselining tells Prisma Migrate to assume that one or more migrations have **alr Baselining is part of [adding Prisma Migrate to a project with an existing database](/orm/prisma-migrate/getting-started#adding-prisma-migrate-to-an-existing-project). - +:::warning This guide **does not apply for MongoDB**.
Instead of `migrate deploy`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb). -
+::: diff --git a/content/200-orm/300-prisma-migrate/300-workflows/40-customizing-migrations.mdx b/content/200-orm/300-prisma-migrate/300-workflows/40-customizing-migrations.mdx index e96f27e88c..d41ee7ba19 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/40-customizing-migrations.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/40-customizing-migrations.mdx @@ -7,12 +7,12 @@ tocDepth: 3 - +:::warning This guide **does not apply for MongoDB**.
Instead of `migrate dev`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb). -
+::: In some scenarios, you need to edit a migration file before you apply it. For example, to [change the direction of a 1-1 relation](#example-change-the-direction-of-a-1-1-relation) (moving the foreign key from one side to another) without data loss, you need to move data as part of the migration - this SQL is not part of the default migration, and must be written by hand. diff --git a/content/200-orm/300-prisma-migrate/300-workflows/50-squashing-migrations.mdx b/content/200-orm/300-prisma-migrate/300-workflows/50-squashing-migrations.mdx index 8faac3bf46..2b594c4753 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/50-squashing-migrations.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/50-squashing-migrations.mdx @@ -36,11 +36,11 @@ For detailed steps on how to achieve this using `migrate diff` and `migrate reso ## Considerations when squashing migrations - +:::warning When squashing migrations, be aware that any manually changed or added SQL in your `migration.sql` files will not be retained. If you have migration files with custom additions such as a view or a trigger, ensure to re-add them after your migrations were squashed. - +::: ## How to squash migrations @@ -57,11 +57,11 @@ Before squashing your migrations, make sure you have the following starting cond - All migrations applied to production are part of the local migration history already - There is no custom SQL in any of the new migration files that you have added to your branch - +:::info If the migration history on the production database has diverged after you created your feature branch, then you would need to first merge the migrations history and the datamodel changes from production into your local history. - +::: Then follow these steps: @@ -95,11 +95,11 @@ Then follow these steps, either on your `main` branch or on a newly checked out 2. Create a new empty directory in the `./prisma/migrations` directory. In this guide this will be called `000000000000_squashed_migrations`. Inside this, add a new empty `migration.sql` file. - + :::info We name the migration `000000000000_squashed_migrations` with all the leading zeroes because we want it to be the first migration in the migrations directory. Migrate runs the migrations in the directory in lexicographic (alphabetical) order. This is why it generates migrations with the date and time as a prefix when you use `migrate dev`. You can give the migration another name, as long as it it sorts lower than later migrations, for example `0_squashed` or `202207180000_squashed`. - + ::: 3. Create a single migration that takes you: diff --git a/content/200-orm/300-prisma-migrate/300-workflows/60-generating-down-migrations.mdx b/content/200-orm/300-prisma-migrate/300-workflows/60-generating-down-migrations.mdx index 5f20a17429..bc3e5af495 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/60-generating-down-migrations.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/60-generating-down-migrations.mdx @@ -17,17 +17,17 @@ When generating a migration SQL file, you may wish to also create a "down migrat This guide explains how to use Prisma Migrate's [`migrate diff` command](/orm/reference/prisma-cli-reference#migrate-diff) to create a down migration, and how to apply it to your production database with the [`db execute`](/orm/reference/prisma-cli-reference#db-execute) command in the case of a failed up migration. - +:::warning This guide applies to generating SQL down migrations for relational databases only. It does not apply to MongoDB. - +::: - +:::info The `migrate diff` and `db execute` commands are available in Preview in versions `3.9.0` and later, and are generally available in versions `3.13.0` and later. - +::: ## Considerations when generating down migrations diff --git a/content/200-orm/300-prisma-migrate/300-workflows/70-patching-and-hotfixing.mdx b/content/200-orm/300-prisma-migrate/300-workflows/70-patching-and-hotfixing.mdx index c9a2e6fc68..d17cc95bbd 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/70-patching-and-hotfixing.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/70-patching-and-hotfixing.mdx @@ -9,12 +9,12 @@ Patching or hotfixing a database involves making an often time critical change d Patching the production database directly results in **schema drift**: your database schema has 'drifted away' from the source of truth, and is out of sync with your migration history. You can use the `prisma migrate resolve` command to reconcile your migration history _without_ having to remove and re-apply the hotfix with `prisma migrate deploy`. - +:::warning This guide **does not apply for MongoDB**.
Instead of `migrate dev`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb). -
+:::
@@ -252,11 +252,11 @@ Your local migration history now yields the same result as the state your produc ## Migration history conflicts - +:::info This does not apply from version [3.12.0](https://github.com/prisma/prisma/releases/tag/3.12.0) upwards. - +::: `prisma migrate deploy` issues a warning if an already applied migration has been edited - however, it does not stop the migration process. To remove the warnings, restore the original migration from source control. diff --git a/content/200-orm/300-prisma-migrate/300-workflows/80-unsupported-database-features.mdx b/content/200-orm/300-prisma-migrate/300-workflows/80-unsupported-database-features.mdx index 5f5ff4a796..4e3fd00c03 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/80-unsupported-database-features.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/80-unsupported-database-features.mdx @@ -22,12 +22,12 @@ The Prisma schema is able to represent [unsupported field types](/orm/prisma-sch ::: - +:::warning This guide **does not apply for MongoDB**.
Instead of `migrate dev`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb). -
+::: diff --git a/content/200-orm/300-prisma-migrate/300-workflows/90-development-and-production.mdx b/content/200-orm/300-prisma-migrate/300-workflows/90-development-and-production.mdx index fabec1e8dd..10049b806a 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/90-development-and-production.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/90-development-and-production.mdx @@ -21,11 +21,11 @@ npx prisma migrate dev ### Create and apply migrations - +:::danger `migrate dev` is a development command and should never be used in a production environment. - +::: This command: @@ -48,11 +48,11 @@ You can also `reset` the database yourself to undo manual changes or `db push` e npx prisma migrate reset ``` - +:::warning `migrate reset` is a development command and should never be used in a production environment. - +::: This command: diff --git a/content/200-orm/500-reference/050-prisma-client-reference.mdx b/content/200-orm/500-reference/050-prisma-client-reference.mdx index cc31ef781c..f92eadde2b 100644 --- a/content/200-orm/500-reference/050-prisma-client-reference.mdx +++ b/content/200-orm/500-reference/050-prisma-client-reference.mdx @@ -13,7 +13,8 @@ If Prisma ORM's Rust engine binaries cause large bundle sizes, slow builds, or d ```prisma generator client { - provider = "prisma-client-js" // or "prisma-client" + provider = "prisma-client" + output = "./generated" engineType = "client" } ``` @@ -106,7 +107,7 @@ From version 5.2.0 and upwards, you can also use the [`datasourceUrl`](#datasour ##### Programmatically override a datasource `url` ```ts -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '../prisma/generated/client'; const prisma = new PrismaClient({ datasources: { @@ -122,7 +123,6 @@ Based on the following `datasource` block: ```prisma datasource db { provider = "sqlite" - url = env("DATABASE_URL") } ``` @@ -139,7 +139,7 @@ Programmatically overrides the [`datasource`](#datasources) block in the `schema #### Examples ```ts -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '../prisma/generated/client'; const prisma = new PrismaClient({ datasourceUrl: 'postgresql://johndoe:randompassword@localhost:5432/mydb', @@ -208,7 +208,7 @@ export type LogEvent = { ```ts highlight=3;normal; -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '../prisma/generated/client'; const prisma = new PrismaClient({ log: ['query', 'info'] }); @@ -247,7 +247,7 @@ prisma:query SELECT COUNT(*) FROM (SELECT "public"."User"."id" FROM "public"."Us ```ts -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '../prisma/generated/client'; const prisma = new PrismaClient({ log: [{ level: 'query', emit: 'event' }], @@ -296,7 +296,7 @@ main() ```ts -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '../prisma/generated/client'; const prisma = new PrismaClient({ log: [ @@ -415,7 +415,7 @@ The example below uses the [Neon driver adapter](/orm/overview/databases/neon#ho ```ts import { PrismaNeon } from '@prisma/adapter-neon'; -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '../prisma/generated/client'; import dotenv from 'dotenv'; dotenv.config(); @@ -427,13 +427,13 @@ const prisma = new PrismaClient({ adapter }); ### `rejectOnNotFound` - +:::info -**Note**: `rejectOnNotFound` was removed in v5.0.0. +`rejectOnNotFound` was removed in v5.0.0. **Deprecated:** `rejectOnNotFound` is deprecated in v4.0.0. From v4.0.0, use the queries [`findUniqueOrThrow`](#finduniqueorthrow) or [`findFirstOrThrow`](#findfirstorthrow). - +::: Use the `rejectOnNotFound` parameter to configure `findUnique()` and/or `findFirst` to throw an error if the record was not found. By default, both operations return `null` if the record is not found. @@ -487,11 +487,11 @@ const prisma = new PrismaClient({ ### `transactionOptions` - +:::info -**Note**: `transactionOptions` was introduced in v5.10.0. +`transactionOptions` was introduced in v5.10.0. - +::: Allows to set [transaction options](/orm/prisma-client/queries/transactions#transaction-options) globally on the constructor level. @@ -712,7 +712,7 @@ const user = await prisma.user.findFirst({ ##### Get the first `Post` record where the `title` starts with `A test`, reverse the list with `take` ```ts -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '../prisma/generated/client'; const prisma = new PrismaClient({}); @@ -848,7 +848,7 @@ The following example results in **two** `INSERT` statements: ```ts -import { Prisma, PrismaClient } from '@prisma/client'; +import { Prisma, PrismaClient } from '../prisma/generated/client'; const prisma = new PrismaClient({ log: ['query'] }); @@ -949,11 +949,11 @@ const user = await prisma.user.update({ ### `upsert()` - +:::info This section covers the usage of the `upsert()` operation. To learn about using [nested upsert queries](#upsert-1) within `update()`, reference the linked documentation. - +::: `upsert` does the following: @@ -2178,7 +2178,8 @@ Because the `relationLoadStrategy` option is currently in Preview, you need to e ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["relationJoins"] } ``` @@ -2954,10 +2955,12 @@ To enable `nativeDistinct`: ```prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["nativeDistinct"] } ``` +``` See [Preview Features](/orm/reference/preview-features/client-preview-features#preview-features-promoted-to-general-availability) for more details. @@ -3487,11 +3490,11 @@ const user = await prisma.user.update({ ### `upsert` - +:::info This section covers the usage of nested upsert within `update()`. To learn about the [`upsert()`](#upsert) operation, reference the linked documentation. - +::: A nested `upsert` query updates a related record if it exists, or creates a new related record. @@ -4457,12 +4460,12 @@ const addTag = await prisma.post.update({ ### `unset` - +:::warning This method is available on MongoDB only in versions [3.11.1](https://github.com/prisma/prisma/releases/tag/3.11.1) and later. - +::: Use `unset` to unset the value of a scalar list. Unlike `set: null`, `unset` removes the list entirely. @@ -4487,7 +4490,7 @@ const setTags = await prisma.post.update({ Scalar list filters allow you to filter by the contents of a list / array field. - +:::warning Available for: @@ -4495,7 +4498,7 @@ Available for: - CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later - MongoDB in versions [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0) and later - +::: ### Remarks @@ -4589,12 +4592,12 @@ const posts = await prisma.post.findMany({ ### `isSet` - +:::warning This filter is available on MongoDB only in versions [3.11.1](https://github.com/prisma/prisma/releases/tag/3.11.1) and later. - +::: Filter lists to include only results that have been set (either set to a value, or explicitly set to `null`). Setting this filter to `true` will exclude undefined results that are not set at all. @@ -4632,11 +4635,11 @@ const posts = await prisma.post.findMany({ ## Composite type methods - +:::warning Available for MongoDB only in Prisma `3.10.0` and later. - +::: Composite type methods allow you to create, update and delete [composite types](/orm/prisma-client/special-fields-and-types/composite-types). @@ -4801,11 +4804,11 @@ const product = prisma.product.update({ ## Composite type filters - +:::warning Available for MongoDB only in Prisma `3.11.0` and later. - +::: Composite type filters allow you to filter the contents of [composite types](/orm/prisma-client/special-fields-and-types/composite-types). @@ -5057,11 +5060,11 @@ const updatePosts = await prisma.post.updateMany({ For use cases and advanced examples, see: [Working with `Json` fields](/orm/prisma-client/special-fields-and-types/working-with-json-fields). - +:::warning Supported by [PostgreSQL](/orm/overview/databases/postgresql) and [MySQL](/orm/overview/databases/mysql) with different syntaxes for the `path` option. PostgreSQL does not support filtering on object key values in arrays. - +::: The examples in this section assumes that the value of the `pet` field is: @@ -5158,11 +5161,11 @@ const getUsers = await prisma.user.findMany({
- +:::warning Filtering by the key values of objects inside an array (below) is only supported by the MySQL connector. - +::: The following query returns all users where the nested `favorites` > `treats` array contains an object where the `name` value is `"Dreamies"`: @@ -5345,11 +5348,11 @@ const getUsers = await prisma.user.findMany({ }); ``` - +:::info -**Note**: In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value. +In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value. - +:::
@@ -5480,13 +5483,13 @@ const getUsers = await prisma.user.findMany({ - `$on` and `$use` client methods do not exist on extended client instances which are extended using [`$extends`](#extends) - +:::warning In [extended clients](/orm/prisma-client/client-extensions), Client methods do not necessarily exist. If you are extending your client, make sure to check for existence before using Client methods like `$transaction` or `$connect`. In addition, if you are using `$on` or `$use`, you will need to use these client methods before extending your client as these methods do not exist on extended clients. For `$use` specifically we recommend transitioning [to use query extensions](/orm/prisma-client/client-extensions/query). - +::: ### `$disconnect()` @@ -5506,11 +5509,11 @@ The `$connect()` method establishes a physical connection to the database via Pr ### `$on()` - +:::warning `$on` is not available in [extended clients](/orm/prisma-client/client-extensions). Please either migrate to client extensions or use the `$on` method prior to extending your client. - +::: The `$on()` method allows you to subscribe to [logging events](#log) or the [exit hook](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management#exit-hooks). @@ -5595,7 +5598,7 @@ Prisma.validator(PrismaClientInstance, '', '', ' The following example shows how you can extract and validate the input for the `create` operation you can reuse within your app: ```ts -import { Prisma } from '@prisma/client'; +import { Prisma } from '../prisma/generated/client'; const validateUserAndPostInput = (name, email, postTitle) => { return Prisma.validator()({ @@ -5613,7 +5616,7 @@ const validateUserAndPostInput = (name, email, postTitle) => { Here is an alternative syntax for the same operation: ```ts -import { Prisma } from '@prisma/client'; +import { Prisma } from '../prisma/generated/client'; import prisma from './prisma'; const validateUserAndPostInput = (name, email, postTitle) => { @@ -5640,7 +5643,7 @@ You can compare columns in the same table directly, for non-unique filters. This feature was moved to general availability in version 5.0.0 and was available via the `fieldReference` Preview feature from Prisma ORM versions 4.3.0 to 4.16.2. - +:::info In the following situations, you must [use raw queries to compare columns in the same table](/orm/more/help-and-troubleshooting/comparing-columns-through-raw-queries): @@ -5649,7 +5652,7 @@ In the following situations, you must [use raw queries to compare columns in the - If you want to compare a field with a [unique constraint](/orm/prisma-schema/data-model/models#defining-a-unique-field) - If you want to use one of the following operators to compare a [JSON field](/orm/prisma-client/special-fields-and-types/working-with-json-fields) in MySQL or MariaDB with another field: [`gt`](#gt), [`gte`](#gte), [`lt`](#lt), or [`lte`](#lte). Note that you can use these operators to compare the JSON field with a scalar value. This limitation applies only if you try to compare a JSON field with another field. - +::: To compare columns in the same table, use the `.fields` property. In the following example, the query returns all records where the value in the `prisma.product.quantity` field is less than or equal to the value in the `prisma.product.warnQuantity` field. @@ -5659,11 +5662,11 @@ prisma.product.findMany({ }); ``` - +:::info `fields` is a special property of every model. It contains the list of fields for that model. - +::: ### Considerations diff --git a/content/200-orm/500-reference/100-prisma-schema-reference.mdx b/content/200-orm/500-reference/100-prisma-schema-reference.mdx index 0a113a1579..dfb6187e6f 100644 --- a/content/200-orm/500-reference/100-prisma-schema-reference.mdx +++ b/content/200-orm/500-reference/100-prisma-schema-reference.mdx @@ -78,7 +78,6 @@ In this example, the target database is available with the following credentials ```prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` @@ -1043,12 +1042,12 @@ Not supported ### `Unsupported` - +:::warning **Not supported by MongoDB**
The [MongoDB connector](/orm/overview/databases/mongodb) does not support the `Unsupported` type. -
+::: The `Unsupported` type was introduced in [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and allows you to represent data types in the Prisma schema that are not supported by Prisma Client. Fields of type `Unsupported` can be created during Introspection with `prisma db pull` or written by hand, and created in the database with Prisma Migrate or `db push`. @@ -1301,7 +1300,7 @@ model User { } ``` - +:::warning You cannot use `cuid()` to generate a default value if your `id` field is of type `ObjectId`. Use the following syntax to generate a valid `ObjectId`: @@ -1309,7 +1308,7 @@ You cannot use `cuid()` to generate a default value if your `id` field is of typ id String @id @default(auto()) @db.ObjectId @map("_id") ``` - +:::
@@ -1338,7 +1337,7 @@ model User { } ``` - +:::warning You cannot use `uuid()` to generate a default value if your `id` field is of type `ObjectId`. Use the following syntax to generate a valid `ObjectId`: @@ -1346,7 +1345,7 @@ You cannot use `uuid()` to generate a default value if your `id` field is of typ id String @id @default(auto()) @db.ObjectId @map("_id") ``` - +:::
@@ -1375,7 +1374,7 @@ model User { } ``` - +:::warning You cannot use `ulid()` to generate a default value if your `id` field is of type `ObjectId`. Use the following syntax to generate a valid `ObjectId`: @@ -1383,7 +1382,7 @@ You cannot use `ulid()` to generate a default value if your `id` field is of typ id String @id @default(auto()) @db.ObjectId @map("_id") ``` - +:::
@@ -1512,12 +1511,12 @@ const profileWithUser = await prisma.profile.create({ ### `@@id` - +:::warning **Not supported by MongoDB**
The [MongoDB connector](/orm/overview/databases/mongodb) does not support composite IDs. -
+::: Defines a multi-field ID (composite ID) on the model. @@ -2468,11 +2467,11 @@ Defines an index in the database. - Define partial indexes with `WHERE` - Create indexes concurrently with `CONCURRENTLY` - +:::info While you cannot configure these option in your Prisma schema, you can still configure them on the database-level directly. - +::: ##### MongoDB @@ -2968,12 +2967,12 @@ The name of the `name` argument on the `@@schema` attribute can be omitted ```prisma highlight=3,9,16;normal generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") //highlight-next-line schemas = ["auth"] } @@ -2987,11 +2986,11 @@ model User { } ``` - +:::info For more information about using the `multiSchema` feature, refer to [this guide](/orm/prisma-schema/data-model/multi-schema). - +::: ### `@shardKey` @@ -2999,7 +2998,7 @@ For more information about using the `multiSchema` feature, refer to [this guide This features requires the `shardKeys` Preview feature flag on your `generator`: ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" output = "../generated/prisma" previewFeatures = ["shardKeys"] } @@ -3022,7 +3021,7 @@ model User { This features requires the `shardKeys` Preview feature flag on your `generator`: ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" output = "../generated/prisma" previewFeatures = ["shardKeys"] } @@ -3044,7 +3043,9 @@ model User { ### `auto()` -This function is available on MongoDB only. +:::warning +This function is available on MongoDB only. +::: Represents **default values** that are automatically generated by the database. @@ -3075,12 +3076,12 @@ model User { ### `autoincrement()` - +:::warning **Not supported by MongoDB**
The [MongoDB connector](/orm/overview/databases/mongodb) does not support the `autoincrement()` function. -
+::: Create a sequence of integers in the underlying database and assign the incremented values to the ID values of the created records based on the sequence. @@ -3109,12 +3110,12 @@ model User { ### `sequence()` - +:::info **Only supported by CockroachDB**
The sequence function is only supported by [CockroachDB connector](/orm/overview/databases/cockroachdb). -
+::: Create a sequence of integers in the underlying database and assign the incremented values to the values of the created records based on the sequence. @@ -3475,11 +3476,11 @@ model User { } ``` - +:::info -**Note**: [`gen_random_uuid()` is a PostgreSQL function](https://www.postgresql.org/docs/13/functions-uuid.html). To use it in PostgreSQL versions 12.13 and earlier, you must enable the `pgcrypto` extension.

In Prisma ORM versions 4.5.0 and later, you can declare the `pgcrypto` extension in your Prisma schema with the [`postgresqlExtensions` preview feature](/orm/prisma-schema/postgresql-extensions). +[`gen_random_uuid()` is a PostgreSQL function](https://www.postgresql.org/docs/13/functions-uuid.html). To use it in PostgreSQL versions 12.13 and earlier, you must enable the `pgcrypto` extension.

In Prisma ORM versions 4.5.0 and later, you can declare the `pgcrypto` extension in your Prisma schema with the [`postgresqlExtensions` preview feature](/orm/prisma-schema/postgresql-extensions). -
+::: ## Attribute argument types @@ -3497,12 +3498,12 @@ An expression that can be evaluated by Prisma ORM: `42.0`, `""`, `Bob`, `now()`, ## `enum` - +:::warning **Not supported Microsoft SQL Server**
The [Microsoft SQL Server connector](/orm/overview/databases/sql-server) does not support the `enum` type. -
+::: Defines an [enum](/orm/prisma-schema/data-model/models#defining-enums) . @@ -3591,17 +3592,17 @@ model User { ## `type` - +:::warning Composite types are available **for MongoDB only**. - +::: - +:::info Composite types are available in versions 3.12.0 and later, and in versions 3.10.0 and later if you enable the `mongodb` Preview feature flag. - +::: Defines a [composite type](/orm/prisma-schema/data-model/models#defining-composite-types) . diff --git a/content/200-orm/500-reference/200-prisma-cli-reference.mdx b/content/200-orm/500-reference/200-prisma-cli-reference.mdx index 31b6eb1914..6f636d254c 100644 --- a/content/200-orm/500-reference/200-prisma-cli-reference.mdx +++ b/content/200-orm/500-reference/200-prisma-cli-reference.mdx @@ -133,7 +133,7 @@ By default, the project sets up a [local Prisma Postgres](/postgres/database/loc | `--db` | No | Shorthand syntax for `--datasource-provider prisma+postgres`; creates a new [Prisma Postgres](/postgres) instance. Requires authentication in the [PDP Console](https://console.prisma.io). | | | `--prompt` (or `--vibe`) | No | Scaffolds a Prisma schema based on the prompt and deploys it to a fresh Prisma Postgres instance. Requires authentication in the [PDP Console](https://console.prisma.io). | | | `--url` | No | Define a custom `datasource` url. | | -| `--generator-provider` | No | Define the generator provider to use. | `prisma-client-js` | +| `--generator-provider` | No | Define the generator provider to use. | `prisma-client` | | `--preview-feature` | No | Define the [Preview features](/orm/reference/preview-features) to use. To define multiple Preview features, you have to provide the flag multiple times for each Preview feature. See examples. | | | `--output` | No | Specifies the [output location for the generated client](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path). | `../generated/prisma` | | `--with-model` | No | Adds a simple `User` model to the initial Prisma schema. Available since version `5.14.0`. | | @@ -215,11 +215,11 @@ prisma init --preview-feature metrics ```prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["metrics"] } ``` @@ -243,11 +243,11 @@ prisma init --preview-feature view --preview-feature metrics ```prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["views", "metrics"] } ``` @@ -267,13 +267,12 @@ An initial `schema.prisma` file to define your schema in: // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client" output = "../generated/prisma" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` @@ -323,11 +322,11 @@ A minimal `schema.prisma` file to define your schema in: datasource db { provider = "mysql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } ``` @@ -350,19 +349,19 @@ DATABASE_URL="mysql://user:password@localhost:3306/mydb" The `generate` command generates assets like Prisma Client based on the [`generator`](/orm/prisma-schema/overview/generators) and [`data model`](/orm/prisma-schema/data-model/models) blocks defined in your `prisma/schema.prisma` file. -The `generate` command is most often used to generate Prisma Client with the `prisma-client-js` generator. This does three things: +The `generate` command is most often used to generate Prisma Client with the `prisma-client` generator. This does the following: -1. Searches the current directory and parent directories to find the applicable `npm` project. It will create a `package.json` file in the current directory if it cannot find one. -2. Installs the `@prisma/client` into the `npm` project if it is not already present. -3. Inspects the current directory to find a Prisma Schema to process. It will then generate a customized [Prisma Client](https://github.com/prisma/prisma-client-js) for your project. +1. Inspects the current directory to find a Prisma Schema to process. +2. Generates a customized Prisma Client based on your schema into the output directory specified in the generator block. #### Prerequisites -To use the `generate` command, you must add a generator definition in your `schema.prisma` file. The `prisma-client-js` generator, used to generate Prisma Client, can be added by including the following in your `schema.prisma` file: +To use the `generate` command, you must add a generator definition in your `schema.prisma` file. The `prisma-client` generator, used to generate Prisma Client, can be added by including the following in your `schema.prisma` file: ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } ``` @@ -413,7 +412,7 @@ prisma generate You can now start using Prisma Client in your code: -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' // or const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() @@ -469,7 +468,7 @@ prisma generate --generator client --generator zod_schemas #### Generated Assets -The `prisma-client-js` generator creates a customized client for working with your database within the `./node_modules/.prisma/client` directory by default - you can [customize the output folder](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path). +The `prisma-client` generator creates a customized client for working with your database in a custom output directory specified by the `output` field - you can [customize the output folder](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path). ### `validate` @@ -524,7 +523,7 @@ Error code: P1012 error: The preview feature "unknownFeatureFlag" is not known. Expected one of: [...] --> schema.prisma:3 | - 2 | provider = "prisma-client-js" + 2 | provider = "prisma-client" 3 | previewFeatures = ["unknownFeatureFlag"] | @@ -591,7 +590,7 @@ Error code: P1012 error: The preview feature "unknownFeatureFlag" is not known. Expected one of: [...] --> schema.prisma:3 | - 2 | provider = "prisma-client-js" + 2 | provider = "prisma-client" 3 | previewFeatures = ["unknownFeatureFlag"] | @@ -923,7 +922,8 @@ prisma db pull --print ```prisma no-copy generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { diff --git a/content/200-orm/500-reference/250-error-reference.mdx b/content/200-orm/500-reference/250-error-reference.mdx index fefd1fd8bd..7b1d484872 100644 --- a/content/200-orm/500-reference/250-error-reference.mdx +++ b/content/200-orm/500-reference/250-error-reference.mdx @@ -334,11 +334,11 @@ Possible P1012 error messages: ### Prisma Migrate (Schema Engine) - +:::warning The Schema Engine was previously called Migration Engine. This change was introduced in version [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0). - +::: #### `P3000` diff --git a/content/200-orm/500-reference/300-environment-variables-reference.mdx b/content/200-orm/500-reference/300-environment-variables-reference.mdx index 9bc8dcc2a2..fb3d680d86 100644 --- a/content/200-orm/500-reference/300-environment-variables-reference.mdx +++ b/content/200-orm/500-reference/300-environment-variables-reference.mdx @@ -84,7 +84,6 @@ Disables all CLI warnings generated by `logger.warn`. ### `PRISMA_GENERATE_NO_ENGINE` - :::danger Prisma v7 deprecation This environment variable is only supported in Prisma 6.19 and earlier. It will not work in Prisma v7. diff --git a/content/200-orm/500-reference/325-prisma-config-reference.mdx b/content/200-orm/500-reference/325-prisma-config-reference.mdx index 713ec76d34..24a14d6ee7 100644 --- a/content/200-orm/500-reference/325-prisma-config-reference.mdx +++ b/content/200-orm/500-reference/325-prisma-config-reference.mdx @@ -440,6 +440,7 @@ Configure the schema engine your project should use. By default it is set to use the classic engine, which requires that `datasource` be set in your `prisma.config.ts`. ```ts +import 'dotenv/config' import path from "node:path"; import { defineConfig, env } from "prisma/config"; export default defineConfig({ diff --git a/content/200-orm/500-reference/380-connection-urls.mdx b/content/200-orm/500-reference/380-connection-urls.mdx index a8bf1b54a9..d68457494b 100644 --- a/content/200-orm/500-reference/380-connection-urls.mdx +++ b/content/200-orm/500-reference/380-connection-urls.mdx @@ -156,7 +156,6 @@ You can also provide the connection URL as an environment variable: ```prisma file=schema.prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` diff --git a/content/200-orm/500-reference/500-preview-features/050-client-preview-features.mdx b/content/200-orm/500-reference/500-preview-features/050-client-preview-features.mdx index 1ea24923c5..f4f60abfc8 100644 --- a/content/200-orm/500-reference/500-preview-features/050-client-preview-features.mdx +++ b/content/200-orm/500-reference/500-preview-features/050-client-preview-features.mdx @@ -33,7 +33,8 @@ To enable a Prisma Client Preview feature: ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" previewFeatures = ["relationJoins"] } ``` diff --git a/content/200-orm/800-more/100-under-the-hood/100-engines.mdx b/content/200-orm/800-more/100-under-the-hood/100-engines.mdx index 78d23be5a0..b9c43e8272 100644 --- a/content/200-orm/800-more/100-under-the-hood/100-engines.mdx +++ b/content/200-orm/800-more/100-under-the-hood/100-engines.mdx @@ -294,8 +294,9 @@ When using Rust-based engines, you can choose between a Node-API library or an e ```prisma generator client { - provider = "prisma-client-js" // or "prisma-client" - engineType = "binary" // or "library" for Rust-based engines + provider = "prisma-client" + output = "./generated" + engineType = "binary" } ``` diff --git a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/101-jsonprotocol-changes.mdx b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/101-jsonprotocol-changes.mdx index 9b21076af3..acf128027f 100644 --- a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/101-jsonprotocol-changes.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/101-jsonprotocol-changes.mdx @@ -204,11 +204,11 @@ prisma.user.findMany({ }) ``` - +:::info Note: This `path` argument change only affects PostgreSQL databases. MySQL databases are not affected as they use a different syntax. - +::: #### Scalar lists diff --git a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/index.mdx b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/index.mdx index 10454a4417..ea3e59c462 100644 --- a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/index.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/600-upgrading-to-prisma-5/index.mdx @@ -43,11 +43,11 @@ pnpm upgrade prisma@5 @prisma/client@5 - +:::danger Before you upgrade, check each breaking change below to see how the upgrade might affect your application. - +::: ## Version changes @@ -58,11 +58,11 @@ See our [system requirements](/orm/reference/system-requirements) for all minimu From Prisma ORM version 5.0.0, the minimum version of Node.js supported is 16.13.0. If your project uses an earlier version of Node.js, you will need to upgrade it. - +:::warning Node.js v16.x is reaching [end-of-life on 11 September 2023](https://nodejs.org/en/blog/announcements/nodejs16-eol) in order to coincide with the end-of-life of OpenSSL 1.1.1. For that reason, we recommend upgrading to the current Node.js LTS, v18.x. Please note that Prisma ORM 5 will be the last major version of Prisma ORM to support Node.js v16. - +::: ### TypeScript minimum version change @@ -72,11 +72,11 @@ From Prisma ORM version 5.0.0, the minimum version of TypeScript supported is 4. From Prisma ORM version 5.0.0, the minimum version of PostgreSQL supported is 9.6. If your project uses an earlier version of PostgreSQL, you will need to upgrade it. - +:::warning While Prisma ORM supports PostgreSQL versions 9.6 and above, we **strongly** recommend updating to a version that is currently supported and still receiving updates. Please check [PostgreSQL's versioning policy](https://www.postgresql.org/support/versioning/) to determine which versions are currently supported. - +::: ### Prisma Client embedded SQLite version updated diff --git a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/700-upgrading-to-prisma-4.mdx b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/700-upgrading-to-prisma-4.mdx index ff95e20ff9..4abaf62f5f 100644 --- a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/700-upgrading-to-prisma-4.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/700-upgrading-to-prisma-4.mdx @@ -451,11 +451,11 @@ To upgrade to Prisma ORM 4 from an earlier version, you need to update both the To ignore the caret `^` and upgrade across major versions, you can use the `@4` tag when you upgrade with `npm`, or `yarn`: - +:::danger Before you upgrade, check each **breaking change** to see how the upgrade might affect your application. - +::: diff --git a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/800-upgrading-to-prisma-3/150-referential-actions.mdx b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/800-upgrading-to-prisma-3/150-referential-actions.mdx index a099b97d22..af110627d1 100644 --- a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/800-upgrading-to-prisma-3/150-referential-actions.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/800-upgrading-to-prisma-3/150-referential-actions.mdx @@ -57,11 +57,11 @@ When you run an Introspection, Prisma ORM compares all the foreign keys in the d After introspecting, you can review the non-default clauses in your schema. The most important clause to review is `onDelete`, which defaults to `Cascade` in version 2.25.0 and earlier. - +:::danger If you are using either the [`delete()`](/orm/prisma-client/queries/crud#delete-a-single-record) or [`deleteAll()`](/orm/prisma-client/queries/crud#delete-all-records) methods, **cascading deletes will now be performed, as the safety net in Prisma Client that previously prevented cascading deletes at runtime is removed**. Be sure to check your code and make any adjustments accordingly. - +::: Make sure you are happy with every case of `onDelete: Cascade` in your schema. If not, either: @@ -91,12 +91,12 @@ model User { When running a [Migration](/orm/prisma-migrate) (or the [`prisma db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) command) the [new defaults](/orm/prisma-schema/data-model/relations/referential-actions#referential-action-defaults) will be applied to your database. - +:::info Unlike when you run `prisma db pull` for the first time, the new referential actions clause and property will **not** automatically be added to your Prisma schema by the Prisma VSCode extension. You will have to manually add them if you wish to use anything other than the new defaults. - +::: Explicitly defining referential actions in your Prisma schema is optional. If you do not explicitly define a referential action for a relation, Prisma ORM uses the [new defaults](/orm/prisma-schema/data-model/relations/referential-actions#referential-action-defaults). diff --git a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/800-upgrading-to-prisma-3/index.mdx b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/800-upgrading-to-prisma-3/index.mdx index 2180704600..059b79c98f 100644 --- a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/800-upgrading-to-prisma-3/index.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/800-upgrading-to-prisma-3/index.mdx @@ -116,13 +116,13 @@ prisma.log.create({ }) ``` - +:::warning This API change does not apply to the MongoDB connector where there is not a difference between a JSON null and a database NULL. They also do not apply to the `array_contains` operator because there can only be a JSON null within an JSON array. Since there cannot be a database NULL within a JSON array, `{ array_contains: null }` is not ambiguous. - +::: ## Specific upgrade paths @@ -134,11 +134,11 @@ To upgrade from version 2.x to 3.x, you need to update both the `prisma` and `@p To ignore the caret `^` and upgrade across major versions, you can use the `@3` tag when upgrading with `npm`, or `yarn` . - +:::danger Before upgrading, check each **breaking change** to see how the upgrade might affect your application. - +::: diff --git a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/900-codemods.mdx b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/900-codemods.mdx index df3c620c2f..c103ccf427 100644 --- a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/900-codemods.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/900-codemods.mdx @@ -8,11 +8,11 @@ metaDescription: 'Use codemods to upgrade your codebase as Prisma ORM evolves.' The `@prisma/codemods` package helps you to upgrade your codebase as Prisma ORM evolves. - +:::info You can checkout the repository, here: https://github.com/prisma/codemods - +::: diff --git a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/index.mdx b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/index.mdx index a207ab3508..5276ab1701 100644 --- a/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/index.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/200-upgrading-versions/index.mdx @@ -45,8 +45,8 @@ To install the latest `dev` distribution tag: npm install @prisma/client@dev prisma@dev ``` - +:::danger Do not use the `dev` distribution tag in production - wait until the official release that contains the features and fixes you are interested in is released. For example, fixes present `@prisma/client@2.23.0-dev.25` will eventually be released as part of `@prisma/client@2.23.0`. - +::: diff --git a/content/200-orm/800-more/300-upgrade-guides/250-upgrading-to-use-preview-features.mdx b/content/200-orm/800-more/300-upgrade-guides/250-upgrading-to-use-preview-features.mdx index 816fd2be41..bdd474e310 100644 --- a/content/200-orm/800-more/300-upgrade-guides/250-upgrading-to-use-preview-features.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/250-upgrading-to-use-preview-features.mdx @@ -18,8 +18,8 @@ Some releases include Preview features that are not considered production-ready, - [Enable Prisma Client and schema preview features](/orm/reference/preview-features/client-preview-features) - [Enable Prisma CLI preview features](/orm/reference/preview-features/cli-preview-features) - +:::warning We do not recommend using Preview features in production. - +::: diff --git a/content/200-orm/800-more/300-upgrade-guides/800-upgrade-from-prisma-1/08-upgrade-from-mongodb-beta.mdx b/content/200-orm/800-more/300-upgrade-guides/800-upgrade-from-prisma-1/08-upgrade-from-mongodb-beta.mdx index 4358dc8ae2..7e0161a6e8 100644 --- a/content/200-orm/800-more/300-upgrade-guides/800-upgrade-from-prisma-1/08-upgrade-from-mongodb-beta.mdx +++ b/content/200-orm/800-more/300-upgrade-guides/800-upgrade-from-prisma-1/08-upgrade-from-mongodb-beta.mdx @@ -12,10 +12,10 @@ The scope of this guide is to give you the workflow necessary to perform the mig We unfortunately can't cover all possible scenarios or changes required, but this guide should help you on your journey. Join [our Discord](https://pris.ly/discord?utm_source=docs&utm_medium=intro_text) or create an issue [on Github](https://github.com/prisma/prisma1/issues/new/choose) with any questions. - +:::warning Perform this migration on your staging environment before trying this in production! - +::: ## Requirements @@ -37,7 +37,7 @@ This should create the following files: - `prisma/schema.prisma`: An initial Prisma schema - `.env`: Environment file where you'll store your connection string - +:::info If you see the following error: @@ -48,7 +48,7 @@ Please try again in a project that is not yet using Prisma. You have likely a `prisma/` directory in your project already. Rename that directory to something like `_prisma/` and try again - +::: ## Find the Connection String to your MongoDB Database @@ -74,11 +74,11 @@ $ npx prisma db pull And you should see your Prisma schema in `prisma/schema.prisma` populated with your models. - +:::info If you see the following error: `Error in connector: SCRAM failure: Authentication failed.`, try adding `?authSource=admin` to the end of your connection string and trying again. - +::: ## Touching up your Prisma Schema @@ -112,11 +112,11 @@ Unlike SQL databases, MongoDB doesn't have an explicit understanding of relation We typically recommend adding the relationships by hand with the help of [this documentation](/orm/overview/databases/mongodb#how-to-add-in-missing-relations-after-introspection). However, Prisma 1 stores foreign keys is different than where Prisma ORM 2 and later expects foreign keys, so if you want to take advantage of relationships, you'll need to shift where the foreign keys are on your database before adding the relationships. - +:::tip 💡 Download the Prisma VSCode Extension to provide autocomplete and helpful error messages as you transition your Prisma schema. - +::: ## Generating a Prisma Client @@ -211,7 +211,7 @@ main() And you should see a user was created. - +:::warning If you see the following error: @@ -221,7 +221,7 @@ Prisma needs to perform transactions, which requires your MongoDB server to be r This means that your MongoDB database isn't running as a replica set. Refer to [the link above](https://pris.ly/d/mongodb-replica-set) for steps to resolve this issue. - +::: ## Upgrading your Application diff --git a/content/200-orm/800-more/350-ai-tools/100-cursor.mdx b/content/200-orm/800-more/350-ai-tools/100-cursor.mdx index 2ab60d89ab..97b1b6fbb5 100644 --- a/content/200-orm/800-more/350-ai-tools/100-cursor.mdx +++ b/content/200-orm/800-more/350-ai-tools/100-cursor.mdx @@ -206,12 +206,12 @@ If you run the prompts below, you may receive a different outputs because LLMs p ```prisma file=schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } @@ -341,7 +341,7 @@ import { UserRole, SubscriptionPlan, SubscriptionStatus, -} from "@prisma/client"; +} from "../prisma/generated/client"; const prisma = new PrismaClient(); diff --git a/content/200-orm/800-more/350-ai-tools/200-tabnine.mdx b/content/200-orm/800-more/350-ai-tools/200-tabnine.mdx index 63c470a872..c67ad37b70 100644 --- a/content/200-orm/800-more/350-ai-tools/200-tabnine.mdx +++ b/content/200-orm/800-more/350-ai-tools/200-tabnine.mdx @@ -56,12 +56,12 @@ _Define a Prisma schema for a SaaS application with User, Organization, and Subs ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { @@ -316,8 +316,8 @@ GROUP BY status; #### Application code ```ts -import { PrismaClient } from '@prisma/client' -import { subscriptionsReport } from '@prisma/client/sql' +import { PrismaClient } from '../prisma/generated/client' +import { subscriptionsReport } from '../prisma/generated/client/sql' const prisma = new PrismaClient(); @@ -416,7 +416,7 @@ _Generate a Prisma seed script for populating User, Organization, and Subscripti #### Generated code ```ts -import { PrismaClient } from "@prisma/client"; +import { PrismaClient } from "../prisma/generated/client"; const prisma = new PrismaClient(); diff --git a/content/200-orm/800-more/350-ai-tools/300-windsurf.mdx b/content/200-orm/800-more/350-ai-tools/300-windsurf.mdx index 814c77f782..35aacddc1d 100644 --- a/content/200-orm/800-more/350-ai-tools/300-windsurf.mdx +++ b/content/200-orm/800-more/350-ai-tools/300-windsurf.mdx @@ -233,12 +233,12 @@ LLMs may produce different results each time, even with the same prompt. ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { @@ -365,7 +365,7 @@ import { UserRole, SubscriptionPlan, SubscriptionStatus, -} from "@prisma/client"; +} from "../prisma/generated/client"; const prisma = new PrismaClient(); diff --git a/content/200-orm/800-more/350-ai-tools/400-github-copilot.mdx b/content/200-orm/800-more/350-ai-tools/400-github-copilot.mdx index 740f3b9305..ea70d9b59e 100644 --- a/content/200-orm/800-more/350-ai-tools/400-github-copilot.mdx +++ b/content/200-orm/800-more/350-ai-tools/400-github-copilot.mdx @@ -137,7 +137,7 @@ You can tailor Copilot Chat's behavior in your repository by [adding a `.github/ ```ts // prisma.ts - import { PrismaClient } from '@prisma/client'; + import { PrismaClient } from '../prisma/generated/client'; export const prisma = global.prisma || new PrismaClient(); if (process.env.NODE_ENV !== 'production') global.prisma = prisma; /``` diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/100-autocompletion-in-graphql-resolvers-with-js.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/100-autocompletion-in-graphql-resolvers-with-js.mdx index 912ecb7d92..963f8db2eb 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/100-autocompletion-in-graphql-resolvers-with-js.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/100-autocompletion-in-graphql-resolvers-with-js.mdx @@ -39,7 +39,7 @@ To overcome this, you need to add a [JSDoc](https://jsdoc.app/) comment named `t // Add this to the top of the file /** - * @typedef { import("@prisma/client").PrismaClient } Prisma + * @typedef { import("../prisma/generated/client").PrismaClient } Prisma */ ``` @@ -75,8 +75,8 @@ The final file should look something like: ```js /** - * @typedef { import("@prisma/client").PrismaClient } Prisma - * @typedef { import("@prisma/client").UserCreateArgs } UserCreateArgs + * @typedef { import("../prisma/generated/client").PrismaClient } Prisma + * @typedef { import("../prisma/generated/client").UserCreateArgs } UserCreateArgs */ const { makeExecutableSchema } = require('graphql-tools') diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/300-implicit-to-explicit-conversion.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/300-implicit-to-explicit-conversion.mdx index b65c07c74f..fcdc3a5c1b 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/300-implicit-to-explicit-conversion.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/300-implicit-to-explicit-conversion.mdx @@ -76,7 +76,7 @@ To migrate the existing data from the implicit relation table to the new explici Considering the above `User` and `Post` models, here’s an example script you can use to migrate data. ```typescript -import { PrismaClient } from "@prisma/client"; +import { PrismaClient } from "../prisma/generated/client"; const prisma = new PrismaClient(); diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/400-nextjs-help.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/400-nextjs-help.mdx index 075f318eb0..19dc9c0bfc 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/400-nextjs-help.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/400-nextjs-help.mdx @@ -31,7 +31,7 @@ To avoid this, create a single Prisma Client instance by using a global variable ```typescript // lib/prisma.ts -import { PrismaClient } from "@prisma/client"; +import { PrismaClient } from "../prisma/generated/client"; const globalForPrisma = global as unknown as { prisma: PrismaClient }; @@ -91,7 +91,7 @@ Use a factory function to dynamically create Prisma Clients based on tenant-spec ```typescript // lib/prismaDynamic.ts -import { PrismaClient } from "@prisma/client"; +import { PrismaClient } from "../prisma/generated/client"; type TenantConfig = { databaseUrl: string; diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/500-comparing-columns-through-raw-queries.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/500-comparing-columns-through-raw-queries.mdx index 146867f787..23df2ec3d1 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/500-comparing-columns-through-raw-queries.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/500-comparing-columns-through-raw-queries.mdx @@ -20,11 +20,11 @@ Comparing values from two columns in the same table can be achieved by using [ra ### Comparing numeric values - +:::info From version 4.3.0, you do not need to use raw queries to compare columns in the same table. You can use the `.fields` property to compare the columns. [Learn more](/orm/reference/prisma-client-reference#compare-columns-in-the-same-table) - +::: One use case for comparing values from different columns would be retrieving posts that have more comments than likes; in this case, you need to compare the values of `commentsCount` and `likesCount`. @@ -48,7 +48,7 @@ Queries (depending upon which database) could look something like: _PostgreSQL / CockroachDB_ ```js -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() @@ -65,7 +65,7 @@ await initiateNumbersComparisonRawQuery() _MySQL_ ```js -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() @@ -82,7 +82,7 @@ await initiateNumbersComparisonRawQuery() _Sqlite_ ```js -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() @@ -118,11 +118,11 @@ _Query Response_ ### Comparing date values - +:::info From version 4.3.0, you do not need to use raw queries to compare columns in the same table. You can use the `.fields` property to compare the columns. [Learn more](/orm/reference/prisma-client-reference#compare-columns-in-the-same-table) - +::: Similarly, if you need to compare dates, you could also achieve the same thing using raw queries. @@ -145,7 +145,7 @@ Queries (depending upon the database) could look something like: _PostgreSQL / CockroachDB_ ```js -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() @@ -162,7 +162,7 @@ await initiateDatesComparisonRawQuery() _MySQL_ ```js -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() @@ -179,7 +179,7 @@ await initiateDatesComparisonRawQuery() _Sqlite_ ```js -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prisma = new PrismaClient() diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/600-vercel-caching-issue.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/600-vercel-caching-issue.mdx index 5061c15778..d4d1fc6f08 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/600-vercel-caching-issue.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/600-vercel-caching-issue.mdx @@ -56,11 +56,11 @@ You can configure the deployment to run this command in multiple different ways: ### A custom `postinstall` script - +:::info This is the preferred method as it is a universal solution. - +::: Within the `scripts` section of your project's `package.json` file, if there is not already a script named `postinstall`, add one and add `prisma generate` to that script: diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/700-netlify-caching-issue.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/700-netlify-caching-issue.mdx index 3285593ac5..ed7836a4bd 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/700-netlify-caching-issue.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/700-netlify-caching-issue.mdx @@ -54,11 +54,11 @@ You can configure the deployment to run this command in multiple different ways: ### A custom `postinstall` script - +:::info This is the preferred method as it is a universal solution. - +::: Within the `scripts` section of your project's `package.json` file, if there is not already a script named `postinstall`, add one and add prisma generate` in that script: diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/800-check-constraints.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/800-check-constraints.mdx index 2166927bc6..a4dc7b9815 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/800-check-constraints.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/800-check-constraints.mdx @@ -260,7 +260,6 @@ Create a new file named `schema.prisma` and add the following code to it: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` @@ -288,12 +287,12 @@ This command introspects your database and for each table adds a Prisma model to ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model anotherproduct { @@ -328,7 +327,8 @@ First, add a `generator` block to your Prisma schema (typically added right belo ```prisma file=schema.prisma showLineNumbers generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } ``` @@ -345,7 +345,7 @@ Now you can use Prisma Client to send database queries in Node.js. Create a new file named `index.js` and add the following code to it: ```js -const { PrismaClient } = require('@prisma/client') +const { PrismaClient } = require('../prisma/generated/client') const prisma = new PrismaClient() @@ -380,7 +380,7 @@ ConnectorError(ConnectorError { user_facing_error: None, kind: QueryError(Error To validate the multi-column check constraint, replace the code in `index.js` with the following: ```js -const { PrismaClient } = require('@prisma/client') +const { PrismaClient } = require('../prisma/generated/client') const prisma = new PrismaClient() @@ -416,7 +416,7 @@ ConnectorError(ConnectorError { user_facing_error: None, kind: QueryError(Error Finally, modify the script to include multiple check constraint violations: ```js -const { PrismaClient } = require('@prisma/client') +const { PrismaClient } = require('../prisma/generated/client') const prisma = new PrismaClient() diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/900-prisma-nuxt-module.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/900-prisma-nuxt-module.mdx index b6fa843888..93b0615b4d 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/900-prisma-nuxt-module.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/900-prisma-nuxt-module.mdx @@ -51,12 +51,12 @@ This module provides several features to streamline the setup and usage of Prism // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "sqlite" - url = env("DATABASE_URL") } model User { @@ -76,9 +76,9 @@ This module provides several features to streamline the setup and usage of Prism } ``` 4. Prompt you to run a migration to create database tables with [Prisma Migrate](/orm/prisma-migrate/understanding-prisma-migrate/overview) - + :::note The database migrates automatically the first time you start the module if there isn't a `migrations` folder. After that, you need to run `npx prisma migrate dev` manually in the CLI to apply any schema changes. Running the `npx prisma migrate dev` command manually makes it easier and safer to manage migrations and also to [troubleshoot](/orm/prisma-migrate/workflows/troubleshooting) any migration-related errors. - + ::: 5. Install and generate a [Prisma Client](/orm/reference/prisma-client-reference) which enables you to query your DB 6. Automatically start [Prisma Studio](/orm/tools/prisma-studio) @@ -103,12 +103,12 @@ To configure [the getting started example](#getting-started) to use a PostgreSQL // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { @@ -190,7 +190,7 @@ If you're using [Nuxt server components](https://nuxt.com/docs/guide/directory-s After running through the initial setup prompts, this module creates the `lib/prisma.ts` file which contains a global instance of Prisma Client. ```typescript file=lib/prisma.ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const prismaClientSingleton = () => { return new PrismaClient() @@ -210,7 +210,7 @@ if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma You can customize Prisma Client's capabilities by using client extensions in your `lib/prisma.ts` file. Here is an example using the [Accelerate client extension](https://www.npmjs.com/package/@prisma/extension-accelerate): ```typescript file=lib/prisma.ts -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' import { withAccelerate } from '@prisma/extension-accelerate' const prismaClientSingleton = () => { @@ -274,9 +274,9 @@ export default defineNuxtConfig({ }) ```
- +:::note The `prisma` key is available in `nuxt.config.ts` after successfully setting up the module by running `npm run dev` - +::: | Option | Type | Default | Description | |---------------------|-----------|---------|-------------| @@ -366,7 +366,8 @@ Please try delete `output = ../generated/prisma` in schema.prisma, like ```prisma file=prisma/schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated" } ``` diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/950-typescript-performance-optimization.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/950-typescript-performance-optimization.mdx index 4cd6f46770..ba4de7c29e 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/950-typescript-performance-optimization.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/950-typescript-performance-optimization.mdx @@ -70,7 +70,7 @@ The solution involves using TypeScript's `typeof` operator instead of direct typ ### Problematic approach for large schemas ```typescript -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const saveFn = async (prismaClient: PrismaClient) => { // Function implementation @@ -89,7 +89,7 @@ await saveFn(client) ### Optimized approach with `typeof` ```typescript -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../prisma/generated/client' const saveFn = async (prismaClient: typeof client) => { // Function implementation diff --git a/package-lock.json b/package-lock.json index 128d01fdb5..687dafc3fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -248,6 +248,7 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.40.0.tgz", "integrity": "sha512-nlr/MMgoLNUHcfWC5Ns2ENrzKx9x51orPc6wJ8Ignv1DsrUmKm0LUih+Tj3J+kxYofzqQIQRU495d4xn3ozMbg==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/client-common": "5.40.0", "@algolia/requester-browser-xhr": "5.40.0", @@ -373,6 +374,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -2313,6 +2315,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -2335,6 +2338,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -2444,6 +2448,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2865,6 +2870,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3547,6 +3553,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.1.tgz", "integrity": "sha512-FWDk1LIGD5UR5Zmm9rCrXRoxZUgbwuP6FBA7rc50DVfzqDOMkeMe3NyJhOsA2dF0zBE3VbHEIMmTjKwTZJwbaA==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/babel": "3.9.1", "@docusaurus/bundler": "3.9.1", @@ -3623,6 +3630,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/faster/-/faster-3.9.1.tgz", "integrity": "sha512-zJIrIv+R/IN5TTLV9L+SvO3hwz62L6pO/L16k+b2nC3to3Gn01cnEGHL6doTGAezuPwTSmteJl+kzaoOf+znzg==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/types": "3.9.1", "@rspack/core": "^1.5.0", @@ -3751,6 +3759,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.1.tgz", "integrity": "sha512-DyLk9BIA6I9gPIuia8XIL+XIEbNnExam6AHzRsfrEq4zJr7k/DsWW7oi4aJMepDnL7jMRhpVcdsCxdjb0/A9xg==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/core": "3.9.1", "@docusaurus/logger": "3.9.1", @@ -5531,6 +5540,7 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", + "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -6751,6 +6761,7 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -6855,6 +6866,7 @@ "integrity": "sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ==", "hasInstallScript": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.24" @@ -7544,6 +7556,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -7903,6 +7916,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -7988,6 +8002,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -8033,6 +8048,7 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.40.0.tgz", "integrity": "sha512-a9aIL2E3Z7uYUPMCmjMFFd5MWhn+ccTubEvnMy7rOTZCB62dXBJtz0R5BZ/TPuX3R9ocBsgWuAbGWQ+Ph4Fmlg==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/abtesting": "1.6.0", "@algolia/client-abtesting": "5.40.0", @@ -8544,6 +8560,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -9576,6 +9593,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -11144,6 +11162,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -16317,6 +16336,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -16997,6 +17017,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -17900,6 +17921,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -18736,6 +18758,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -18745,6 +18768,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -18800,6 +18824,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/react": "*" }, @@ -18828,6 +18853,7 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -19625,6 +19651,7 @@ "resolved": "https://registry.npmjs.org/sass/-/sass-1.93.2.tgz", "integrity": "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==", "license": "MIT", + "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -20937,7 +20964,8 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "license": "0BSD", + "peer": true }, "node_modules/type-fest": { "version": "2.19.0", @@ -21000,6 +21028,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -21036,6 +21065,7 @@ "integrity": "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.7", @@ -21415,6 +21445,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -21636,6 +21667,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz", "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -22063,6 +22095,7 @@ "dev": true, "hasInstallScript": true, "license": "Apache-2.0", + "peer": true, "bin": { "workerd": "bin/workerd" }, @@ -22329,6 +22362,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } From a72eb21f53c8449e90d6a73c9702334afc456fa9 Mon Sep 17 00:00:00 2001 From: Nurul Sundarani Date: Mon, 17 Nov 2025 15:29:23 +0530 Subject: [PATCH 11/23] Update guides to use prisma.config.ts (#7243) * (feat) Update guides to use prisma.config.ts * refactor: Updated guides for Prisma 7 changes --------- Co-authored-by: Aman Varshney --- content/800-guides/010-data-migration.mdx | 47 ++++++++-- .../020-implementing-schema-changes.mdx | 29 +++++++ .../800-guides/030-migrate-from-typeorm.mdx | 29 +++++++ .../800-guides/040-migrate-from-sequelize.mdx | 33 ++++++- .../800-guides/050-migrate-from-mongoose.mdx | 29 +++++++ .../800-guides/060-migrate-from-drizzle.mdx | 55 +++++++++--- content/800-guides/070-cloudflare-d1.mdx | 11 ++- content/800-guides/080-turborepo.mdx | 39 +++++++-- content/800-guides/090-nextjs.mdx | 41 ++++++--- content/800-guides/100-nuxt.mdx | 37 ++++++-- content/800-guides/130-docker.mdx | 39 ++++++++- .../140-use-prisma-in-pnpm-workspaces.mdx | 44 +++++++--- content/800-guides/150-multiple-databases.mdx | 87 +++++++++++++------ content/800-guides/160-tanstack-start.mdx | 27 ++++-- content/800-guides/170-react-router-7.mdx | 29 +++++-- content/800-guides/180-solid-start.mdx | 27 ++++-- content/800-guides/190-data-dog.mdx | 32 ++++++- content/800-guides/190-sveltekit.mdx | 23 +++-- content/800-guides/200-clerk-nextjs.mdx | 43 ++++++++- content/800-guides/210-shopify.mdx | 29 +++++++ content/800-guides/220-astro.mdx | 23 +++-- content/800-guides/230-betterauth-nextjs.mdx | 50 +++++++++-- .../800-guides/300-supabase-accelerate.mdx | 65 +++++++++++--- content/800-guides/310-neon-accelerate.mdx | 65 +++++++++++--- .../320-permit-io-access-control.mdx | 22 +++-- content/800-guides/330-github-actions.mdx | 35 +++++++- content/800-guides/340-ai-sdk-nextjs.mdx | 19 ++-- content/800-guides/350-authjs-nextjs.mdx | 19 ++-- .../800-guides/360-embed-studio-nextjs.mdx | 14 +-- content/800-guides/370-bun.mdx | 30 +++++-- content/800-guides/390-hono.mdx | 30 +++++-- content/800-guides/400-deno-integration.mdx | 1 - content/800-guides/999-making-guides.mdx | 81 ++++++++++++++--- 33 files changed, 973 insertions(+), 211 deletions(-) diff --git a/content/800-guides/010-data-migration.mdx b/content/800-guides/010-data-migration.mdx index 24b98c97b6..81e58874e3 100644 --- a/content/800-guides/010-data-migration.mdx +++ b/content/800-guides/010-data-migration.mdx @@ -45,12 +45,12 @@ Start with a basic schema containing a Post model: ```prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated/prisma" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model Post { @@ -61,7 +61,36 @@ model Post { } ``` -### 1.2. Create a development branch +### 1.2. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + +### 1.3. Create a development branch Create a new branch for your changes: @@ -108,9 +137,17 @@ npx prisma migrate dev --name add-status-column Create a new TypeScript file for the data migration: ```typescript -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../generated/prisma/client' +import { PrismaPg } from '@prisma/adapter-pg' +import 'dotenv/config' + +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL, +}) -const prisma = new PrismaClient() +const prisma = new PrismaClient({ + adapter, +}) async function main() { await prisma.$transaction(async (tx) => { diff --git a/content/800-guides/020-implementing-schema-changes.mdx b/content/800-guides/020-implementing-schema-changes.mdx index a5d8342766..83a4f30211 100644 --- a/content/800-guides/020-implementing-schema-changes.mdx +++ b/content/800-guides/020-implementing-schema-changes.mdx @@ -47,6 +47,35 @@ Source-controlling the `schema.prisma` file is not enough - you must include you - Customized migrations contain information that cannot be represented in the Prisma schema - The `prisma migrate deploy` command only runs migration files +### 1.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + ## 2. Incorporate team changes ### 2.1. Pull latest changes diff --git a/content/800-guides/030-migrate-from-typeorm.mdx b/content/800-guides/030-migrate-from-typeorm.mdx index 210e5bd1be..4b852ac2b9 100644 --- a/content/800-guides/030-migrate-from-typeorm.mdx +++ b/content/800-guides/030-migrate-from-typeorm.mdx @@ -51,6 +51,35 @@ Update the `DATABASE_URL` in the `.env` file with your database connection strin DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE" ``` +### 2.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + ## 3. Migrate the database schema ### 3.1. Introspect your database diff --git a/content/800-guides/040-migrate-from-sequelize.mdx b/content/800-guides/040-migrate-from-sequelize.mdx index 4abf2e8fac..663f59366a 100644 --- a/content/800-guides/040-migrate-from-sequelize.mdx +++ b/content/800-guides/040-migrate-from-sequelize.mdx @@ -58,11 +58,11 @@ The Prisma schema currently looks as follows: datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated/prisma" } ``` @@ -78,6 +78,35 @@ Update the `DATABASE_URL` in the `.env` file with your database connection strin DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE" ``` +### 1.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + ## 2. Migrate the database schema ### 2.1. Introspect your database diff --git a/content/800-guides/050-migrate-from-mongoose.mdx b/content/800-guides/050-migrate-from-mongoose.mdx index 3143c942f0..e9a4b2b306 100644 --- a/content/800-guides/050-migrate-from-mongoose.mdx +++ b/content/800-guides/050-migrate-from-mongoose.mdx @@ -78,6 +78,35 @@ Update the `DATABASE_URL` in the `.env` file with your MongoDB connection string DATABASE_URL="mongodb://USER:PASSWORD@HOST:PORT/DATABASE" ``` +### 1.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + ## 2. Migrate the database schema ### 2.1. Introspect your database diff --git a/content/800-guides/060-migrate-from-drizzle.mdx b/content/800-guides/060-migrate-from-drizzle.mdx index 53b6e57d18..0b53916367 100644 --- a/content/800-guides/060-migrate-from-drizzle.mdx +++ b/content/800-guides/060-migrate-from-drizzle.mdx @@ -82,11 +82,11 @@ The Prisma schema currently looks as follows: datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "./generated/prisma" } ``` @@ -107,7 +107,6 @@ If you're not using PostgreSQL, you need to adjust the `provider` field on the ` ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` @@ -118,7 +117,6 @@ datasource db { ```prisma file=schema.prisma showLineNumbers datasource db { provider = "mysql" - url = env("DATABASE_URL") } ``` @@ -129,7 +127,6 @@ datasource db { ```prisma file=schema.prisma showLineNumbers datasource db { provider = "sqlserver" - url = env("DATABASE_URL") } ``` @@ -140,7 +137,6 @@ datasource db { ```prisma file=schema.prisma showLineNumbers datasource db { provider = "sqlite" - url = env("DATABASE_URL") } ``` @@ -150,7 +146,36 @@ datasource db { Once that's done, you can configure your [database connection URL](/orm/reference/connection-urls) in the `.env` file. Drizzle and Prisma ORM use the same format for connection URLs, so your existing connection URL should work fine. -### 2.3. Introspect your database using Prisma ORM +### 2.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + +### 2.4. Introspect your database using Prisma ORM With your connection URL in place, you can [introspect](/orm/prisma-schema/introspection) your database to generate your Prisma models: @@ -170,7 +195,7 @@ model todo { The generated Prisma model represents a database table. Prisma models are the foundation for your programmatic Prisma Client API which allows you to send queries to your database. -### 2.4. Create a baseline migration +### 2.5. Create a baseline migration To continue using Prisma Migrate to evolve your database schema, you will need to [baseline your database](/orm/prisma-migrate/getting-started). @@ -202,7 +227,7 @@ The command will mark `0_init` as applied by adding it to the `_prisma_migration You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. -### 2.5. Adjust the Prisma schema (optional) +### 2.6. Adjust the Prisma schema (optional) Models that are generated via introspection currently _exactly_ map to your database tables. In this section, you'll learn how you can adjust the naming of the Prisma models to adhere to [Prisma ORM's naming conventions](/orm/reference/prisma-schema-reference#naming-conventions). @@ -254,9 +279,17 @@ touch db/prisma.ts Now, instantiate `PrismaClient` and export it from the file so you can use it in your route handlers later: ```ts copy file=db/prisma.ts showLineNumbers -import { PrismaClient } from '@prisma/client' +import { PrismaClient } from '../generated/prisma/client' +import { PrismaPg } from '@prisma/adapter-pg' +import 'dotenv/config' + +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL, +}) -export const prisma = new PrismaClient() +export const prisma = new PrismaClient({ + adapter, +}) ``` ### 4.1. Replacing `getData` queries diff --git a/content/800-guides/070-cloudflare-d1.mdx b/content/800-guides/070-cloudflare-d1.mdx index 5d8083a679..5cd25c94cc 100644 --- a/content/800-guides/070-cloudflare-d1.mdx +++ b/content/800-guides/070-cloudflare-d1.mdx @@ -53,13 +53,12 @@ In your Prisma schema, set the `provider` of the `datasource` to `sqlite`. If yo ```prisma file=prisma/schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" output = "../src/generated/prisma" } datasource db { provider = "sqlite" - url = env("DATABASE_URL") } //add-start @@ -179,7 +178,7 @@ CLOUDFLARE_D1_TOKEN="F8Cg..." Ensure that you have a `prisma.config.ts` file set up in the root of your project with a [driver adapter](/orm/reference/prisma-config-reference#adapter-removed) defined. -```ts +```typescript file=prisma.config.ts import type { PrismaConfig } from 'prisma'; import { PrismaD1 } from '@prisma/adapter-d1'; @@ -191,6 +190,12 @@ export default { adapter: true, }, schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: process.env.DATABASE_URL!, + }, async adapter() { return new PrismaD1({ CLOUDFLARE_D1_TOKEN: process.env.CLOUDFLARE_D1_TOKEN!, diff --git a/content/800-guides/080-turborepo.mdx b/content/800-guides/080-turborepo.mdx index 6580182f7b..c39d302495 100644 --- a/content/800-guides/080-turborepo.mdx +++ b/content/800-guides/080-turborepo.mdx @@ -94,7 +94,7 @@ Next, install the required dependencies to use Prisma ORM. Use your preferred pa ```terminal npm install prisma --save-dev -npm install @prisma/client +npm install @prisma/client dotenv ```
@@ -103,7 +103,7 @@ npm install @prisma/client ```terminal yarn add prisma --dev -yarn add @prisma/client +yarn add @prisma/client dotenv ```
@@ -112,7 +112,7 @@ yarn add @prisma/client ```terminal pnpm add prisma --save-dev -pnpm add @prisma/client +pnpm add @prisma/client dotenv ```
@@ -200,7 +200,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -222,6 +221,23 @@ model Post { //add-end ``` +The `prisma.config.ts` file created in the `packages/database` directory should look like this: + +```typescript file=packages/database/prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + :::warning It is recommended to add `../generated/prisma` to the `.gitignore` file because it contains platform-specific binaries that can cause compatibility issues across different environments. @@ -335,7 +351,7 @@ Navigate to the project root and run the following command to automatically migr -Generate your `prisma.schema` +Generate your `schema.prisma` To generate the types from Prisma schema, from the project root run: @@ -383,7 +399,9 @@ import { withAccelerate } from "@prisma/extension-accelerate"; const globalForPrisma = global as unknown as { prisma: PrismaClient }; export const prisma = - globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate()); + globalForPrisma.prisma || new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, + }).$extends(withAccelerate()); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; ``` @@ -394,11 +412,18 @@ if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; ```ts file=packages/database/src/client.ts import { PrismaClient } from "../generated/prisma"; +import { PrismaPg } from '@prisma/adapter-pg'; + +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL, +}); const globalForPrisma = global as unknown as { prisma: PrismaClient }; export const prisma = - globalForPrisma.prisma || new PrismaClient(); + globalForPrisma.prisma || new PrismaClient({ + adapter, + }); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; ``` diff --git a/content/800-guides/090-nextjs.mdx b/content/800-guides/090-nextjs.mdx index 445d252b3e..d5e242f4ac 100644 --- a/content/800-guides/090-nextjs.mdx +++ b/content/800-guides/090-nextjs.mdx @@ -110,7 +110,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -139,17 +138,17 @@ This creates two models: `User` and `Post`, with a one-to-many relationship betw To get access to the variables in the `.env` file, they can either be loaded by your runtime, or by using `dotenv`. Include an import for `dotenv` at the top of the `prisma.config.ts` -```ts +```typescript file=prisma.config.ts //add-start import 'dotenv/config' //add-end import { defineConfig, env } from 'prisma/config'; + export default defineConfig({ schema: 'prisma/schema.prisma', migrations: { path: 'prisma/migrations' }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -171,8 +170,16 @@ Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts import { PrismaClient, Prisma } from "../app/generated/prisma"; +import { PrismaPg } from '@prisma/adapter-pg' +import 'dotenv/config' -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL, +}) + +const prisma = new PrismaClient({ + adapter, +}); const userData: Prisma.UserCreateInput[] = [ { @@ -218,9 +225,10 @@ main(); Now, tell Prisma how to run this script by updating your `prisma.config.ts`: -```ts file=prisma.config.ts +```typescript file=prisma.config.ts import 'dotenv/config' import { defineConfig, env } from 'prisma/config'; + export default defineConfig({ schema: 'prisma/schema.prisma', migrations: { @@ -229,7 +237,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -287,11 +294,13 @@ Now, add the following code to your `lib/prisma.ts` file: import { PrismaClient } from '../app/generated/prisma' import { withAccelerate } from '@prisma/extension-accelerate' -const globalForPrisma = global as unknown as { +const globalForPrisma = global as unknown as { prisma: PrismaClient } -const prisma = globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate()) +const prisma = globalForPrisma.prisma || new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()) if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma @@ -304,12 +313,19 @@ export default prisma ```typescript file=lib/prisma.ts showLineNumbers //add-start import { PrismaClient } from '../src/app/generated/prisma' +import { PrismaPg } from '@prisma/adapter-pg' -const globalForPrisma = global as unknown as { +const globalForPrisma = global as unknown as { prisma: PrismaClient } -const prisma = globalForPrisma.prisma || new PrismaClient() +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL, +}) + +const prisma = globalForPrisma.prisma || new PrismaClient({ + adapter, +}) if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma @@ -683,7 +699,7 @@ Before you deploy, you also need to tell Vercel to make sure that the Prisma Cli "scripts": { "dev": "next dev --turbopack", "build": "next build", - "postinstall": "prisma generate --no-engine", + "postinstall": "prisma generate", "start": "next start", "lint": "next lint" }, @@ -713,9 +729,6 @@ Before you deploy, you also need to tell Vercel to make sure that the Prisma Cli } ``` -:::note -If you're not using Prisma Postgres, you need to remove the `--no-engine` flag from the command. -::: After this change, you can deploy your application to Vercel by running `vercel`. diff --git a/content/800-guides/100-nuxt.mdx b/content/800-guides/100-nuxt.mdx index c35659aa03..58cee219c7 100644 --- a/content/800-guides/100-nuxt.mdx +++ b/content/800-guides/100-nuxt.mdx @@ -62,7 +62,36 @@ To follow this guide, ensure you have the following: }); ``` -## 2. Setup Prisma ORM by running the development server locally +## 2. Configure Prisma + +Before running the development server, create a `prisma.config.ts` file in the root of your project to manage environment variables and configuration: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables: + +```bash +npm install dotenv +``` + +::: + +## 3. Setup Prisma ORM by running the development server locally After configuring your Nuxt project with the Prisma module, the next step is to set up Prisma ORM. This process begins by starting the development server, which automatically configures Prisma with a [SQLite database](/orm/overview/databases/sqlite). @@ -90,12 +119,11 @@ Once the setup flow has terminated, it: // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client" } datasource db { provider = "sqlite" - url = env("DATABASE_URL") } model User { @@ -121,7 +149,7 @@ Once the setup flow has terminated, it: 5. Installed and generated [Prisma Client](https://da-2255.docs-51g.pages.dev/orm/reference/prisma-client-reference) which enables you to query your DB. 6. Installed [Prisma Studio](/orm/tools/prisma-studio). -When the Prisma setup is complete, the development server should start on `https://localhost:3000`. +When the Prisma setup is complete, the development server should start on `https://localhost:3000`. Next, stop the server, as we need to make some code changes. @@ -210,7 +238,6 @@ Now that the Prisma Postgres instance is ready, update your Nuxt application to datasource db { // edit-next-line provider = "postgresql" - url = env("DATABASE_URL") } ``` 3. Delete the SQLite database files (`dev.db` and `dev.db-journal`) along with the `migrations` folder, all located in the `prisma` directory. This cleans up the existing SQLite setup and prepares your project to migrate to PostgreSQL. diff --git a/content/800-guides/130-docker.mdx b/content/800-guides/130-docker.mdx index b6d6e1684d..031b660565 100644 --- a/content/800-guides/130-docker.mdx +++ b/content/800-guides/130-docker.mdx @@ -100,11 +100,10 @@ Add a `User` model to the `schema.prisma` file located in the `prisma/schema.pri ```prisma file=prisma/schema.prisma datasource db { provider = "postgresql" - url = env("DATABASE_URL") } generator client { - provider = "prisma-client-js" + provider = "prisma-client" //add-start output = "../generated/prisma_client" //add-end @@ -126,6 +125,33 @@ In the `schema.prisma` file, we specify a [custom `output` path](/orm/prisma-cli ::: +Now, create a `prisma.config.ts` file in the root of your project: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables: + +```bash +npm install dotenv +``` + +::: + ### 1.4. Create an Express.js server With the Prisma schema in place, let's create an Express.js server to interact with the database. Start by creating an `index.js` file: @@ -140,9 +166,16 @@ Add the following code to set up a basic Express server: //add-start const express = require("express"); const { PrismaClient } = require("./generated/prisma_client"); +const { PrismaPg } = require("@prisma/adapter-pg"); + +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL, +}); const app = express(); -const prisma = new PrismaClient(); +const prisma = new PrismaClient({ + adapter, +}); app.use(express.json()); // Get all users diff --git a/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx b/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx index 634859b3b1..eeba51cc96 100644 --- a/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx +++ b/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx @@ -141,7 +141,7 @@ Edit the `schema.prisma` file to define a `User` model in your database and spec ```prisma file=prisma/schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" //add-start output = "../generated/client" //add-end @@ -149,7 +149,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -161,6 +160,35 @@ model User { //add-end ``` +Now, create a `prisma.config.ts` file in the `database` package to configure Prisma: + +```typescript file=database/prisma.config.ts +// add-start +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +// add-end +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables from the `.env` file: + +```terminal +pnpm add dotenv +``` + +::: + Next, add helper scripts to your `package.json` to simplify Prisma commands: ```json file=database/package.json @@ -170,7 +198,7 @@ Next, add helper scripts to your `package.json` to simplify Prisma commands: "test": "echo \"Error: no test specified\" && exit 1", // delete-end // add-start - "db:generate": "prisma generate --no-engine", + "db:generate": "prisma generate", "db:migrate": "prisma migrate dev", "db:deploy": "prisma migrate deploy", "db:studio": "prisma studio" @@ -179,12 +207,6 @@ Next, add helper scripts to your `package.json` to simplify Prisma commands: } ``` -:::info - -If you're not using [Prisma Postgres](/postgres/getting-started) for your database, exclude the `--no-engine` flag from the `db:generate` script. - -::: - Use [Prisma Migrate](/orm/prisma-migrate) to migrate your database changes: ```terminal @@ -201,7 +223,9 @@ import { PrismaClient } from "./generated/client"; import { withAccelerate } from "@prisma/extension-accelerate"; // Instantiate the extended Prisma client to infer its type -const extendedPrisma = new PrismaClient().$extends(withAccelerate()); +const extendedPrisma = new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()); type ExtendedPrismaClient = typeof extendedPrisma; // Use globalThis for broader environment compatibility diff --git a/content/800-guides/150-multiple-databases.mdx b/content/800-guides/150-multiple-databases.mdx index f3dd98f223..854b33908c 100644 --- a/content/800-guides/150-multiple-databases.mdx +++ b/content/800-guides/150-multiple-databases.mdx @@ -121,7 +121,7 @@ Open `prisma-user-database/schema.prisma` file and update it to define a `User` ```prisma file=prisma-user-database/schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" //add-start output = "../prisma-user-database/user-database-client-types" //add-end @@ -129,12 +129,6 @@ generator client { datasource db { provider = "postgresql" - //delete-start - url = env("DATABASE_URL") - //delete-end - //add-start - url = env("PPG_USER_DATABASE_URL") - //add-end } //add-start @@ -146,6 +140,35 @@ model User { //add-end ``` +Create a `prisma.config.ts` file for the user database: + +```typescript file=prisma-user-database/prisma.config.ts +//add-start +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma-user-database/schema.prisma', + migrations: { + path: 'prisma-user-database/migrations', + }, + datasource: { + url: env('PPG_USER_DATABASE_URL'), + }, +}); +//add-end +``` + +:::note + +You'll need to install the `dotenv` package if you haven't already: + +```terminal +npm install dotenv +``` + +::: + Your user database schema is now ready. ### 2.2. Create a Prisma Postgres instance for post data @@ -178,7 +201,7 @@ Edit the `prisma-post-database/schema.prisma` file to define a `Post` model. Als ```prisma file=prisma-post-database/schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" //add-start output = "../prisma-post-database/post-database-client-types" //add-end @@ -186,23 +209,36 @@ generator client { datasource db { provider = "postgresql" - //delete-start - url = env("DATABASE_URL") - //delete-end - //add-start - url = env("PPG_POST_DATABASE_URL") - //add-end } //add-start model Post { id Int @id @default(autoincrement()) - title String + title String content String? } //add-end ``` +Create a `prisma.config.ts` file for the post database: + +```typescript file=prisma-post-database/prisma.config.ts +//add-start +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma-post-database/schema.prisma', + migrations: { + path: 'prisma-post-database/migrations', + }, + datasource: { + url: env('PPG_POST_DATABASE_URL'), + }, +}); +//add-end +``` + Your post database schema is now set. ### 2.3. Add helper scripts and migrate the schemas @@ -216,8 +252,8 @@ To simplify your workflow, add helper scripts to your `package.json` file that r "start": "next start", "lint": "next lint", // add-start - "postinstall": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine", - "generate": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine", + "postinstall": "npx prisma generate --schema ./prisma-user-database/schema.prisma && npx prisma generate --schema ./prisma-post-database/schema.prisma", + "generate": "npx prisma generate --schema ./prisma-user-database/schema.prisma && npx prisma generate --schema ./prisma-post-database/schema.prisma", "migrate": "npx prisma migrate dev --schema ./prisma-user-database/schema.prisma && npx prisma migrate dev --schema ./prisma-post-database/schema.prisma", "deploy": "npx prisma migrate deploy --schema ./prisma-user-database/schema.prisma && npx prisma migrate deploy --schema ./prisma-post-database/schema.prisma", "studio": "npx prisma studio --schema ./prisma-user-database/schema.prisma --port 5555 & npx prisma studio --schema ./prisma-post-database/schema.prisma --port 5556" @@ -225,11 +261,6 @@ To simplify your workflow, add helper scripts to your `package.json` file that r } ``` -:::info - -If you are not using a Prisma Postgres database, remove the `--no-engine` flag from the custom scripts above. - -::: Here is an explanation of the custom scripts: @@ -264,7 +295,9 @@ In `lib/user-prisma-client.ts`, add the following code: import { PrismaClient } from "../prisma-user-database/user-database-client-types"; import { withAccelerate } from "@prisma/extension-accelerate" -const getPrisma = () => new PrismaClient().$extends(withAccelerate()); +const getPrisma = () => new PrismaClient({ + accelerateUrl: process.env.PPG_USER_DATABASE_URL, +}).$extends(withAccelerate()); const globalForUserDBPrismaClient = global as unknown as { userDBPrismaClient: ReturnType; @@ -293,7 +326,9 @@ In `lib/post-prisma-client.ts`, add this code: import { PrismaClient } from "../prisma-post-database/post-database-client-types"; import { withAccelerate } from "@prisma/extension-accelerate" -const getPrisma = () => new PrismaClient().$extends(withAccelerate()); +const getPrisma = () => new PrismaClient({ + accelerateUrl: process.env.PPG_POST_DATABASE_URL, +}).$extends(withAccelerate()); const globalForPostDBPrismaClient = global as unknown as { postDBPrismaClient: ReturnType; @@ -385,8 +420,8 @@ Before starting the development server, note that if you are using Next.js `v15. "build": "next build", "start": "next start", "lint": "next lint", - "postinstall": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine", - "generate": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine", + "postinstall": "npx prisma generate --schema ./prisma-user-database/schema.prisma && npx prisma generate --schema ./prisma-post-database/schema.prisma", + "generate": "npx prisma generate --schema ./prisma-user-database/schema.prisma && npx prisma generate --schema ./prisma-post-database/schema.prisma", "migrate": "npx prisma migrate dev --schema ./prisma-user-database/schema.prisma && npx prisma migrate dev --schema ./prisma-post-database/schema.prisma", "deploy": "npx prisma migrate deploy --schema ./prisma-user-database/schema.prisma && npx prisma migrate deploy --schema ./prisma-post-database/schema.prisma", "studio": "npx prisma studio --schema ./prisma-user-database/schema.prisma --port 5555 & npx prisma studio --schema ./prisma-post-database/schema.prisma --port 5556" diff --git a/content/800-guides/160-tanstack-start.mdx b/content/800-guides/160-tanstack-start.mdx index 971908e4d4..85ce70c040 100644 --- a/content/800-guides/160-tanstack-start.mdx +++ b/content/800-guides/160-tanstack-start.mdx @@ -316,7 +316,7 @@ npm install @prisma/extension-accelerate @prisma/client dotenv ```terminal npm install prisma tsx --save-dev -npm install @prisma/client dotenv +npm install @prisma/client @prisma/adapter-pg dotenv ``` @@ -351,7 +351,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -390,7 +389,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -412,8 +410,15 @@ Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts import { PrismaClient, Prisma } from "../app/generated/prisma/client.js"; +import { PrismaPg } from "@prisma/adapter-pg"; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); const userData: Prisma.UserCreateInput[] = [ { @@ -468,7 +473,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -503,7 +507,9 @@ Set up the Prisma client like this: import { PrismaClient } from "../generated/prisma/client.js"; import { withAccelerate } from "@prisma/extension-accelerate"; -const prisma = new PrismaClient().$extends(withAccelerate()); +const prisma = new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()); export default prisma; ``` @@ -511,8 +517,15 @@ export default prisma; ```tsx file=src/lib/prisma.ts import { PrismaClient } from "../generated/prisma/client.js"; +import { PrismaPg } from "@prisma/adapter-pg"; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); export default prisma; ``` diff --git a/content/800-guides/170-react-router-7.mdx b/content/800-guides/170-react-router-7.mdx index 6cd1474854..7a8b96d633 100644 --- a/content/800-guides/170-react-router-7.mdx +++ b/content/800-guides/170-react-router-7.mdx @@ -56,7 +56,7 @@ npm install @prisma/extension-accelerate @prisma/client dotenv ```terminal npm install prisma tsx --save-dev -npm install @prisma/client dotenv +npm install @prisma/client @prisma/adapter-pg dotenv ``` @@ -90,7 +90,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -129,7 +128,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -151,8 +149,15 @@ Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts import { PrismaClient, Prisma } from "../app/generated/prisma/client.js"; +import { PrismaPg } from "@prisma/adapter-pg"; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); const userData: Prisma.UserCreateInput[] = [ { @@ -209,7 +214,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -246,7 +250,9 @@ const globalForPrisma = global as unknown as { prisma: PrismaClient } -const prisma = globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate()) +const prisma = globalForPrisma.prisma || new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()) if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma @@ -257,12 +263,19 @@ export default prisma ```typescript file=app/lib/prisma.ts import { PrismaClient } from "../generated/prisma/client.js"; +import { PrismaPg } from "@prisma/adapter-pg"; -const globalForPrisma = global as unknown as { +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const globalForPrisma = global as unknown as { prisma: PrismaClient } -const prisma = globalForPrisma.prisma || new PrismaClient() +const prisma = globalForPrisma.prisma || new PrismaClient({ + adapter, +}) if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma diff --git a/content/800-guides/180-solid-start.mdx b/content/800-guides/180-solid-start.mdx index 705eaf4a58..4efe665593 100644 --- a/content/800-guides/180-solid-start.mdx +++ b/content/800-guides/180-solid-start.mdx @@ -76,7 +76,7 @@ npm install @prisma/extension-accelerate @prisma/client dotenv ```terminal npm install prisma tsx --save-dev -npm install @prisma/client dotenv +npm install @prisma/client @prisma/adapter-pg dotenv ``` @@ -110,7 +110,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -149,7 +148,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -172,8 +170,15 @@ Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts import { PrismaClient, Prisma } from "../src/generated/prisma/client.js"; +import { PrismaPg } from "@prisma/adapter-pg"; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); const userData: Prisma.UserCreateInput[] = [ { @@ -230,7 +235,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -267,7 +271,9 @@ Add the following code to create a Prisma Client instance: import { PrismaClient } from "../src/generated/prisma/client.js"; import { withAccelerate } from "@prisma/extension-accelerate"; -const prisma = new PrismaClient().$extends(withAccelerate()); +const prisma = new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()); export default prisma; ``` @@ -276,8 +282,15 @@ export default prisma; ```typescript file=lib/prisma.ts import { PrismaClient } from "../src/generated/prisma/client.js"; +import { PrismaPg } from "@prisma/adapter-pg"; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); export default prisma; ``` diff --git a/content/800-guides/190-data-dog.mdx b/content/800-guides/190-data-dog.mdx index 41d7894df3..ef7b600aae 100644 --- a/content/800-guides/190-data-dog.mdx +++ b/content/800-guides/190-data-dog.mdx @@ -154,13 +154,12 @@ Now, open `prisma/schema.prisma` and update your generator block and models. Rep ```prisma file=prisma/schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" output = "../src/generated/prisma" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -182,6 +181,35 @@ model Post { //add-end ``` +Create a `prisma.config.ts` file to configure Prisma: + +```typescript file=prisma.config.ts +//add-start +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +//add-end +``` + +:::note + +You'll need to install the `dotenv` package if you haven't already: + +```terminal +npm install dotenv +``` + +::: + ### 2.3. Generate the Prisma Client and run migrations Generate the Prisma Client and apply your schema to your database: diff --git a/content/800-guides/190-sveltekit.mdx b/content/800-guides/190-sveltekit.mdx index 9031029e71..eba7f3fefc 100644 --- a/content/800-guides/190-sveltekit.mdx +++ b/content/800-guides/190-sveltekit.mdx @@ -70,7 +70,7 @@ npm install @prisma/extension-accelerate @prisma/client dotenv ```terminal npm install prisma tsx --save-dev -npm install @prisma/client dotenv +npm install @prisma/client @prisma/adapter-pg dotenv ``` @@ -104,7 +104,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -143,7 +142,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -165,8 +163,15 @@ Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts import { PrismaClient, Prisma } from "../src/generated/prisma/client.js"; +import { PrismaPg } from "@prisma/adapter-pg"; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); const userData: Prisma.UserCreateInput[] = [ { @@ -223,7 +228,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -264,7 +268,7 @@ import { DATABASE_URL } from '$env/static/private'; import { withAccelerate } from '@prisma/extension-accelerate'; const prisma = new PrismaClient({ - datasourceUrl: DATABASE_URL + accelerateUrl: DATABASE_URL }).$extends(withAccelerate()); export default prisma; @@ -275,9 +279,14 @@ export default prisma; ```tsx file=src/lib/prisma.ts import { PrismaClient } from '../generated/prisma/client.js'; import { DATABASE_URL } from '$env/static/private'; +import { PrismaPg } from '@prisma/adapter-pg'; + +const adapter = new PrismaPg({ + connectionString: DATABASE_URL, +}); const prisma = new PrismaClient({ - datasourceUrl: DATABASE_URL + adapter, }); export default prisma; diff --git a/content/800-guides/200-clerk-nextjs.mdx b/content/800-guides/200-clerk-nextjs.mdx index 4d4409fa5d..09e849de66 100644 --- a/content/800-guides/200-clerk-nextjs.mdx +++ b/content/800-guides/200-clerk-nextjs.mdx @@ -260,7 +260,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -286,6 +285,35 @@ model Post { This will create two models: `User` and `Post`, with a one-to-many relationship between them. +Create a `prisma.config.ts` file to configure Prisma: + +```typescript file=prisma.config.ts showLineNumbers +//add-start +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +//add-end +``` + +:::note + +You'll need to install the `dotenv` package: + +```terminal +npm install dotenv +``` + +::: + Now, run the following command to create the database tables and generate the Prisma Client: ```terminal @@ -314,7 +342,9 @@ const globalForPrisma = global as unknown as { }; const prisma = - globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate()); + globalForPrisma.prisma || new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; @@ -326,12 +356,19 @@ export default prisma; ```tsx file=lib/prisma.ts showLineNumbers //add-start import { PrismaClient } from "../app/generated/prisma"; +import { PrismaPg } from "@prisma/adapter-pg"; + +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); const globalForPrisma = global as unknown as { prisma: PrismaClient; }; -const prisma = globalForPrisma.prisma || new PrismaClient(); +const prisma = globalForPrisma.prisma || new PrismaClient({ + adapter, +}); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; diff --git a/content/800-guides/210-shopify.mdx b/content/800-guides/210-shopify.mdx index b8a9eca491..81c9e4afa9 100644 --- a/content/800-guides/210-shopify.mdx +++ b/content/800-guides/210-shopify.mdx @@ -85,6 +85,35 @@ model Session { } ``` +Create a `prisma.config.ts` file to configure Prisma: + +```typescript file=prisma.config.ts +//add-start +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +//add-end +``` + +:::note + +Since Shopify apps typically have dotenv pre-installed, you should already have access to it. If not, install it with: + +```terminal +npm install dotenv +``` + +::: + To enable your app to store notes for each product, let's add a new `ProductNote` model to your Prisma schema. This model will allow you to save and organize notes linked to individual products in your database through the `productGid` field. diff --git a/content/800-guides/220-astro.mdx b/content/800-guides/220-astro.mdx index ccd930ce0b..beae2a5d44 100644 --- a/content/800-guides/220-astro.mdx +++ b/content/800-guides/220-astro.mdx @@ -59,7 +59,7 @@ npm install @prisma/extension-accelerate @prisma/client dotenv ```terminal npm install prisma tsx --save-dev -npm install @prisma/client dotenv +npm install @prisma/client @prisma/adapter-pg dotenv ``` @@ -90,7 +90,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -130,7 +129,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -152,8 +150,15 @@ Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts import { PrismaClient, Prisma } from "../prisma/generated/client.js"; +import { PrismaPg } from "@prisma/adapter-pg"; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); const userData: Prisma.UserCreateInput[] = [ { @@ -223,7 +228,6 @@ export default defineConfig({ path: 'prisma/migrations', seed: `tsx prisma/seed.ts`, }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -276,7 +280,7 @@ import { PrismaClient } from "../../prisma/generated/client"; import { withAccelerate } from "@prisma/extension-accelerate"; const prisma = new PrismaClient({ - datasourceUrl: import.meta.env.DATABASE_URL, + accelerateUrl: import.meta.env.DATABASE_URL, }).$extends(withAccelerate()); export default prisma; @@ -286,9 +290,14 @@ export default prisma; ```typescript file=src/lib/prisma.ts import { PrismaClient } from "../../prisma/generated/client"; +import { PrismaPg } from "@prisma/adapter-pg"; + +const adapter = new PrismaPg({ + connectionString: import.meta.env.DATABASE_URL, +}); const prisma = new PrismaClient({ - datasourceUrl: import.meta.env.DATABASE_URL, + adapter, }); export default prisma; diff --git a/content/800-guides/230-betterauth-nextjs.mdx b/content/800-guides/230-betterauth-nextjs.mdx index 4907a37fa0..dbb8c590e2 100644 --- a/content/800-guides/230-betterauth-nextjs.mdx +++ b/content/800-guides/230-betterauth-nextjs.mdx @@ -67,7 +67,7 @@ npm install @prisma/extension-accelerate @prisma/client ```terminal npm install prisma --save-dev -npm install @prisma/client +npm install @prisma/client @prisma/adapter-pg ``` @@ -88,7 +88,36 @@ This will create: - A `.env` file containing the `DATABASE_URL` at the project root - An `output` directory for the generated Prisma Client as `better-auth/generated/prisma` -### 2.2. Configure the Prisma client generator +### 2.2. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +The `dotenv` package should already be installed as it's a Next.js dependency. If not, install it using: + +```bash +npm install dotenv +``` + +::: + +### 2.3. Generate the Prisma client Run the following command to create the database tables and generate the Prisma Client: @@ -96,7 +125,7 @@ Run the following command to create the database tables and generate the Prisma npx prisma generate ``` -### 2.3. Set up a global Prisma client +### 2.4. Set up a global Prisma client In the `src` directory, create a `lib` folder and a `prisma.ts` file inside it. This file will be used to create and export your Prisma Client instance. @@ -118,7 +147,9 @@ const globalForPrisma = global as unknown as { }; const prisma = - globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate()); + globalForPrisma.prisma || new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, + }).$extends(withAccelerate()); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; @@ -128,13 +159,20 @@ export default prisma; ```tsx file=src/lib/prisma.ts import { PrismaClient } from "@/generated/prisma"; +import { PrismaPg } from "@prisma/adapter-pg"; + +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); const globalForPrisma = global as unknown as { prisma: PrismaClient; }; const prisma = - globalForPrisma.prisma || new PrismaClient() + globalForPrisma.prisma || new PrismaClient({ + adapter, + }); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; @@ -325,8 +363,6 @@ With the new models in your schema, you need to update your database. Run a migr npx prisma migrate dev --name add-auth-models ``` -
- ## 4. Set up the API routes Better Auth needs an API endpoint to handle authentication requests like sign-in, sign-up, and sign-out. You'll create a catch-all API route in Next.js to handle all requests sent to `/api/auth/[...all]`. diff --git a/content/800-guides/300-supabase-accelerate.mdx b/content/800-guides/300-supabase-accelerate.mdx index a898071628..e319fc9c35 100644 --- a/content/800-guides/300-supabase-accelerate.mdx +++ b/content/800-guides/300-supabase-accelerate.mdx @@ -46,6 +46,33 @@ Update the file and set the `DATABASE_URL` to your Supabase connection string: DATABASE_URL="postgresql://postgres:[YOUR-PASSWORD]@db.nzpppscrldfwlzfalbrf.supabase.co:5432/postgres" ``` +Create a `prisma.config.ts` file to configure Prisma: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables: + +```bash +npm install dotenv +``` + +::: + ## 2. Introspect your database Next, run the following command to introspect your database and create your data model: @@ -58,7 +85,7 @@ This command reads your database schema and creates new models in your `schema.p :::note -If you want to use Prisma Migrate in the future, you also need to [baseline your database](/orm/prisma-migrate/workflows/baselining). +If you want to use Prisma Migrate in the future, you also need to [baseline your database](/orm/prisma-migrate/workflows/baselining). ::: @@ -95,16 +122,26 @@ DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=ey..." :::note -If you want to use Prisma Migrate with Prisma Accelerate, you can set the `directUrl` field on the `datasource` block: +If you want to use Prisma Migrate with Prisma Accelerate, you need to provide a direct database URL in your `prisma.config.ts` file. The Accelerate URL (starting with `prisma://`) is used for queries via PrismaClient, while the direct database URL is used for migrations. + +Update your `prisma.config.ts`: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; -```prisma file=schema.prisma -datasource db { - url = env("DATABASE_URL") // points to the connection pool for queries - directUrl = env("DIRECT_URL") // points to the database for migrations -} +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DIRECT_URL'), // Direct database URL for migrations + }, +}); ``` -Accordingly, you'll need to set the `DIRECT_URL` in your `.env` file: +And add the `DIRECT_URL` to your `.env` file: ```bash file=.env DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=ey..." @@ -118,10 +155,14 @@ DIRECT_URL="postgresql://postgres:[YOUR-PASSWORD]@db.nzpppscrldfwlzfalbrf.supaba With your Prisma schema in place, you can go ahead and generate Prisma Client: ``` -npx prisma generate --no-engine +npx prisma generate ``` -The `--no-engine` option is used to omit the [query engine](/orm/more/under-the-hood/engines) in the generated Prisma Client library. The query engine manages Prisma ORM's internal connection pool and is not needed when using Prisma Accelerate. +:::info + +In Prisma 7, the `--no-engine` flag is no longer required when using Prisma Accelerate. Previously, you would run `prisma generate --no-engine`, but now the standard `prisma generate` command works for all use cases. + +::: ## 6. Send queries through the connection pool @@ -131,7 +172,9 @@ In your application code, you now need to apply the Accelerate extension to your import { PrismaClient } from "./generated/prisma" import { withAccelerate } from "@prisma/extension-accelerate" -const prisma = new PrismaClient().$extends(withAccelerate()) +const prisma = new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()) ``` At this point, you can now start sending queries which will be routed through the connection pool to your database. \ No newline at end of file diff --git a/content/800-guides/310-neon-accelerate.mdx b/content/800-guides/310-neon-accelerate.mdx index 95d3b1987c..f353b515ea 100644 --- a/content/800-guides/310-neon-accelerate.mdx +++ b/content/800-guides/310-neon-accelerate.mdx @@ -46,6 +46,33 @@ Update the file and set the `DATABASE_URL` to your Neon connection string: DATABASE_URL="postgresql://neondb_owner:[YOUR-PASSWORD]@ep-lingering-hat-a2e7tkt3.eu-central-1.aws.neon.tech/neondb?sslmode=require" ``` +Create a `prisma.config.ts` file to configure Prisma: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables: + +```bash +npm install dotenv +``` + +::: + ## 2. Introspect your database Next, run the following command to introspect your database and create your data model: @@ -58,7 +85,7 @@ This command reads your database schema and creates new models in your `schema.p :::note -If you want to use Prisma Migrate in the future, you also need to [baseline your database](/orm/prisma-migrate/workflows/baselining). +If you want to use Prisma Migrate in the future, you also need to [baseline your database](/orm/prisma-migrate/workflows/baselining). ::: @@ -95,16 +122,26 @@ DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=ey..." :::note -If you want to use Prisma Migrate with Prisma Accelerate, you can set the `directUrl` field on the `datasource` block: +If you want to use Prisma Migrate with Prisma Accelerate, you need to provide a direct database URL in your `prisma.config.ts` file. The Accelerate URL (starting with `prisma://`) is used for queries via PrismaClient, while the direct database URL is used for migrations. + +Update your `prisma.config.ts`: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; -```prisma file=schema.prisma -datasource db { - url = env("DATABASE_URL") // points to the connection pool for queries - directUrl = env("DIRECT_URL") // points to the database for migrations -} +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DIRECT_URL'), // Direct database URL for migrations + }, +}); ``` -Accordingly, you'll need to set the `DIRECT_URL` in your `.env` file: +And add the `DIRECT_URL` to your `.env` file: ```bash file=.env DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=ey..." @@ -118,10 +155,14 @@ DIRECT_URL="postgresql://neondb_owner:[YOUR-PASSWORD]@ep-lingering-hat-a2e7tkt3. With your Prisma schema in place, you can go ahead and generate Prisma Client: ``` -npx prisma generate --no-engine +npx prisma generate ``` -The `--no-engine` option is used to omit the [query engine](/orm/more/under-the-hood/engines) in the generated Prisma Client library. The query engine manages Prisma ORM's internal connection pool and is not needed when using Prisma Accelerate. +:::info + +In Prisma 7, the `--no-engine` flag is no longer required when using Prisma Accelerate. Previously, you would run `prisma generate --no-engine`, but now the standard `prisma generate` command works for all use cases. + +::: ## 6. Send queries through the connection pool @@ -131,7 +172,9 @@ In your application code, you now need to apply the Accelerate extension to your import { PrismaClient } from "./generated/prisma" import { withAccelerate } from "@prisma/extension-accelerate" -const prisma = new PrismaClient().$extends(withAccelerate()) +const prisma = new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()) ``` At this point, you can now start sending queries which will be routed through the connection pool to your database. \ No newline at end of file diff --git a/content/800-guides/320-permit-io-access-control.mdx b/content/800-guides/320-permit-io-access-control.mdx index 39e3e7f688..5d13d0594c 100644 --- a/content/800-guides/320-permit-io-access-control.mdx +++ b/content/800-guides/320-permit-io-access-control.mdx @@ -47,7 +47,7 @@ npm init -y Install application and development dependencies: ```terminal -npm install express cors dotenv @prisma/client +npm install express cors dotenv @prisma/client @prisma/adapter-pg npm install -D prisma typescript tsx ``` @@ -174,7 +174,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model Project { @@ -211,7 +210,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -253,8 +251,15 @@ Create a new file at `scripts/seed.ts` and add the following: ```ts import { PrismaClient } from '../src/generated/prisma/client'; +import { PrismaPg } from '@prisma/adapter-pg'; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); async function main() { console.log('🌱 Seeding test data...'); @@ -455,11 +460,18 @@ Create a new file: `src/middleware/auth.middleware.ts` ```ts import { Request, Response, NextFunction } from 'express'; import { PrismaClient } from '../generated/prisma/client.js'; +import { PrismaPg } from '@prisma/adapter-pg'; import createPermitClientExtension from '@permitio/permit-prisma'; import { clientExtensionConfig } from '../config/permit-config'; +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + // Extend PrismaClient with Permit -const prisma = new PrismaClient().$extends( +const prisma = new PrismaClient({ + adapter, +}).$extends( createPermitClientExtension(clientExtensionConfig) ); diff --git a/content/800-guides/330-github-actions.mdx b/content/800-guides/330-github-actions.mdx index b89d46545b..3eb898d7a6 100644 --- a/content/800-guides/330-github-actions.mdx +++ b/content/800-guides/330-github-actions.mdx @@ -77,7 +77,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } model User { @@ -97,6 +96,36 @@ model Post { } ``` +Create a `prisma.config.ts` file to configure Prisma with seeding: + +```typescript file=prisma.config.ts +//add-start +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + seed: `tsx src/seed.ts`, + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +//add-end +``` + +:::note + +You'll need to install the `dotenv` package: + +```terminal +npm install dotenv +``` + +::: + ### 2.3. Run initial migration and generate client ```terminal @@ -114,7 +143,9 @@ import { withAccelerate } from "@prisma/extension-accelerate"; import { PrismaClient } from "../src/generated/prisma/client"; import "dotenv/config"; -const prisma = new PrismaClient().$extends(withAccelerate()); +const prisma = new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()); const userData = [ { diff --git a/content/800-guides/340-ai-sdk-nextjs.mdx b/content/800-guides/340-ai-sdk-nextjs.mdx index d59d18004d..4d00104062 100644 --- a/content/800-guides/340-ai-sdk-nextjs.mdx +++ b/content/800-guides/340-ai-sdk-nextjs.mdx @@ -62,7 +62,7 @@ npm install @prisma/extension-accelerate @prisma/client dotenv ```terminal npm install prisma tsx --save-dev -npm install @prisma/client dotenv +npm install @prisma/client @prisma/adapter-pg dotenv ``` @@ -90,13 +90,12 @@ In the `prisma/schema.prisma` file, add the following models: ```prisma file=prisma/schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" output = "../app/generated/prisma" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -140,7 +139,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -176,7 +174,9 @@ const globalForPrisma = global as unknown as { prisma: PrismaClient; }; -const prisma = globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate()); +const prisma = globalForPrisma.prisma || new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; @@ -187,12 +187,19 @@ export default prisma; ```tsx file=lib/prisma.ts import { PrismaClient } from "../app/generated/prisma/client"; +import { PrismaPg } from "@prisma/adapter-pg"; + +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); const globalForPrisma = global as unknown as { prisma: PrismaClient; }; -const prisma = globalForPrisma.prisma || new PrismaClient(); +const prisma = globalForPrisma.prisma || new PrismaClient({ + adapter, +}); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; diff --git a/content/800-guides/350-authjs-nextjs.mdx b/content/800-guides/350-authjs-nextjs.mdx index 2bf14e647b..3ccf3160e7 100644 --- a/content/800-guides/350-authjs-nextjs.mdx +++ b/content/800-guides/350-authjs-nextjs.mdx @@ -63,7 +63,7 @@ npm install @prisma/extension-accelerate @prisma/client dotenv ```terminal npm install prisma tsx --save-dev -npm install @prisma/client dotenv +npm install @prisma/client @prisma/adapter-pg dotenv ``` @@ -100,7 +100,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } ``` @@ -187,7 +186,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -217,7 +215,9 @@ const globalForPrisma = global as unknown as { prisma: PrismaClient } -const prisma = globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate()) +const prisma = globalForPrisma.prisma || new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()) if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma @@ -230,12 +230,19 @@ export default prisma ```typescript file=lib/prisma.ts showLineNumbers //add-start import { PrismaClient } from '../app/generated/prisma' +import { PrismaPg } from '@prisma/adapter-pg' -const globalForPrisma = global as unknown as { +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}) + +const globalForPrisma = global as unknown as { prisma: PrismaClient } -const prisma = globalForPrisma.prisma || new PrismaClient() +const prisma = globalForPrisma.prisma || new PrismaClient({ + adapter, +}) if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma diff --git a/content/800-guides/360-embed-studio-nextjs.mdx b/content/800-guides/360-embed-studio-nextjs.mdx index 2b117d1664..dc50f894fb 100644 --- a/content/800-guides/360-embed-studio-nextjs.mdx +++ b/content/800-guides/360-embed-studio-nextjs.mdx @@ -80,7 +80,7 @@ Install the required Prisma packages: ```terminal npm install prisma tsx --save-dev -npm install @prisma/extension-accelerate @prisma/client dotenv +npm install @prisma/extension-accelerate @prisma/client @prisma/adapter-pg dotenv ``` ### 2.2. Initialize Prisma with Prisma Postgres @@ -117,7 +117,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -157,7 +156,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -181,8 +179,15 @@ Create a seed file to add some sample data. Create a `seed.ts` file in the `pris ```typescript file=prisma/seed.ts import { PrismaClient } from '../app/generated/prisma' +import { PrismaPg } from '@prisma/adapter-pg' -const prisma = new PrismaClient() +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}) + +const prisma = new PrismaClient({ + adapter, +}) async function main() { // Create users @@ -243,7 +248,6 @@ export default defineConfig({ path: 'prisma/migrations', seed: `tsx prisma/seed.ts`, }, - engine: 'classic', datasource: { url: env('DIRECT_URL'), }, diff --git a/content/800-guides/370-bun.mdx b/content/800-guides/370-bun.mdx index fd90ceac90..00fdfa1ad3 100644 --- a/content/800-guides/370-bun.mdx +++ b/content/800-guides/370-bun.mdx @@ -43,7 +43,7 @@ Install the required Prisma packages and other dependencies: ```terminal bun add -d prisma -bun add @prisma/client +bun add @prisma/client @prisma/adapter-pg ``` ### 2.2. Initialize Prisma ORM with Prisma Postgres @@ -100,7 +100,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -120,8 +119,15 @@ Create a `db.ts` file in your project root to configure `PrismaClient`: ```typescript file=db.ts import { PrismaClient } from "./generated/prisma/client"; +import { PrismaPg } from "@prisma/adapter-pg"; -export const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +export const prisma = new PrismaClient({ + adapter, +}); ``` ### 3.2. Create a seed script @@ -130,8 +136,15 @@ Create a seed script in the `prisma` folder to populate your database with sampl ```typescript file=prisma/seed.ts import { PrismaClient } from "../generated/prisma/client"; +import { PrismaPg } from "@prisma/adapter-pg"; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); async function main() { // Create multiple users @@ -169,16 +182,17 @@ main() Add the following content to the file: ```typescript file=prisma.config.ts +import 'dotenv/config' import { defineConfig, env } from 'prisma/config'; + export default defineConfig({ schema: 'prisma/schema.prisma', - migrations: { - path: 'prisma/migrations', + migrations: { + path: 'prisma/migrations', // add-start - seed: `bun run prisma/seed.ts` + seed: `bun run prisma/seed.ts` //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, diff --git a/content/800-guides/390-hono.mdx b/content/800-guides/390-hono.mdx index 40df95a5b9..f87d00968c 100644 --- a/content/800-guides/390-hono.mdx +++ b/content/800-guides/390-hono.mdx @@ -48,7 +48,7 @@ npm install @prisma/extension-accelerate @prisma/client dotenv ```terminal npm install prisma --save-dev -npm install @prisma/client dotenv +npm install @prisma/client @prisma/adapter-pg dotenv ``` @@ -80,7 +80,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -106,17 +105,17 @@ This creates two models: `User` and `Post`, with a one-to-many relationship betw In `prisma.config.ts`, import `dotenv` at the top of the file -```ts +```typescript file=prisma.config.ts import { defineConfig, env } from "prisma/config"; // add-start import "dotenv/config"; // add-end + export default defineConfig({ schema: "prisma/schema.prisma", migrations: { path: "prisma/migrations", }, - engine: "classic", datasource: { url: env("DATABASE_URL"), }, @@ -138,8 +137,15 @@ Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts import { PrismaClient, Prisma } from "../src/generated/prisma/client.js"; +import { PrismaPg } from "@prisma/adapter-pg"; + +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); -const prisma = new PrismaClient(); +const prisma = new PrismaClient({ + adapter, +}); const userData: Prisma.UserCreateInput[] = [ { @@ -192,9 +198,10 @@ main() Now, tell Prisma how to run this script by updating your `prisma.config.ts`: -```ts file=prisma.config.ts +```typescript file=prisma.config.ts import { defineConfig, env } from "prisma/config"; import "dotenv/config"; + export default defineConfig({ schema: "prisma/schema.prisma", migrations: { @@ -203,7 +210,6 @@ export default defineConfig({ seed: "tsx prisma/seed.ts" //add-end }, - engine: "classic", datasource: { url: env("DATABASE_URL"), }, @@ -244,7 +250,7 @@ function withPrisma(c: Context, next: Next) { if (!databaseUrl) { throw new Error('DATABASE_URL is not set'); } - const prisma = new PrismaClient({ datasourceUrl: databaseUrl }) + const prisma = new PrismaClient({ accelerateUrl: databaseUrl }) .$extends(withAccelerate()); c.set('prisma', prisma); @@ -261,13 +267,19 @@ export default withPrisma; ```tsx file=src/lib/prisma.ts import type { Context, Next } from 'hono'; import { PrismaClient } from '../generated/prisma/client.js'; +import { PrismaPg } from '@prisma/adapter-pg'; import "dotenv/config"; const databaseUrl = process.env.DATABASE_URL; if (!databaseUrl) { throw new Error('DATABASE_URL is not set'); } -const prisma = new PrismaClient({ datasourceUrl: databaseUrl }); + +const adapter = new PrismaPg({ + connectionString: databaseUrl, +}); + +const prisma = new PrismaClient({ adapter }); function withPrisma(c: Context, next: Next) { if (!c.get('prisma')) { diff --git a/content/800-guides/400-deno-integration.mdx b/content/800-guides/400-deno-integration.mdx index b0b10fe407..f6c7c8cefe 100644 --- a/content/800-guides/400-deno-integration.mdx +++ b/content/800-guides/400-deno-integration.mdx @@ -132,7 +132,6 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") } // add-start diff --git a/content/800-guides/999-making-guides.mdx b/content/800-guides/999-making-guides.mdx index b8d2a04f8f..49ee775e9f 100644 --- a/content/800-guides/999-making-guides.mdx +++ b/content/800-guides/999-making-guides.mdx @@ -94,9 +94,17 @@ Example: ```typescript file=src/index.ts // Import required dependencies import { PrismaClient } from '@prisma/client' +import { PrismaPg } from '@prisma/adapter-pg' + +// Initialize adapter +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}) // Initialize Prisma Client -const prisma = new PrismaClient() +const prisma = new PrismaClient({ + adapter, +}) ``` ### Formatting conventions @@ -314,13 +322,12 @@ In addition, update the text above this and add "*and change the generator to us ```prisma file=prisma/schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" output = "../generated/prisma" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } //add-start @@ -344,14 +351,47 @@ model Post { This creates two models: `User` and `Post`, with a one-to-many relationship between them. -### 2.3. Configure the Prisma Client generator +### 2.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=prisma.config.ts +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables: + +```bash +npm install dotenv +``` + +::: + +:::warning +***DEV NOTE:*** If your guide includes database seeding, you'll update this config file later to add the `seed` field in the migrations section. See the seeding section below for an example. +::: + +### 2.4. Generate Prisma Client and run migrations Now, run the following command to create the database tables and generate the Prisma Client: ```terminal npx prisma migrate dev --name init ``` -### 2.4. Seed the database +### 2.5. Seed the database Add some seed data to populate the database with sample users and posts. @@ -359,8 +399,15 @@ Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts import { PrismaClient, Prisma } from "../generated/prisma"; +import { PrismaPg } from "@prisma/adapter-pg"; -const prisma = new PrismaClient(); +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); + +const prisma = new PrismaClient({ + adapter, +}); const userData: Prisma.UserCreateInput[] = [ { @@ -404,16 +451,24 @@ export async function main() { main(); ``` -Now, tell Prisma how to run this script by updating your `package.json`: +Create a `prisma.config.ts` file to configure Prisma with seeding: -```json file=package.json -... rest of the file +```typescript file=prisma.config.ts //add-start -"prisma": { - "seed": "tsx prisma/seed.ts" -} +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + seed: `tsx prisma/seed.ts`, + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); //add-end -... rest of the file ``` Run the seed script: From 05b7cb0e1710d87e3544e907bcbf679547ee6d77 Mon Sep 17 00:00:00 2001 From: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> Date: Mon, 17 Nov 2025 16:21:10 +0600 Subject: [PATCH 12/23] feat: update ppg for other dbs section (#7264) * feat: add kysley * feat: add drizzle * feat: add typeorm * fix: clean-up * feat: separate the sections better * fix: remove badges --- .../100-quickstart/100-prisma-postgres.mdx | 1 - .../100-quickstart/200-sqlite.mdx | 1 - .../100-quickstart/300-postgresql.mdx | 1 - .../100-quickstart/400-mysql.mdx | 1 - .../100-quickstart/500-sql-server.mdx | 1 - .../100-quickstart/600-planetscale.mdx | 1 - .../100-quickstart/700-cockroachdb.mdx | 1 - .../100-quickstart/800-mongodb.mdx | 1 - .../100-prisma-postgres.mdx | 1 - .../200-sqlite.mdx | 1 - .../300-postgresql.mdx | 1 - .../200-add-to-existing-project/400-mysql.mdx | 1 - .../500-sql-server.mdx | 1 - .../600-planetscale.mdx | 1 - .../700-cockroachdb.mdx | 1 - .../800-mongodb.mdx | 1 - .../100-quickstart/100-kysely.mdx | 256 ++++++++++++----- .../100-quickstart/200-drizzle-orm.mdx | 261 +++++++++--------- .../100-quickstart/300-typeorm.mdx | 258 +++++++++-------- .../100-quickstart/50-prisma-orm.mdx | 80 ++---- .../225-import-from-existing-database.mdx | 14 - .../200-import-from-existing-database.mdx | 2 +- sidebars.ts | 95 ++----- src/css/custom.css | 8 + static/_redirects | 1 + 25 files changed, 490 insertions(+), 501 deletions(-) delete mode 100644 content/250-postgres/100-introduction/225-import-from-existing-database.mdx diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx index c73c259d73..c28b1f4514 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx @@ -3,7 +3,6 @@ title: 'Quickstart with Prisma ORM and Prisma Postgres' sidebar_label: 'Prisma Postgres' metaTitle: 'Quickstart: Prisma ORM with Prisma Postgres (5 min)' metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to Prisma Postgres and generating a Prisma Client for database access.' -sidebar_custom_props: { badge: '5 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx index b4dcb6abf4..f04dc1ca00 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx @@ -3,7 +3,6 @@ title: 'Quickstart with Prisma ORM and SQLite' sidebar_label: 'SQLite' metaTitle: 'Quickstart: Prisma ORM with SQLite (5 min)' metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to SQLite and generating a Prisma Client for database access.' -sidebar_custom_props: { badge: '5 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx index 53f3352521..2d31c50999 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx @@ -3,7 +3,6 @@ title: 'Quickstart with Prisma ORM and PostgreSQL' sidebar_label: 'PostgreSQL' metaTitle: 'Quickstart: Prisma ORM with PostgreSQL (10 min)' metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to PostgreSQL and generating a Prisma Client for database access.' -sidebar_custom_props: { badge: '10 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx index 8edc3e72df..6a02d9858b 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx @@ -3,7 +3,6 @@ title: 'Quickstart with Prisma ORM and MySQL' sidebar_label: 'MySQL' metaTitle: 'Quickstart: Prisma ORM with MySQL (10 min)' metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to MySQL and generating a Prisma Client for database access.' -sidebar_custom_props: { badge: '10 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx index f78be99bca..b7c23969ef 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx @@ -3,7 +3,6 @@ title: 'Quickstart with Prisma ORM and SQL Server' sidebar_label: 'SQL Server' metaTitle: 'Quickstart: Prisma ORM with SQL Server (10 min)' metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to SQL Server and generating a Prisma Client for database access.' -sidebar_custom_props: { badge: '10 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx index d6c4752fb5..f5836d6792 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx @@ -3,7 +3,6 @@ title: 'Quickstart with Prisma ORM and PlanetScale' sidebar_label: 'PlanetScale' metaTitle: 'Quickstart: Prisma ORM with PlanetScale MySQL (10 min)' metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to PlanetScale MySQL and generating a Prisma Client for database access.' -sidebar_custom_props: { badge: '10 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx index 8768122e43..f227598dc7 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx @@ -3,7 +3,6 @@ title: 'Quickstart with Prisma ORM and CockroachDB' sidebar_label: 'CockroachDB' metaTitle: 'Quickstart: Prisma ORM with CockroachDB (10 min)' metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to CockroachDB and generating a Prisma Client for database access.' -sidebar_custom_props: { badge: '10 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx index a3594ba48e..13b0375a2e 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx @@ -3,7 +3,6 @@ title: 'Quickstart with Prisma ORM and MongoDB' sidebar_label: 'MongoDB' metaTitle: 'Quickstart: Prisma ORM with MongoDB (10 min)' metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to MongoDB and generating a Prisma Client for database access.' -sidebar_custom_props: { badge: '10 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx index e6585e83b8..07b5149aaf 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx @@ -3,7 +3,6 @@ title: 'Add Prisma ORM to an existing Prisma Postgres project' sidebar_title: 'Prisma Postgres' metaTitle: 'How to add Prisma ORM to an existing project using Prisma Postgres (15 min)' metaDescription: 'Add Prisma ORM to an existing TypeScript project with Prisma Postgres and learn database introspection, baselining, and querying.' -sidebar_custom_props: { badge: '15 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx index e9d5d66134..9109da70fe 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx @@ -3,7 +3,6 @@ title: 'Add Prisma ORM to an existing SQLite project' sidebar_title: 'SQLite' metaTitle: 'How to add Prisma ORM to an existing project using SQLite (15 min)' metaDescription: 'Add Prisma ORM to an existing TypeScript project with SQLite and learn database introspection, baselining, and querying.' -sidebar_custom_props: { badge: '15 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx index 46deacf6c4..4c9160e611 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx @@ -3,7 +3,6 @@ title: 'Add Prisma ORM to an existing PostgreSQL project' sidebar_title: 'PostgreSQL' metaTitle: 'How to add Prisma ORM to an existing project using PostgreSQL (15 min)' metaDescription: 'Add Prisma ORM to an existing TypeScript project with PostgreSQL and learn database introspection, baselining, and querying.' -sidebar_custom_props: { badge: '15 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/400-mysql.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/400-mysql.mdx index 6830a8aa8c..ada30bc3ff 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/400-mysql.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/400-mysql.mdx @@ -3,7 +3,6 @@ title: 'Add Prisma ORM to an existing MySQL project' sidebar_title: 'MySQL' metaTitle: 'How to add Prisma ORM to an existing project using MySQL (15 min)' metaDescription: 'Add Prisma ORM to an existing TypeScript project with MySQL and learn database introspection, baselining, and querying.' -sidebar_custom_props: { badge: '15 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx index ca420d5d2b..0ae3bd823d 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx @@ -3,7 +3,6 @@ title: 'Add Prisma ORM to an existing SQL Server project' sidebar_title: 'SQL Server' metaTitle: 'How to add Prisma ORM to an existing project using SQL Server (15 min)' metaDescription: 'Add Prisma ORM to an existing TypeScript project with SQL Server and learn database introspection, baselining, and querying.' -sidebar_custom_props: { badge: '15 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/600-planetscale.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/600-planetscale.mdx index 66bf9be2f2..73a77b3044 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/600-planetscale.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/600-planetscale.mdx @@ -3,7 +3,6 @@ title: 'Add Prisma ORM to an existing PlanetScale project' sidebar_title: 'PlanetScale' metaTitle: 'How to add Prisma ORM to an existing project using PlanetScale MySQL (15 min)' metaDescription: 'Add Prisma ORM to an existing TypeScript project with PlanetScale MySQL and learn database introspection and querying.' -sidebar_custom_props: { badge: '15 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx index 8e6215d96a..7908afe4a6 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx @@ -3,7 +3,6 @@ title: 'Add Prisma ORM to an existing CockroachDB project' sidebar_title: 'CockroachDB' metaTitle: 'How to add Prisma ORM to an existing project using CockroachDB (15 min)' metaDescription: 'Add Prisma ORM to an existing TypeScript project with CockroachDB and learn database introspection, baselining, and querying.' -sidebar_custom_props: { badge: '15 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx index 7fc993a4c7..b0cf0e76b9 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx @@ -3,7 +3,6 @@ title: 'Add Prisma ORM to an existing MongoDB project' sidebar_title: 'MongoDB' metaTitle: 'How to add Prisma ORM to an existing project using MongoDB (15 min)' metaDescription: 'Add Prisma ORM to an existing TypeScript project with MongoDB and learn database introspection and querying.' -sidebar_custom_props: { badge: '15 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' diff --git a/content/100-getting-started/03-prisma-postgres/100-quickstart/100-kysely.mdx b/content/100-getting-started/03-prisma-postgres/100-quickstart/100-kysely.mdx index 1b2b1ff247..65d686208f 100644 --- a/content/100-getting-started/03-prisma-postgres/100-quickstart/100-kysely.mdx +++ b/content/100-getting-started/03-prisma-postgres/100-quickstart/100-kysely.mdx @@ -3,107 +3,222 @@ title: 'Use Prisma Postgres with Kysely' sidebar_label: 'Kysely' metaTitle: 'Quickstart: Kysely with Prisma Postgres (10 min)' metaDescription: 'Get started with Kysely and Prisma Postgres by creating a type-safe SQL query builder for your database.' -sidebar_custom_props: { badge: '10 min' } --- -[Kysely](https://kysely.dev) is a type-safe TypeScript SQL query builder that provides excellent TypeScript support and a fluent API for building SQL queries. In this guide, you'll learn how to connect Kysely to [Prisma Postgres](/postgres) and start querying your database with full type safety. +[Kysely](https://kysely.dev) is a type-safe TypeScript SQL query builder that provides TypeScript support and a fluent API for building SQL queries. In this guide, you'll learn how to connect Kysely to [Prisma Postgres](/postgres) and start querying your database with full type safety. ## Prerequisites -- **Node.js** - Version 14 or higher -- **TypeScript** - Version 4.6 or higher (5.4+ recommended for better type inference) -- A [Prisma Data Platform](https://console.prisma.io) account -- (Optional) **Kysely setup** - If you already have Kysely configured in your project, skip to [step 2](#2-get-your-direct-connection-string) +- Node.js version 14 or higher +- TypeScript version 4.6 or higher (5.4+ recommended for improved type inference, 5.9+ for better compilation performance) +- Strict mode enabled in your `tsconfig.json` for Kysely's type safety -For detailed Kysely installation and configuration, see the [Kysely Getting started guide](https://kysely.dev/docs/getting-started). +## 1. Create a new project -## 1. Create a Prisma Postgres database +Create a new directory for your project and initialize it with npm: -Follow these steps to create your Prisma Postgres database: +```terminal +mkdir kysely-quickstart +cd kysely-quickstart +npm init -y +``` -1. Log in to [Prisma Data Platform](https://console.prisma.io) and open the Console. -2. In a workspace of your choice, click the **New project** button. -3. Type a name for your project in the **Name** field, e.g. `kysely-quickstart`. -4. In the **Prisma Postgres** section, click the **Get started** button. -5. In the **Region** dropdown, select the region that's closest to your current location, e.g. US East (N. Virginia). -6. Click the **Create project** button. +Install TypeScript and initialize it: -At this point, you'll be redirected to the Database page where you will need to wait for a few seconds while the status of your database changes from **PROVISIONING** to **CONNECTED**. +```terminal +npm install --save-dev typescript +npx tsc --init +``` -Once the green **CONNECTED** label appears, your database is ready to use! +## 2. Configure TypeScript + +Kysely requires TypeScript's strict mode for proper type safety. Update your `tsconfig.json` file: + +```json file=tsconfig.json +{ + // ... + "compilerOptions": { + // ... + // add-start + "strict": true, + "allowImportingTsExtensions": true, + "noEmit": true + // add-end + // ... + } + // ... +} +``` + +:::note -## 2. Get your direct connection string +The `strict: true` setting is **required** for Kysely's type safety to work correctly. -To connect to Prisma Postgres via direct TCP, you need to: +::: -1. Open your project in the Prisma Console. -2. Navigate to your active Prisma Postgres instance. -3. Click the **API Keys** tab in the project's sidenav. -4. Click the **Create API key** button. -5. In the popup, provide a **Name** for the API key and click **Create**. -6. Copy the connection string starting with `postgres://`, this is your direct connection string. +In your `package.json`, set the `type` to `module`: + +```json +{ +// ... +// add-start +"type": "module" +// add-end +// ... +} +``` -## 3. Create a new project +## 3. Create a Prisma Postgres database -Create a new directory for your project and initialize it: +You can create a Prisma Postgres database using the `create-db` CLI tool. Follow these steps to create your Prisma Postgres database: ```terminal -mkdir kysely-quickstart -cd kysely-quickstart -npm init -y +npx create-db +``` + +Then the CLI tool should output: + +```terminal +┌ 🚀 Creating a Prisma Postgres database +│ +│ Provisioning a temporary database in us-east-1... +│ +│ It will be automatically deleted in 24 hours, but you can claim it. +│ +◇ Database created successfully! +│ +│ +● Database Connection +│ +│ +│ Connection String: +│ +│ postgresql://hostname:password@db.prisma.io:5432/postgres?sslmode=require +│ +│ +◆ Claim Your Database +│ +│ Keep your database for free: +│ +│ https://create-db.prisma.io/claim?CLAIM_CODE +│ +│ Database will be deleted on 11/18/2025, 1:55:39 AM if not claimed. +│ +└ +``` + +Create a `.env` file and add the connection string from the output: + +```env file=.env +DATABASE_URL="postgresql://hostname:password@db.prisma.io:5432/postgres?sslmode=require" +``` + +:::warning + +**Never commit `.env` files to version control.** Add `.env` to your `.gitignore` file to keep credentials secure. + +::: + +The database created is temporary and will be deleted in 24 hours unless claimed. Claiming moves the database into your [Prisma Data Platform](https://console.prisma.io) account. Visit the claim URL from the output to keep your database. + +:::note + +To learn more about the `create-db` CLI tool, see the [create-db documentation](/postgres/introduction/npx-create-db). + +::: + +## 4. Install dependencies + +Install Kysely and the PostgreSQL driver: + +```terminal +npm install kysely pg dotenv +npm install --save-dev @types/pg tsx ``` -## 4. Configure Kysely with Prisma Postgres +**Package breakdown:** +- `kysely`: The type-safe SQL query builder +- `pg`: PostgreSQL driver for Node.js (required by Kysely's PostgresDialect) +- `dotenv`: Loads environment variables from `.env` file +- `@types/pg`: TypeScript type definitions for the pg driver +- `tsx`: TypeScript execution engine for running `.ts` files directly + +## 5. Define database types -Create a database connection file that uses your Prisma Postgres connection string: +Create a `src/types.ts` file to define your database schema types: +```typescript file=src/types.ts +import type { Generated } from "kysely"; -```typescript file=database.ts +export interface Database { + users: UsersTable; +} + +export interface UsersTable { + id: Generated; + email: string; + name: string | null; +} +``` + +## 6. Configure database connection + +Create a `src/database.ts` file to instantiate Kysely with your Prisma Postgres connection: + +```typescript file=src/database.ts +import 'dotenv/config' +import type { Database } from './types.ts' import { Pool } from 'pg' import { Kysely, PostgresDialect } from 'kysely' +// Parse DATABASE_URL into connection parameters +function parseConnectionString(url: string) { + const parsed = new URL(url) + return { + host: parsed.hostname, + port: parseInt(parsed.port), + user: parsed.username, + password: parsed.password, + database: parsed.pathname.slice(1), // Remove leading '/' + } +} + +const connectionParams = parseConnectionString(process.env.DATABASE_URL!) + const dialect = new PostgresDialect({ pool: new Pool({ - connectionString: process.env.DATABASE_URL, + ...connectionParams, + ssl: true, max: 10, }) }) -// Define your database interface -interface Database { - users: { - id: number - email: string - name: string | null - } - posts: { - id: number - title: string - content: string | null - published: boolean - author_id: number - } -} - +// Database interface is passed to Kysely's constructor, and from now on, Kysely +// knows your database structure. +// Dialect is passed to Kysely's constructor, and from now on, Kysely knows how +// to communicate with your database. export const db = new Kysely({ dialect, }) ``` -Create a `.env` file and add your Prisma Postgres connection string: - -```env file=.env -DATABASE_URL="postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require" -``` - -## 5. Use Kysely with Prisma Postgres +## 7. Run queries -Now you can use Kysely to query your Prisma Postgres database: +Create a `src/script.ts` file: -```typescript file=script.ts -import { db } from './database' +```typescript file=src/script.ts +import { db } from './database.ts' async function main() { + // Create the users table + await db.schema + .createTable('users') + .ifNotExists() + .addColumn('id', 'serial', (col) => col.primaryKey()) + .addColumn('email', 'varchar(255)', (col) => col.notNull().unique()) + .addColumn('name', 'varchar(255)') + .execute() + // Insert a user const user = await db .insertInto('users') @@ -136,16 +251,19 @@ main() }) ``` -## Next steps +Run the script: + +```terminal +npx tsx src/script.ts +``` -Now that you have Kysely connected to Prisma Postgres, you can: +You should receive the following output: -- **Learn more about Kysely** - Check out the [Kysely documentation](https://kysely.dev/docs/intro) for advanced query patterns -- **Explore migrations** - Learn about [Kysely migrations](https://kysely.dev/docs/migrations) for managing schema changes -- **Add more complex queries** - Explore [joins](https://kysely.dev/docs/category/join), [subqueries](https://kysely.dev/docs/examples/join/subquery-join), and [transactions](https://kysely.dev/docs/category/transactions) +```terminal +Created user: { id: 1, email: 'alice@prisma.io', name: 'Alice' } +All users: [ { id: 1, email: 'alice@prisma.io', name: 'Alice' } ] +``` -## More info +## Next steps -- [Kysely documentation](https://kysely.dev) -- [Prisma Postgres documentation](/postgres) -- [PostgreSQL driver documentation](https://node-postgres.com) +You've successfully connected Kysely to Prisma Postgres! For more advanced features like schemas, migrations, and complex queries, see the [Kysely documentation](https://kysely.dev/docs/intro). diff --git a/content/100-getting-started/03-prisma-postgres/100-quickstart/200-drizzle-orm.mdx b/content/100-getting-started/03-prisma-postgres/100-quickstart/200-drizzle-orm.mdx index c729d66565..7066de2857 100644 --- a/content/100-getting-started/03-prisma-postgres/100-quickstart/200-drizzle-orm.mdx +++ b/content/100-getting-started/03-prisma-postgres/100-quickstart/200-drizzle-orm.mdx @@ -2,192 +2,187 @@ title: 'Use Prisma Postgres with Drizzle ORM' sidebar_label: 'Drizzle ORM' metaTitle: 'Quickstart: Drizzle ORM with Prisma Postgres (10 min)' -metaDescription: 'Get started with Drizzle ORM and Prisma Postgres by creating a lightweight, performant TypeScript ORM for your database.' -sidebar_custom_props: { badge: '10 min' } +metaDescription: 'Get started with Drizzle ORM and Prisma Postgres.' --- -[Drizzle ORM](https://orm.drizzle.team) is a lightweight and performant TypeScript ORM with developer experience in mind. It provides a SQL-like syntax with full TypeScript support and excellent performance. In this guide, you'll learn how to connect Drizzle ORM to [Prisma Postgres](/postgres) and start building type-safe database queries. +[Drizzle ORM](https://orm.drizzle.team) is a TypeScript ORM. In this guide, you'll learn how to connect Drizzle ORM to [Prisma Postgres](/postgres). ## Prerequisites -- **Node.js** - Version 16 or higher -- **TypeScript** - Version 5.0 or higher -- A [Prisma Data Platform](https://console.prisma.io) account -- (Optional) **Drizzle ORM setup** - If you already have Drizzle configured in your project, skip to [step 2](#2-get-your-direct-connection-string) +- Node.js version 16 or higher +- TypeScript version 5.0 or higher -For detailed Drizzle ORM installation and configuration, see the [Drizzle ORM Getting started guide](https://orm.drizzle.team/docs/get-started-postgresql). +## 1. Create a new project -## 1. Create a Prisma Postgres database +Create a new directory for your project and initialize it with npm: -Follow these steps to create your Prisma Postgres database: +```terminal +mkdir drizzle-quickstart +cd drizzle-quickstart +npm init -y +``` -1. Log in to [Prisma Data Platform](https://console.prisma.io) and open the Console. -2. In a workspace of your choice, click the **New project** button. -3. Type a name for your project in the **Name** field, e.g. `drizzle-quickstart`. -4. In the **Prisma Postgres** section, click the **Get started** button. -5. In the **Region** dropdown, select the region that's closest to your current location, e.g. US East (N. Virginia). -6. Click the **Create project** button. +Install TypeScript and initialize it: -At this point, you'll be redirected to the Database page where you will need to wait for a few seconds while the status of your database changes from **PROVISIONING** to **CONNECTED**. +```terminal +npm install --save-dev typescript +npx tsc --init +``` -Once the green **CONNECTED** label appears, your database is ready to use! +In your `package.json`, set the `type` to `module`: -## 2. Get your direct connection string +```json file=package.json +{ + // ... + // add-start + "type": "module" + // add-end + // ... +} +``` -To connect to Prisma Postgres via direct TCP, you need to: +## 2. Create a Prisma Postgres database -1. Open your project in the Prisma Console. -2. Navigate to your active Prisma Postgres instance. -3. Click the **API Keys** tab in the project's sidenav. -4. Click the **Create API key** button. -5. In the popup, provide a **Name** for the API key and click **Create**. -6. Copy the connection string starting with `postgres://`, this is your direct connection string. +You can create a Prisma Postgres database using the `create-db` CLI tool. Follow these steps to create your Prisma Postgres database: -## 3. Create a new project +```terminal +npx create-db +``` -Create a new directory for your project and initialize it: +Then the CLI tool should output: ```terminal -mkdir drizzle-quickstart -cd drizzle-quickstart -npm init -y +┌ 🚀 Creating a Prisma Postgres database +│ +│ Provisioning a temporary database in us-east-1... +│ +│ It will be automatically deleted in 24 hours, but you can claim it. +│ +◇ Database created successfully! +│ +│ +● Database Connection +│ +│ +│ Connection String: +│ +│ postgresql://hostname:password@db.prisma.io:5432/postgres?sslmode=require +│ +│ +◆ Claim Your Database +│ +│ Keep your database for free: +│ +│ https://create-db.prisma.io/claim?CLAIM_CODE +│ +│ Database will be deleted on 11/18/2025, 1:55:39 AM if not claimed. +│ +└ ``` -## 4. Configure Drizzle ORM with Prisma Postgres +Create a `.env` file and add the connection string from the output: -Define your database schema using Drizzle's schema definition: +```env file=.env +DATABASE_URL="postgresql://hostname:password@db.prisma.io:5432/postgres?sslmode=require" +``` +:::warning -```typescript file=schema.ts -import { pgTable, serial, text, varchar, boolean, timestamp, integer } from 'drizzle-orm/pg-core' -import { relations } from 'drizzle-orm' +**Never commit `.env` files to version control.** Add `.env` to your `.gitignore` file to keep credentials secure. -export const users = pgTable('users', { - id: serial('id').primaryKey(), - email: varchar('email', { length: 255 }).notNull().unique(), - name: text('name'), - createdAt: timestamp('created_at').defaultNow().notNull(), -}) +::: -export const posts = pgTable('posts', { - id: serial('id').primaryKey(), - title: varchar('title', { length: 255 }).notNull(), - content: text('content'), - published: boolean('published').default(false).notNull(), - authorId: integer('author_id') - .notNull() - .references(() => users.id, { onDelete: 'cascade' }), - createdAt: timestamp('created_at').defaultNow().notNull(), -}) +The database created is temporary and will be deleted in 24 hours unless claimed. Claiming moves the database into your [Prisma Data Platform](https://console.prisma.io) account. Visit the claim URL from the output to keep your database. -// Define relations -export const usersRelations = relations(users, ({ many }) => ({ - posts: many(posts), -})) - -export const postsRelations = relations(posts, ({ one }) => ({ - author: one(users, { - fields: [posts.authorId], - references: [users.id], - }), -})) -``` +:::note -Configure Drizzle Kit with your Prisma Postgres connection string: +To learn more about the `create-db` CLI tool, see the [create-db documentation](/postgres/introduction/npx-create-db). -```typescript file=drizzle.config.ts -import { defineConfig } from 'drizzle-kit' +::: -export default defineConfig({ - schema: './schema.ts', - out: './drizzle', - dialect: 'postgresql', - dbCredentials: { - url: process.env.DATABASE_URL!, - }, -}) -``` +## 3. Install dependencies -Create a `.env` file and add your Prisma Postgres connection string: +Install Drizzle ORM and the PostgreSQL driver: -```env file=.env -DATABASE_URL="postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require" +```terminal +npm install drizzle-orm pg dotenv +npm install --save-dev drizzle-kit @types/pg tsx ``` -Create a database connection file: +**Package breakdown:** +- `drizzle-orm`: The lightweight TypeScript ORM +- `pg`: PostgreSQL driver for Node.js +- `dotenv`: Loads environment variables from `.env` file +- `drizzle-kit`: CLI tool for migrations and schema management +- `@types/pg`: TypeScript type definitions for the pg driver +- `tsx`: TypeScript execution engine for running `.ts` files directly + +## 4. Run a query + +Create a `src/script.ts` file: -```typescript file=db.ts +```typescript file=src/script.ts +import 'dotenv/config' import { drizzle } from 'drizzle-orm/node-postgres' import { Pool } from 'pg' -import * as schema from './schema' const pool = new Pool({ connectionString: process.env.DATABASE_URL, }) -export const db = drizzle({ client: pool, schema }) -``` - -## 5. Use Drizzle ORM with Prisma Postgres - -Generate and push your schema to the database: - -```terminal -npx drizzle-kit push -``` - -Now you can use Drizzle ORM to query your Prisma Postgres database: - -```typescript file=script.ts -import { db } from './db' -import { users, posts } from './schema' -import { eq } from 'drizzle-orm' +const db = drizzle({ client: pool }) async function main() { - // Insert a user - const [user] = await db - .insert(users) - .values({ - name: 'Alice', - email: 'alice@prisma.io', - }) - .returning() - - console.log('Created user:', user) - - // Query users with their posts - const usersWithPosts = await db.query.users.findMany({ - with: { - posts: true, - }, - }) - - console.log('Users with posts:', JSON.stringify(usersWithPosts, null, 2)) + const result = await db.execute('select 1') + console.log('Query result:', result) } main() - .then(() => { - console.log('Done!') - process.exit(0) + .then(async () => { + await pool.end() + console.log('Connection closed') }) - .catch((error) => { + .catch(async (error) => { console.error('Error:', error) + await pool.end() process.exit(1) }) ``` -## Next steps +Run the script: + +```terminal +npx tsx src/script.ts +``` -Now that you have Drizzle ORM connected to Prisma Postgres, you can: +You should receive output similar to: -- **Learn more about Drizzle** - Check out the [Drizzle ORM documentation](https://orm.drizzle.team/docs/overview) for advanced features -- **Explore queries** - Learn about [select queries](https://orm.drizzle.team/docs/select), [joins](https://orm.drizzle.team/docs/joins), and [transactions](https://orm.drizzle.team/docs/transactions) -- **Manage migrations** - Explore [Drizzle Kit migrations](https://orm.drizzle.team/docs/migrations) for schema management -- **Use relational queries** - Take advantage of [Drizzle's relational query API](https://orm.drizzle.team/docs/rqb) for cleaner code +```terminal +Query result: Result { + command: 'SELECT', + rowCount: 1, + oid: null, + rows: [ { '?column?': 1 } ], + fields: [ + Field { + name: '?column?', + tableID: 0, + columnID: 0, + dataTypeID: 23, + dataTypeSize: 4, + dataTypeModifier: -1, + format: 'text' + } + ], + _parsers: [ [Function: parseInteger] ], + _types: { getTypeParser: [Function: getTypeParser] }, + RowCtor: null, + rowAsArray: false, + _prebuiltEmptyResultObject: { '?column?': null } +} +Connection closed +``` -## More info +## Next steps -- [Drizzle ORM documentation](https://orm.drizzle.team) -- [Drizzle ORM GitHub repository](https://github.com/drizzle-team/drizzle-orm) -- [Prisma Postgres documentation](/postgres) -- [Drizzle Kit documentation](https://orm.drizzle.team/kit-docs/overview) +You've successfully connected Drizzle ORM to Prisma Postgres! For more advanced features like schemas, migrations, and queries, see the [Drizzle ORM documentation](https://orm.drizzle.team/docs/get-started). diff --git a/content/100-getting-started/03-prisma-postgres/100-quickstart/300-typeorm.mdx b/content/100-getting-started/03-prisma-postgres/100-quickstart/300-typeorm.mdx index ff923f02cc..bbcc4469df 100644 --- a/content/100-getting-started/03-prisma-postgres/100-quickstart/300-typeorm.mdx +++ b/content/100-getting-started/03-prisma-postgres/100-quickstart/300-typeorm.mdx @@ -3,183 +3,179 @@ title: 'Use Prisma Postgres with TypeORM' sidebar_label: 'TypeORM' metaTitle: 'Quickstart: TypeORM with Prisma Postgres (10 min)' metaDescription: 'Get started with TypeORM and Prisma Postgres by connecting your TypeScript ORM to a managed PostgreSQL database.' -sidebar_custom_props: { badge: '10 min' } --- -[TypeORM](https://typeorm.io) is a feature-rich ORM that supports both Active Record and Data Mapper patterns, providing flexibility in how you structure your database code. In this guide, you'll learn how to connect TypeORM to [Prisma Postgres](/postgres) and start building type-safe database applications. +[TypeORM](https://typeorm.io) is a TypeScript ORM. In this guide, you'll learn how to connect TypeORM to [Prisma Postgres](/postgres). ## Prerequisites -- **Node.js** - Version 16 or higher -- **TypeScript** - Version 4.5 or higher -- A [Prisma Data Platform](https://console.prisma.io) account -- (Optional) **TypeORM setup** - If you already have TypeORM configured in your project, skip to [step 2](#2-get-your-direct-connection-string) +- Node.js version 16 or higher +- TypeScript version 4.5 or higher -For detailed TypeORM installation and configuration, see the [TypeORM Getting started guide](https://typeorm.io/docs/getting-started/). +## 1. Generate a TypeORM project -## 1. Create a Prisma Postgres database +Use the TypeORM CLI to generate a starter project: -Follow these steps to create your Prisma Postgres database: +```terminal +npx typeorm init --name typeorm-quickstart --database postgres +``` -1. Log in to [Prisma Data Platform](https://console.prisma.io) and open the Console. -2. In a workspace of your choice, click the **New project** button. -3. Type a name for your project in the **Name** field, e.g. `typeorm-quickstart`. -4. In the **Prisma Postgres** section, click the **Get started** button. -5. In the **Region** dropdown, select the region that's closest to your current location, e.g. US East (N. Virginia). -6. Click the **Create project** button. +This command will generate a new project with the following structure: -At this point, you'll be redirected to the Database page where you will need to wait for a few seconds while the status of your database changes from **PROVISIONING** to **CONNECTED**. +``` +typeorm-quickstart +├── src +│ ├── entity +│ │ └── User.ts # Sample entity +│ ├── migration # Migrations folder +│ ├── data-source.ts # Data source configuration +│ └── index.ts # Application entry point +├── .gitignore +├── package.json +├── README.md +└── tsconfig.json +``` -Once the green **CONNECTED** label appears, your database is ready to use! +## 2. Install dependencies -## 2. Get your direct connection string +Navigate to the project directory and install dependencies: -To connect to Prisma Postgres via direct TCP, you need to: +```terminal +cd typeorm-quickstart +npm install +``` -1. Open your project in the Prisma Console. -2. Navigate to your active Prisma Postgres instance. -3. Click the **API Keys** tab in the project's sidenav. -4. Click the **Create API key** button. -5. In the popup, provide a **Name** for the API key and click **Create**. -6. Copy the connection string starting with `postgres://`, this is your direct connection string. +Install dotenv to load environment variables: -## 3. Configure TypeORM with Prisma Postgres +```terminal +npm install dotenv +``` -Update your TypeORM DataSource configuration to use your Prisma Postgres connection string. In your `data-source.ts` (or equivalent configuration file): +## 3. Create a Prisma Postgres database -```typescript file=data-source.ts -import "reflect-metadata" -import { DataSource } from "typeorm" -import { User } from "./entity/User" -import { Post } from "./entity/Post" +You can create a Prisma Postgres database using the `create-db` CLI tool. Follow these steps to create your Prisma Postgres database: -export const AppDataSource = new DataSource({ - type: "postgres", - url: process.env.DATABASE_URL, // Your Prisma Postgres connection string - synchronize: true, // Set to false in production - logging: false, - entities: [User, Post], - migrations: [], - subscribers: [], -}) +```terminal +npx create-db ``` -Create a `.env` file and add your Prisma Postgres connection string: +Then the CLI tool should output: -```env file=.env -DATABASE_URL="postgres://USER:PASSWORD@db.prisma.io:5432/?sslmode=require" +```terminal +┌ 🚀 Creating a Prisma Postgres database +│ +│ Provisioning a temporary database in us-east-1... +│ +│ It will be automatically deleted in 24 hours, but you can claim it. +│ +◇ Database created successfully! +│ +│ +● Database Connection +│ +│ +│ Connection String: +│ +│ postgresql://hostname:password@db.prisma.io:5432/postgres?sslmode=require +│ +│ +◆ Claim Your Database +│ +│ Keep your database for free: +│ +│ https://create-db.prisma.io/claim?CLAIM_CODE +│ +│ Database will be deleted on 11/18/2025, 1:55:39 AM if not claimed. +│ +└ ``` -:::tip - -For production applications, set `synchronize: false` and use [TypeORM migrations](https://typeorm.io/docs/migrations/setup) to manage schema changes safely. +Create a `.env` file and add the connection string from the output: -::: +```env file=.env +DATABASE_URL="postgresql://hostname:password@db.prisma.io:5432/postgres?sslmode=require" +``` -## 4. Define your entities +:::warning -Create your TypeORM entities as usual. Here's an example with User and Post entities: +**Never commit `.env` files to version control.** Add `.env` to your `.gitignore` file to keep credentials secure. -```typescript file=entity/User.ts -import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm" -import { Post } from "./Post" +::: -@Entity() -export class User { - @PrimaryGeneratedColumn() - id: number +The database created is temporary and will be deleted in 24 hours unless claimed. Claiming moves the database into your [Prisma Data Platform](https://console.prisma.io) account. Visit the claim URL from the output to keep your database. - @Column({ unique: true }) - email: string +:::note - @Column({ nullable: true }) - name: string +To learn more about the `create-db` CLI tool, see the [create-db documentation](/postgres/introduction/npx-create-db). - @OneToMany(() => Post, (post) => post.author) - posts: Post[] -} -``` +::: -```typescript file=entity/Post.ts -import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm" -import { User } from "./User" +## 4. Configure database connection -@Entity() -export class Post { - @PrimaryGeneratedColumn() - id: number +Update the `src/data-source.ts` file to use your Prisma Postgres connection: - @Column() - title: string +```typescript file=src/data-source.ts +import "reflect-metadata" +// add-start +import "dotenv/config"; +// add-end +import { DataSource } from "typeorm" +import { User } from "./entity/User" - @Column({ type: "text", nullable: true }) - content: string +// add-start +// Parse DATABASE_URL into connection parameters +function parseConnectionString(url: string) { + const parsed = new URL(url) + return { + host: parsed.hostname, + port: parseInt(parsed.port), + username: parsed.username, + password: parsed.password, + database: parsed.pathname.slice(1), // Remove leading '/' + } +} - @Column({ default: false }) - published: boolean +const connectionParams = parseConnectionString(process.env.DATABASE_URL!) +// add-end - @ManyToOne(() => User, (user) => user.posts) - author: User -} +export const AppDataSource = new DataSource({ + type: "postgres", + // delete-start + host: "localhost", + port: 5432, + username: "test", + password: "test", + database: "test", + // delete-end + // add-start + ...connectionParams, + ssl: true, + // add-end + synchronize: true, + logging: false, + entities: [User], + migrations: [], + subscribers: [], +}) ``` -For more information on defining entities, see the [TypeORM Entities documentation](https://typeorm.io/docs/entity/entities). - -## 5. Initialize and use TypeORM +## 5. Run the application -Initialize your DataSource and start querying: +Start the application: -```typescript file=index.ts -import "reflect-metadata" -import { AppDataSource } from "./data-source" -import { User } from "./entity/User" -import { Post } from "./entity/Post" - -AppDataSource.initialize() - .then(async () => { - console.log("Connected to Prisma Postgres!") - - // Create a user with a post - const user = new User() - user.email = "alice@prisma.io" - user.name = "Alice" - await AppDataSource.manager.save(user) - - const post = new Post() - post.title = "Hello World" - post.content = "This is my first post!" - post.published = true - post.author = user - await AppDataSource.manager.save(post) - - console.log("Created user and post!") - - // Query users with their posts - const users = await AppDataSource.getRepository(User).find({ - relations: { - posts: true, - }, - }) - - console.log("Users with posts:", JSON.stringify(users, null, 2)) - }) - .catch((error) => console.log("Error:", error)) +```terminal +npm start ``` -Run your application: +You should see output indicating the connection was successful and a new user was inserted into the database: ```terminal -npx tsx index.ts +Inserting a new user into the database... +Saved a new user with id: 1 +Loading users from the database... +Loaded users: [ User { id: 1, firstName: 'Timber', lastName: 'Saw', age: 25 } ] ``` ## Next steps -Now that you have TypeORM connected to Prisma Postgres, you can: - -- **Learn more about TypeORM** - Check out the [TypeORM documentation](https://typeorm.io/docs/) for comprehensive guides - -## More info - -- [TypeORM documentation](https://typeorm.io) -- [Prisma Postgres documentation](/postgres) -- [TypeORM PostgreSQL driver documentation](https://typeorm.io/docs/drivers/postgres/) +You've successfully connected TypeORM to Prisma Postgres! For more advanced features like entities, migrations, and queries, see the [TypeORM documentation](https://typeorm.io/docs/getting-started). diff --git a/content/100-getting-started/03-prisma-postgres/100-quickstart/50-prisma-orm.mdx b/content/100-getting-started/03-prisma-postgres/100-quickstart/50-prisma-orm.mdx index d774affd78..d7bc02afd6 100644 --- a/content/100-getting-started/03-prisma-postgres/100-quickstart/50-prisma-orm.mdx +++ b/content/100-getting-started/03-prisma-postgres/100-quickstart/50-prisma-orm.mdx @@ -3,7 +3,6 @@ title: 'Use Prisma Postgres with Prisma ORM' sidebar_label: 'Prisma ORM' metaTitle: 'Quickstart: Prisma ORM with Prisma Postgres (5 min)' metaDescription: 'Create a new TypeScript project from scratch by connecting Prisma ORM to Prisma Postgres and generating a Prisma Client for database access.' -sidebar_custom_props: { badge: '5 min' } --- import Prerequisites from '../../_components/_prerequisites.mdx' @@ -17,37 +16,11 @@ import NextSteps from '../../_components/_next-steps.mdx' -## 1. Create a Prisma Postgres database - -Follow these steps to create your Prisma Postgres database: - -1. Log in to [Prisma Data Platform](https://console.prisma.io) and open the Console. -2. In a workspace of your choice, click the **New project** button. -3. Type a name for your project in the **Name** field, e.g. `hello-ppg`. -4. In the **Prisma Postgres** section, click the **Get started** button. -5. In the **Region** dropdown, select the region that's closest to your current location, e.g. US East (N. Virginia). -6. Click the **Create project** button. - -At this point, you'll be redirected to the Database page where you will need to wait for a few seconds while the status of your database changes from **PROVISIONING** to **CONNECTED**. - -Once the green **CONNECTED** label appears, your database is ready to use! - -## 2. Get your direct connection string - -To connect to Prisma Postgres via direct TCP, you need to: - -1. Open your project in the Prisma Console. -2. Navigate to your active Prisma Postgres instance. -3. Click the **API Keys** tab in the project's sidenav. -4. Click the **Create API key** button. -5. In the popup, provide a **Name** for the API key and click **Create**. -6. Copy the connection string starting with `postgres://`, this is your direct connection string. - -## 3. Create a new project +## 1. Create a new project -## 4. Install required dependencies +## 2. Install required dependencies Install the packages needed for this quickstart: @@ -63,7 +36,7 @@ Here's what each package does: - **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database - **`dotenv`** - Loads environment variables from your `.env` file -## 5. Configure ESM support +## 3. Configure ESM support Update `tsconfig.json` for ESM compatibility: @@ -90,49 +63,28 @@ Update `package.json` to enable ESM: } ``` -## 6. Initialize Prisma ORM +## 4. Initialize Prisma ORM and create a Prisma Postgres database -You can now invoke the Prisma CLI by prefixing it with `npx`: +Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: ```terminal -npx prisma +npx prisma init --db --output ../generated/prisma ``` -Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: +:::info -```terminal -npx prisma init --output ../generated/prisma -``` +You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database. + +::: This command does a few things: - Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a new Prisma Postgres database (when using `--db` flag) - Creates a `.env` file in the root directory for environment variables - Generates the Prisma Client in the `generated/prisma/` directory - Creates a `prisma.config.ts` file for Prisma configuration -Add your Prisma Postgres direct connection string to the `.env` file: - -```env file=.env -DATABASE_URL="postgres://your-connection-string" -``` - -The generated `prisma.config.ts` file looks like this: - -```typescript file=prisma.config.ts -import { defineConfig, env } from 'prisma/config' - -export default defineConfig({ - schema: 'prisma/schema.prisma', - migrations: { - path: 'prisma/migrations', - }, - datasource: { - url: env('DATABASE_URL'), - }, -}) -``` - Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: ```typescript file=prisma.config.ts @@ -165,7 +117,7 @@ datasource db { } ``` -## 7. Define your data model +## 5. Define your data model Open `prisma/schema.prisma` and add the following models: @@ -198,7 +150,7 @@ model Post { //add-end ``` -## 8. Create and apply your first migration +## 6. Create and apply your first migration Create your first migration to set up the database tables: @@ -214,7 +166,7 @@ Now run the following command to generate the Prisma Client: npx prisma generate ``` -## 9. Instantiate Prisma Client +## 7. Instantiate Prisma Client Now that you have all the dependencies installed, you can instantiate Prisma Client. You need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: @@ -231,7 +183,7 @@ const prisma = new PrismaClient({ adapter }) export { prisma } ``` -## 10. Write your first query +## 8. Write your first query Create a `script.ts` file to test your setup: @@ -286,7 +238,7 @@ npx tsx script.ts You should see the created user and all users printed to the console! -## 11. Explore your data with Prisma Studio +## 9. Explore your data with Prisma Studio diff --git a/content/250-postgres/100-introduction/225-import-from-existing-database.mdx b/content/250-postgres/100-introduction/225-import-from-existing-database.mdx deleted file mode 100644 index 7420adf337..0000000000 --- a/content/250-postgres/100-introduction/225-import-from-existing-database.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: 'Import data from an existing PostgreSQL database' -sidebar_label: 'Import from existing database' -metaTitle: 'Import from existing Postgres database into Prisma Postgres' -metaDescription: 'Learn how to import data from an existing database into Prisma Postgres.' -tocDepth: 3 -toc: true -search: true ---- - -If you have an existing database and want to import your data into Prisma Postgres, you can use one of our guides: - -- [Import from PostgreSQL](/getting-started/prisma-postgres/import-from-existing-database-postgresql) -- [Import from MySQL](/getting-started/prisma-postgres/import-from-existing-database-mysql) \ No newline at end of file diff --git a/content/250-postgres/50-getting-started/200-import-from-existing-database.mdx b/content/250-postgres/50-getting-started/200-import-from-existing-database.mdx index e72aa23fdf..9d4cdd5ecf 100644 --- a/content/250-postgres/50-getting-started/200-import-from-existing-database.mdx +++ b/content/250-postgres/50-getting-started/200-import-from-existing-database.mdx @@ -8,4 +8,4 @@ hide_table_of_contents: true import { Redirect } from '@docusaurus/router'; - \ No newline at end of file + \ No newline at end of file diff --git a/sidebars.ts b/sidebars.ts index da2972ced2..b5c9e63729 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -82,65 +82,41 @@ const sidebars: SidebarsConfig = { type: "doc", id: "getting-started/prisma-orm/quickstart/prisma-postgres", label: "Prisma Postgres", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/quickstart/mysql", label: "MySQL", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/quickstart/postgresql", label: "PostgreSQL", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/quickstart/sqlite", label: "SQLite", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/quickstart/sql-server", label: "SQL Server", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/quickstart/planetscale", label: "PlanetScale", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/quickstart/cockroachdb", label: "CockroachDB", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/quickstart/mongodb", label: "MongoDB", - customProps: { - badge: "5 Min", - }, }, ], }, @@ -162,65 +138,41 @@ const sidebars: SidebarsConfig = { type: "doc", id: "getting-started/prisma-orm/add-to-existing-project/prisma-postgres", label: "Prisma Postgres", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/add-to-existing-project/mysql", label: "MySQL", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/add-to-existing-project/postgresql", label: "PostgreSQL", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/add-to-existing-project/sqlite", label: "SQLite", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/add-to-existing-project/sql-server", label: "SQL Server", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/add-to-existing-project/planetscale", label: "PlanetScale", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/add-to-existing-project/cockroachdb", label: "CockroachDB", - customProps: { - badge: "5 Min", - }, }, { type: "doc", id: "getting-started/prisma-orm/add-to-existing-project/mongodb", label: "MongoDB", - customProps: { - badge: "5 Min", - }, }, ], }, @@ -254,33 +206,30 @@ const sidebars: SidebarsConfig = { type: "doc", id: "getting-started/prisma-postgres/quickstart/prisma-orm", label: "Prisma ORM", - customProps: { - badge: "5 Min", - }, }, { - type: "doc", - id: "getting-started/prisma-postgres/quickstart/kysely", - label: "Kysely", - customProps: { - badge: "10 Min", - }, - }, - { - type: "doc", - id: "getting-started/prisma-postgres/quickstart/drizzle-orm", - label: "Drizzle ORM", - customProps: { - badge: "10 Min", - }, - }, - { - type: "doc", - id: "getting-started/prisma-postgres/quickstart/typeorm", - label: "TypeORM", - customProps: { - badge: "10 Min", - }, + type: "category", + label: "Other tools", + collapsed: false, + collapsible: false, + className: "sidebar-item-normal-weight", + items: [ + { + type: "doc", + id: "getting-started/prisma-postgres/quickstart/kysely", + label: "Kysely", + }, + { + type: "doc", + id: "getting-started/prisma-postgres/quickstart/drizzle-orm", + label: "Drizzle ORM", + }, + { + type: "doc", + id: "getting-started/prisma-postgres/quickstart/typeorm", + label: "TypeORM", + }, + ], }, ], }, diff --git a/src/css/custom.css b/src/css/custom.css index 5ff447caf1..b301f3eb07 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -1827,4 +1827,12 @@ kbd.DocSearch-Commands-Key { .theme-doc-sidebar-item-category .menu__list .sidebar-item-normal-weight a.menu__link--active { font-weight: 600 !important; +} + +/* Make category labels with normal weight class have normal font weight and size */ +.theme-doc-sidebar-item-category.sidebar-item-normal-weight > .menu__list-item-collapsible > .menu__link, +.theme-doc-sidebar-item-category .sidebar-item-normal-weight > .menu__list-item-collapsible > .menu__link { + font-weight: normal !important; + font-size: 14px !important; + line-height: 1.25 !important; } \ No newline at end of file diff --git a/static/_redirects b/static/_redirects index c90e320673..875bdece14 100644 --- a/static/_redirects +++ b/static/_redirects @@ -821,5 +821,6 @@ /getting-started/prisma-postgres/upgrade-from-early-access* /docs/postgres/getting-started +/postgres/introduction/import-from-existing-database* /docs/getting-started/prisma-postgres/import-from-existing-database-postgresql ### NO REDIRECTS BELOW THIS LINE. ADD REDIRECTS ABOVE THIS SECTION ### From 5c857d72a2688d702477b24e50f3e14825f38667 Mon Sep 17 00:00:00 2001 From: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> Date: Mon, 17 Nov 2025 19:27:00 +0600 Subject: [PATCH 13/23] feat: update prisma init related changes in other parts (#7267) * feat: add kysley * feat: add drizzle * feat: add typeorm * fix: clean-up * fix: update prisma init command changes * feat: update prisma cli docs * fix: clarify the usage of prisma init better * fix: add type defs * feat: add pg as a dependency * fix: broken internal link --- .../100-quickstart/100-prisma-postgres.mdx | 6 +- .../100-quickstart/200-sqlite.mdx | 10 +- .../100-quickstart/300-postgresql.mdx | 6 +- .../100-quickstart/500-sql-server.mdx | 3 +- .../100-quickstart/700-cockroachdb.mdx | 6 +- .../100-prisma-postgres.mdx | 6 +- .../200-sqlite.mdx | 3 +- .../300-postgresql.mdx | 6 +- .../500-sql-server.mdx | 3 +- .../700-cockroachdb.mdx | 6 +- .../03-prisma-postgres/100-from-the-cli.mdx | 45 ++- ...15-import-from-existing-database-mysql.mdx | 1 - .../500-databases/200-database-drivers.mdx | 43 ++- .../500-databases/300-postgresql.mdx | 26 +- .../050-overview/500-databases/400-mysql.mdx | 28 +- .../050-overview/500-databases/500-sqlite.mdx | 50 ++-- .../500-databases/800-sql-server/index.mdx | 1 + .../100-queries/037-relation-queries.mdx | 6 +- .../050-prisma-client-reference.mdx | 2 +- .../200-prisma-cli-reference.mdx | 272 +++++++++++++++--- .../350-integrations/100-netlify.mdx | 2 +- .../30-docs-components/01-mdx-examples.mdx | 105 ++++--- 22 files changed, 456 insertions(+), 180 deletions(-) diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx index c28b1f4514..a5cb227c42 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx @@ -25,8 +25,8 @@ import NextSteps from '../../_components/_next-steps.mdx' Install the packages needed for this quickstart: ```terminal -npm install prisma @types/node --save-dev -npm install @prisma/client @prisma/adapter-pg dotenv +npm install prisma @types/node @types/pg --save-dev +npm install @prisma/client @prisma/adapter-pg pg dotenv ``` Here's what each package does: @@ -34,6 +34,8 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`pg`** - The node-postgres database driver +- **`@types/pg`** - TypeScript type definitions for node-postgres - **`dotenv`** - Loads environment variables from your `.env` file ## 3. Configure ESM support diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx index f04dc1ca00..14f227368c 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx @@ -27,7 +27,7 @@ In this guide, you will learn how to set up a new TypeScript project from scratc Install the packages needed for this quickstart: ```terminal -npm install prisma @types/node --save-dev +npm install prisma @types/node @types/better-sqlite3 --save-dev npm install @prisma/client @prisma/adapter-better-sqlite3 dotenv ``` @@ -36,6 +36,7 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-better-sqlite3`** - The SQLite driver adapter that connects Prisma Client to your database +- **`@types/better-sqlite3`** - TypeScript type definitions for better-sqlite3 - **`dotenv`** - Loads environment variables from your `.env` file ## 3. Configure ESM support @@ -93,16 +94,13 @@ import { defineConfig, env } from 'prisma/config' export default defineConfig({ schema: 'prisma/schema.prisma', - migrations: { - path: 'prisma/migrations', - }, datasource: { url: env('DATABASE_URL'), }, }) ``` -Add `dotenv` to `prisma.config.ts` so that Prisma can load environment variables from your `.env` file: +Add `dotenv` and migrations configuration to `prisma.config.ts`: ```typescript file=prisma.config.ts // add-start @@ -112,9 +110,11 @@ import { defineConfig, env } from 'prisma/config' export default defineConfig({ schema: 'prisma/schema.prisma', + // add-start migrations: { path: 'prisma/migrations', }, + // add-end datasource: { url: env('DATABASE_URL'), }, diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx index 2d31c50999..bb7b117053 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx @@ -36,8 +36,8 @@ If you don't already have a PostgreSQL database, follow the quickstart to set up Install the packages needed for this quickstart: ```terminal -npm install prisma @types/node --save-dev -npm install @prisma/client @prisma/adapter-pg dotenv +npm install prisma @types/node @types/pg --save-dev +npm install @prisma/client @prisma/adapter-pg pg dotenv ``` Here's what each package does: @@ -45,6 +45,8 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`pg`** - The node-postgres database driver +- **`@types/pg`** - TypeScript type definitions for node-postgres - **`dotenv`** - Loads environment variables from your `.env` file ## 3. Configure ESM support diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx index b7c23969ef..9083dff2f1 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx @@ -32,7 +32,7 @@ You also need: Install the packages needed for this quickstart: ```terminal -npm install prisma @types/node --save-dev +npm install prisma @types/node @types/mssql --save-dev npm install @prisma/client @prisma/adapter-mssql dotenv ``` @@ -41,6 +41,7 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-mssql`** - The SQL Server driver adapter that connects Prisma Client to your database +- **`@types/mssql`** - TypeScript type definitions for mssql - **`dotenv`** - Loads environment variables from your `.env` file ## 3. Configure ESM support diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx index f227598dc7..601a6a775b 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx @@ -30,8 +30,8 @@ You also need: Install the packages needed for this quickstart: ```terminal -npm install prisma @types/node --save-dev -npm install @prisma/client @prisma/adapter-pg dotenv +npm install prisma @types/node @types/pg --save-dev +npm install @prisma/client @prisma/adapter-pg pg dotenv ``` Here's what each package does: @@ -39,6 +39,8 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma migrate`, and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database (CockroachDB is PostgreSQL-compatible) +- **`pg`** - The node-postgres database driver +- **`@types/pg`** - TypeScript type definitions for node-postgres - **`dotenv`** - Loads environment variables from your `.env` file ## 3. Configure ESM support diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx index 07b5149aaf..f415afdace 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/100-prisma-postgres.mdx @@ -20,8 +20,8 @@ import NextSteps from '../../_components/_next-steps.mdx' Navigate to your existing project directory and install the required dependencies: ```terminal -npm install prisma @types/node --save-dev -npm install @prisma/client @prisma/adapter-pg dotenv +npm install prisma @types/node @types/pg --save-dev +npm install @prisma/client @prisma/adapter-pg pg dotenv ``` Here's what each package does: @@ -29,6 +29,8 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`pg`** - The node-postgres database driver +- **`@types/pg`** - TypeScript type definitions for node-postgres - **`dotenv`** - Loads environment variables from your `.env` file ## 2. Initialize Prisma ORM diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx index 9109da70fe..4829c9be51 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx @@ -20,7 +20,7 @@ import NextSteps from '../../_components/_next-steps.mdx' Navigate to your existing project directory and install the required dependencies: ```terminal -npm install prisma @types/node --save-dev +npm install prisma @types/node @types/better-sqlite3 --save-dev npm install @prisma/client @prisma/adapter-better-sqlite3 dotenv ``` @@ -29,6 +29,7 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-better-sqlite3`** - The SQLite driver adapter that connects Prisma Client to your database +- **`@types/better-sqlite3`** - TypeScript type definitions for better-sqlite3 - **`dotenv`** - Loads environment variables from your `.env` file ## 2. Initialize Prisma ORM diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx index 4c9160e611..025304d8ff 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/300-postgresql.mdx @@ -20,8 +20,8 @@ import NextSteps from '../../_components/_next-steps.mdx' Navigate to your existing project directory and install the required dependencies: ```terminal -npm install prisma @types/node --save-dev -npm install @prisma/client @prisma/adapter-pg dotenv +npm install prisma @types/node @types/pg --save-dev +npm install @prisma/client @prisma/adapter-pg pg dotenv ``` Here's what each package does: @@ -29,6 +29,8 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`pg`** - The node-postgres database driver +- **`@types/pg`** - TypeScript type definitions for node-postgres - **`dotenv`** - Loads environment variables from your `.env` file ## 2. Initialize Prisma ORM diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx index 0ae3bd823d..31dfe9f393 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/500-sql-server.mdx @@ -20,7 +20,7 @@ import NextSteps from '../../_components/_next-steps.mdx' Navigate to your existing project directory and install the required dependencies: ```terminal -npm install prisma @types/node --save-dev +npm install prisma @types/node @types/mssql --save-dev npm install @prisma/client @prisma/adapter-mssql dotenv ``` @@ -30,6 +30,7 @@ Here's what each package does: - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-mssql`** - The SQL Server driver adapter that connects Prisma Client to your database - **`dotenv`** - Loads environment variables from your `.env` file +- **`@types/mssql`** - TypeScript type definitions for mssql ## 2. Initialize Prisma ORM diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx index 7908afe4a6..5b878d723c 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx @@ -20,8 +20,8 @@ import NextSteps from '../../_components/_next-steps.mdx' Navigate to your existing project directory and install the required dependencies: ```terminal -npm install prisma @types/node --save-dev -npm install @prisma/client @prisma/adapter-pg dotenv +npm install prisma @types/node @types/pg --save-dev +npm install @prisma/client @prisma/adapter-pg pg dotenv ``` Here's what each package does: @@ -29,6 +29,8 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db pull`, and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database (CockroachDB is PostgreSQL-compatible) +- **`pg`** - The node-postgres database driver +- **`@types/pg`** - TypeScript type definitions for node-postgres - **`dotenv`** - Loads environment variables from your `.env` file ## 2. Initialize Prisma ORM diff --git a/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx b/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx index 9d3e6275ff..8c8c91ccb6 100644 --- a/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx +++ b/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx @@ -31,30 +31,57 @@ npx prisma@latest init --db ```code no-copy wrap -Success! Your Prisma Postgres database is ready ✅ +✓ Select an authentication method Google +Authenticating to Prisma Platform via browser. -We created an initial schema.prisma file and a .env file with your DATABASE_URL environment variable already set. +Visit the following URL in your browser to authenticate: +https://console.prisma.io/auth/cli?state=eyJjb6ll... + +Successfully authenticated as jon@doe.com. +Let's set up your Prisma Postgres database! +✓ Select your region: ap-southeast-1 - Asia Pacific (Singapore) +✓ Enter a project name: My Prisma Project +✓ Success! Your Prisma Postgres database is ready ✅ + +We found an existing schema.prisma file in your current project directory. + +--- Database URL --- + +Connect Prisma ORM to your Prisma Postgres database with this URL: --- Next steps --- Go to https://pris.ly/ppg-init for detailed instructions. -1. Define your database schema -Open the schema.prisma file and define your first models. Check the docs if you need inspiration: https://pris.ly/ppg-init +1. Install the Postgres adapter +npm install @prisma/adapter-pg + +...and add it to your Prisma Client instance: + +import { PrismaClient } from "./generated/prisma/client"; +import { PrismaPg } from "@prisma/adapter-pg"; + +const connectionString = `${process.env.DATABASE_URL}`; + +const adapter = new PrismaPg({ connectionString }); +const prisma = new PrismaClient({ adapter }); 2. Apply migrations Run the following command to create and apply a migration: -npx prisma migrate dev --name init +npx prisma migrate dev 3. Manage your data -View and edit your data locally by running this command: +View and edit your data locally by running this command: npx prisma studio -... or online in Console: -https://console.prisma.io/cliwxim5p005xqh0g3mvqpyak/cm6kw97t801ijzhvfwz4a0my3/cm6kw97ta01ikzhvf965vresv/studio +...or online in Console: +https://console.prisma.io/$path 4. Send queries from your app -To access your database from a JavaScript/TypeScript app, you need to use Prisma ORM. Go here for step-by-step instructions: https://pris.ly/ppg-init +If you already have an existing app with Prisma ORM, you can now run it and it will send queries against your newly created Prisma Postgres instance. + +5. Learn more +For more info, visit the Prisma Postgres docs: https://pris.ly/ppg-docs ``` diff --git a/content/100-getting-started/03-prisma-postgres/115-import-from-existing-database-mysql.mdx b/content/100-getting-started/03-prisma-postgres/115-import-from-existing-database-mysql.mdx index 0d009ba206..97bfeade5e 100644 --- a/content/100-getting-started/03-prisma-postgres/115-import-from-existing-database-mysql.mdx +++ b/content/100-getting-started/03-prisma-postgres/115-import-from-existing-database-mysql.mdx @@ -189,7 +189,6 @@ datasource db { // add-start provider = "postgres" // add-end - url = env("DATABASE_URL") } ``` diff --git a/content/200-orm/050-overview/500-databases/200-database-drivers.mdx b/content/200-orm/050-overview/500-databases/200-database-drivers.mdx index 822925c2ad..c89546e390 100644 --- a/content/200-orm/050-overview/500-databases/200-database-drivers.mdx +++ b/content/200-orm/050-overview/500-databases/200-database-drivers.mdx @@ -12,19 +12,18 @@ One of Prisma Client's components is the [Query Engine](/orm/more/under-the-hood :::note -As of [v6.15.0](https://pris.ly/release/6.16.0), Prisma ORM can be used without Rust engines in production applications. Learn more [here](/orm/prisma-client/setup-and-configuration/no-rust-engine). +As of Prisma ORM 7, the query compiler (client engine) is the default, which means Prisma Client is generated without a Rust-based query engine binary. This provides better performance and developer experience. Learn more [here](/orm/prisma-client/setup-and-configuration/no-rust-engine). -**When enabled, your Prisma Client will be generated without a Rust-based query engine binary**: +In Prisma ORM 7, the default generator configuration is: ```prisma generator client { - provider = "prisma-client" - output = "../src/generated/prisma" - engineType = "client" // no Rust engine + provider = "prisma-client" + output = "../generated/prisma" } ``` -Note that [driver adapters](/orm/overview/databases/database-drivers#driver-adapters) are required if you want to use Prisma ORM without Rust engines. +Note that [driver adapters](/orm/overview/databases/database-drivers#driver-adapters) are required when using the query compiler. You can [read about the performance and DX improvements](https://www.prisma.io/blog/prisma-orm-without-rust-latest-performance-benchmarks) of this change on our blog. @@ -120,7 +119,7 @@ As of the 6.6.0 release, you instantiate the driver adapter _directly_ with the ```typescript import { PrismaLibSQL } from '@prisma/adapter-libsql' -import { PrismaClient } from '../prisma/prisma-client' +import { PrismaClient } from '../generated/prisma/client' const adapter = new PrismaLibSQL({ url: env.LIBSQL_DATABASE_URL, @@ -130,17 +129,18 @@ const adapter = new PrismaLibSQL({ const prisma = new PrismaClient({ adapter }) ``` -### Driver adapters don't read the connection string from the Prisma schema +### Driver adapters and database connection configuration -When using Prisma ORM's built-in drivers, the connection string is read from the `url` field of the `datasource` block in your Prisma schema. +In Prisma ORM 7, the database connection URL is configured in [`prisma.config.ts`](/orm/reference/prisma-config-reference). However, when using a driver adapter, the connection string needs to be provided in your _application code_ when the driver adapter is set up initially. -On the other hand, when using a driver adapter, the connection string needs to be provided in your _application code_ when the driver adapter is set up initially. Here is how this is done for the `pg` driver and the `@prisma/adapter-pg` adapter: +Here is how this is done for the `pg` driver and the `@prisma/adapter-pg` adapter: ```ts -import { PrismaClient } from '../prisma/generated/client' +import 'dotenv/config' +import { PrismaClient } from '../generated/prisma/client' import { PrismaPg } from '@prisma/adapter-pg' -const adapter = new PrismaPg({ connectionString: env.DATABASE_URL }) +const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) ``` @@ -148,9 +148,9 @@ See the docs for the driver adapter you're using for concrete setup instructions ### Driver adapters and custom output paths -Since Prisma 5.9.0, when using the driver adapters Preview feature along with a [custom output path for Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path), you cannot reference Prisma Client using a relative path. +In Prisma ORM 7, the recommended approach is to use a custom output path for Prisma Client. The default output path is `../generated/prisma`. -Let's assume you had `output` in your Prisma schema set to `../src/generated/client`: +Let's assume you have `output` in your Prisma schema set to `../generated/prisma`: ```prisma generator client { @@ -159,23 +159,22 @@ generator client { } ``` -What you should _not_ do is reference that path relatively: +You can reference Prisma Client using a relative path from your application code: -```ts no-copy -// what not to do! -import { PrismaClient } from './src/generated/client' +```ts +import { PrismaClient } from '../generated/prisma/client' const client = new PrismaClient() ``` -Instead, you will need to use a linked dependency. +Alternatively, you can use a linked dependency for cleaner imports. ```terminal -npm add db@./src/generated/client +npm add db@./generated/prisma ``` @@ -183,7 +182,7 @@ npm add db@./src/generated/client ```terminal -pnpm add db@link:./src/generated/client +pnpm add db@link:./generated/prisma ``` @@ -191,7 +190,7 @@ pnpm add db@link:./src/generated/client ```terminal -yarn add db@link:./src/generated/client +yarn add db@link:./generated/prisma ``` diff --git a/content/200-orm/050-overview/500-databases/300-postgresql.mdx b/content/200-orm/050-overview/500-databases/300-postgresql.mdx index 52ead2eb8d..98fb4750d2 100644 --- a/content/200-orm/050-overview/500-databases/300-postgresql.mdx +++ b/content/200-orm/050-overview/500-databases/300-postgresql.mdx @@ -28,11 +28,13 @@ datasource db { } ``` -The database connection URL is configured in `prisma.config.ts`: +The `datasource` block specifies the `postgresql` data source connector. -```ts file=prisma.config.ts -import 'dotenv/config' +In Prisma ORM 7, the database connection URL is configured in [`prisma.config.ts`](/orm/reference/prisma-config-reference): + +```typescript file=prisma.config.ts import { defineConfig, env } from 'prisma/config' +import 'dotenv/config' export default defineConfig({ schema: 'prisma/schema.prisma', @@ -42,16 +44,7 @@ export default defineConfig({ }) ``` -:::info - -When using Prisma CLI commands, environment variables are not automatically loaded. You'll need to use a package like `dotenv` to load environment variables from a `.env` file, or ensure your environment variables are set in your shell. - -::: - -The fields passed to the `datasource` block are: - -- `provider`: Specifies the `postgresql` data source connector. -- The `url` field is configured in `prisma.config.ts` and specifies the [connection URL](#connection-url) for the PostgreSQL database server. +This configuration uses an [environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the database connection URL. ## Using the `node-postgres` driver @@ -74,13 +67,14 @@ npm install @prisma/adapter-pg Now, when you instantiate Prisma Client, you need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: ```ts +import 'dotenv/config' import { PrismaPg } from '@prisma/adapter-pg' -import { PrismaClient } from '../prisma/generated/client' +import { PrismaClient } from '../generated/prisma/client' const connectionString = `${process.env.DATABASE_URL}` -const adapter = new PrismaPg({ connectionString }); -const prisma = new PrismaClient({ adapter }); +const adapter = new PrismaPg({ connectionString }) +const prisma = new PrismaClient({ adapter }) ``` Notice that this code requires the `DATABASE_URL` environment variable to be set to your PostgreSQL connection string. You can learn more about the connection string below. diff --git a/content/200-orm/050-overview/500-databases/400-mysql.mdx b/content/200-orm/050-overview/500-databases/400-mysql.mdx index 18e7214e5f..60b61c9bcb 100644 --- a/content/200-orm/050-overview/500-databases/400-mysql.mdx +++ b/content/200-orm/050-overview/500-databases/400-mysql.mdx @@ -19,11 +19,13 @@ datasource db { } ``` -The database connection URL is configured in `prisma.config.ts`: +The `datasource` block specifies the `mysql` data source connector, which is used for both MySQL and MariaDB. -```ts file=prisma.config.ts -import 'dotenv/config' +In Prisma ORM 7, the database connection URL is configured in [`prisma.config.ts`](/orm/reference/prisma-config-reference): + +```typescript file=prisma.config.ts import { defineConfig, env } from 'prisma/config' +import 'dotenv/config' export default defineConfig({ schema: 'prisma/schema.prisma', @@ -33,16 +35,7 @@ export default defineConfig({ }) ``` -:::info - -When using Prisma CLI commands, environment variables are not automatically loaded. You'll need to use a package like `dotenv` to load environment variables from a `.env` file, or ensure your environment variables are set in your shell. - -::: - -The fields passed to the `datasource` block are: - -- `provider`: Specifies the `mysql` data source connector, which is used both for MySQL and MariaDB. -- The `url` field is configured in `prisma.config.ts` and specifies the [connection URL](#connection-url) for the MySQL database server. +This configuration uses an [environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the database connection URL. ## Using the `mariadb` driver @@ -65,15 +58,16 @@ npm install @prisma/adapter-mariadb Now, when you instantiate Prisma Client, you need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: ```ts -import { PrismaMariaDb } from '@prisma/adapter-mariadb'; -import { PrismaClient } from './generated/prisma'; +import 'dotenv/config' +import { PrismaMariaDb } from '@prisma/adapter-mariadb' +import { PrismaClient } from '../generated/prisma/client' const adapter = new PrismaMariaDb({ host: "localhost", port: 3306, connectionLimit: 5 -}); -const prisma = new PrismaClient({ adapter }); +}) +const prisma = new PrismaClient({ adapter }) ``` ## Connection details diff --git a/content/200-orm/050-overview/500-databases/500-sqlite.mdx b/content/200-orm/050-overview/500-databases/500-sqlite.mdx index 1e27d3911b..6235b5d18c 100644 --- a/content/200-orm/050-overview/500-databases/500-sqlite.mdx +++ b/content/200-orm/050-overview/500-databases/500-sqlite.mdx @@ -16,14 +16,25 @@ To connect to a SQLite database file, you need to configure a [`datasource`](/or ```prisma file=schema.prisma datasource db { provider = "sqlite" - url = "file:./dev.db" } ``` -The fields passed to the `datasource` block are: +The `datasource` block specifies the `sqlite` data source connector. -- `provider`: Specifies the `sqlite` data source connector. -- `url`: Specifies the [connection URL](/orm/reference/connection-urls) for the SQLite database. The connection URL always starts with the prefix `file:` and then contains a file path pointing to the SQLite database file. In this case, the file is located in the same directory and called `dev.db`. +In Prisma ORM 7, the database connection URL is configured in [`prisma.config.ts`](/orm/reference/prisma-config-reference): + +```typescript file=prisma.config.ts +import { defineConfig } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: 'file:./dev.db', + }, +}) +``` + +The connection URL always starts with the prefix `file:` and then contains a file path pointing to the SQLite database file. In this example, the file is located in the same directory and called `dev.db`. ## Using the `better-sqlite3` driver @@ -51,8 +62,8 @@ import { PrismaClient } from './generated/prisma'; const adapter = new PrismaBetterSqlite3({ url: "file:./prisma/dev.db" -}); -const prisma = new PrismaClient({ adapter }); +}) +const prisma = new PrismaClient({ adapter }) ``` ### 3. Configure timestamp format for backward compatibility @@ -71,8 +82,8 @@ const adapter = new PrismaBetterSqlite3({ url: "file:./prisma/dev.db" }, { timestampFormat: 'unixepoch-ms' -}); -const prisma = new PrismaClient({ adapter }); +}) +const prisma = new PrismaClient({ adapter }) ``` :::info @@ -138,29 +149,26 @@ try migrating the 'int' column type to BIGINT ### Connection URL -The connection URL of a SQLite connector points to a file on your file system. For example, the following two paths are equivalent because the `.db` is in the same directory: +The connection URL of a SQLite connector points to a file on your file system and is configured in `prisma.config.ts`. For example, the following two paths are equivalent because the `.db` is in the same directory: -```prisma file=schema.prisma -datasource db { - provider = "sqlite" - url = "file:./dev.db" +```typescript file=prisma.config.ts +datasource: { + url: 'file:./dev.db', } ``` is the same as: -```prisma file=schema.prisma -datasource db { - provider = "sqlite" - url = "file:dev.db" +```typescript file=prisma.config.ts +datasource: { + url: 'file:dev.db', } ``` You can also target files from the root or any other place in your file system: -```prisma file=schema.prisma -datasource db { - provider = "sqlite" - url = "file:/Users/janedoe/dev.db" +```typescript file=prisma.config.ts +datasource: { + url: 'file:/Users/janedoe/dev.db', } ``` diff --git a/content/200-orm/050-overview/500-databases/800-sql-server/index.mdx b/content/200-orm/050-overview/500-databases/800-sql-server/index.mdx index 86e02b41ac..aac61feff2 100644 --- a/content/200-orm/050-overview/500-databases/800-sql-server/index.mdx +++ b/content/200-orm/050-overview/500-databases/800-sql-server/index.mdx @@ -65,6 +65,7 @@ npm install @prisma/adapter-mssql Now, when you instantiate Prisma Client, you need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: ```ts +import 'dotenv/config' import { PrismaMssql } from '@prisma/adapter-mssql' import { PrismaClient } from '../prisma/generated/client' diff --git a/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx b/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx index daffbf41a1..ee1d12b671 100644 --- a/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx +++ b/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx @@ -530,7 +530,7 @@ const result = await prisma.user.create({ There are two ways to create or update a single record and multiple related records - for example, a user with multiple posts: -- Use a nested [`create`](/orm/reference/prisma-client-reference#create-1) query +- Use a nested [`create`](/orm/reference/prisma-client-reference#create) query - Use a nested [`createMany`](/orm/reference/prisma-client-reference#createmany-1) query In most cases, a nested `create` will be preferable unless the [`skipDuplicates` query option](/orm/reference/prisma-client-reference#nested-createmany-options) is required. Here's a quick table describing the differences between the two options: @@ -544,7 +544,7 @@ In most cases, a nested `create` will be preferable unless the [`skipDuplicates` #### Using nested `create` -The following query uses nested [`create`](/orm/reference/prisma-client-reference#create-1) to create: +The following query uses nested [`create`](/orm/reference/prisma-client-reference#create) to create: - One user - Two posts @@ -640,7 +640,7 @@ Here's a visual representation of how a nested create operation can write to sev #### Using nested `createMany` -The following query uses a nested [`createMany`](/orm/reference/prisma-client-reference#create-1) to create: +The following query uses a nested [`createMany`](/orm/reference/prisma-client-reference#create) to create: - One user - Two posts diff --git a/content/200-orm/500-reference/050-prisma-client-reference.mdx b/content/200-orm/500-reference/050-prisma-client-reference.mdx index f92eadde2b..8ea2c2473f 100644 --- a/content/200-orm/500-reference/050-prisma-client-reference.mdx +++ b/content/200-orm/500-reference/050-prisma-client-reference.mdx @@ -825,7 +825,7 @@ const user = await prisma.user.findMany({ #### Remarks -- You can also perform a nested [`create`](#create-1) - for example, add a `User` and two `Post` records at the same time. +- You can also perform a nested [`create`](#create) - for example, add a `User` and two `Post` records at the same time. #### Examples diff --git a/content/200-orm/500-reference/200-prisma-cli-reference.mdx b/content/200-orm/500-reference/200-prisma-cli-reference.mdx index 6f636d254c..aac2536e20 100644 --- a/content/200-orm/500-reference/200-prisma-cli-reference.mdx +++ b/content/200-orm/500-reference/200-prisma-cli-reference.mdx @@ -155,17 +155,27 @@ prisma init ```code no-copy wrap -✔ Your Prisma schema was created at prisma/schema.prisma. - You can now open it in your favorite editor. +npx prisma init -Next steps: -1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started -2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlite, sqlserver, mongodb or cockroachdb. -3. Run prisma db pull to turn your database schema into a Prisma schema. -4. Run prisma generate to generate Prisma Client. You can then start querying your database. +Initialized Prisma in your project -More information in our documentation: -https://pris.ly/d/getting-started + prisma/ + schema.prisma + prisma.config.ts + +Next, choose how you want to set up your database: + +CONNECT EXISTING DATABASE: + 1. Configure your DATABASE_URL in `prisma.config.ts` + 2. Run `npx prisma db pull` to introspect your database. + +CREATE NEW DATABASE: + Local: npx prisma dev (runs Postgres locally in your terminal) + Cloud: npx create-db (creates a free Prisma Postgres database) + + Then, define your models in `prisma/schema.prisma` and run `npx prisma migrate dev` to apply your schema. + +Learn more: https://pris.ly/getting-started ``` @@ -184,10 +194,76 @@ The command output contains helpful information on how to use the generated file **Run `prisma init --db`** + + + + ```terminal prisma init --db ``` + + + + +```code no-copy wrap +✓ Select an authentication method Google +Authenticating to Prisma Platform via browser. + +Visit the following URL in your browser to authenticate: +https://console.prisma.io/auth/cli?state=eyJjb6ll... + +Successfully authenticated as amanyoyoyo@gmail.com. +Let's set up your Prisma Postgres database! +✓ Select your region: ap-southeast-1 - Asia Pacific (Singapore) +✓ Enter a project name: My Prisma Project +✓ Success! Your Prisma Postgres database is ready ✅ + +We found an existing schema.prisma file in your current project directory. + +--- Database URL --- + +Connect Prisma ORM to your Prisma Postgres database with this URL: + +--- Next steps --- + +Go to https://pris.ly/ppg-init for detailed instructions. + +1. Install the Postgres adapter +npm install @prisma/adapter-pg + +...and add it to your Prisma Client instance: + +import { PrismaClient } from "./generated/prisma/client"; +import { PrismaPg } from "@prisma/adapter-pg"; + +const connectionString = `${process.env.DATABASE_URL}`; + +const adapter = new PrismaPg({ connectionString }); +const prisma = new PrismaClient({ adapter }); + +2. Apply migrations +Run the following command to create and apply a migration: +npx prisma migrate dev + +3. Manage your data +View and edit your data locally by running this command: +npx prisma studio + +...or online in Console: +https://console.prisma.io/cmhyn0uwl0q6903foel16ff31/cmhyn143t074tyLfoezs684ag/cmhyn143t074uylfon8hfre5z/studio + +4. Send queries from your app +If you already have an existing app with Prisma ORM, you can now run it and it will send queries against your newly created Prisma Postgres instance. + +5. Learn more +For more info, visit the Prisma Postgres docs: https://pris.ly/ppg-docs +``` + + + + + The command creates a new [Prisma Postgres](https://www.prisma.io/postgres) instance. Note that it requires you to be authenticated with the [PDP Console](https://console.prisma.io), If you run it for the first time without being authenticated, the command will open the browser for you to log into Console. **Run `prisma init --prompt "Simple habit tracker application"`** @@ -219,7 +295,6 @@ datasource db { generator client { provider = "prisma-client" - output = "./generated" previewFeatures = ["metrics"] } ``` @@ -247,7 +322,6 @@ datasource db { generator client { provider = "prisma-client" - output = "./generated" previewFeatures = ["views", "metrics"] } ``` @@ -276,6 +350,26 @@ datasource db { } ``` +**`prisma.config.ts`** + +A TypeScript configuration file for Prisma that defines your datasource URL and other settings: + +```typescript +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + +See the [Prisma Config reference](/orm/reference/prisma-config-reference) for more details. + **`.env`** A file to define environment variables for your project: @@ -287,7 +381,7 @@ A file to define environment variables for your project: # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. # See the documentation for all the connection string options: https://pris.ly/d/connection-strings -DATABASE_URL="file:./dev.db" +DATABASE_URL="postgresql://user:password@localhost:5432/mydb" ``` **`.gitignore`** @@ -326,10 +420,28 @@ datasource db { generator client { provider = "prisma-client" - output = "./generated" + output = "../generated/prisma" } ``` +**`prisma.config.ts`** + +A TypeScript configuration file for Prisma with the custom URL: + +```typescript +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + **`.env`** A file to define environment variables for your project: @@ -828,17 +940,37 @@ Introspection with the `db pull` command on the [MongoDB connector](/orm/overvie #### Prerequisites -Before using the `db pull` command, you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. +Before using the `db pull` command, you must configure your database connection in your `prisma.config.ts` file. -For example, the following `datasource` defines a SQLite database file within the current directory: +For example: + +```prisma file=schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} -```prisma datasource db { provider = "sqlite" - url = "file:my-database.db" } ``` +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + + + #### Options | Option | Required | Description | Default | @@ -972,17 +1104,35 @@ See also: #### Prerequisites -Before using the `db push` command, you must define a valid [datasource](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. +Before using the `db push` command, you must configure your database connection in your `prisma.config.ts` file. -For example, the following `datasource` defines a SQLite database file within the current directory: +For example: + +```prisma file=schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} -```prisma datasource db { provider = "sqlite" - url = "file:my-database.db" } ``` +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + #### Options | Options | Required | Description | @@ -1066,17 +1216,37 @@ See also: #### Prerequisites -Before using the `db execute` command, if you do not use the `--url` option you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. +Before using the `db execute` command, if you do not use the `--url` option you must configure your database connection in your `prisma.config.ts` file. -For example, the following `datasource` defines a SQLite database file within the current directory: +For example: + +```prisma file=schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} -```prisma datasource db { provider = "sqlite" - url = "file:my-database.db" } ``` +This how your `prisma.config.ts` file should look like: + +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + #### Options One of the following data source inputs is required: @@ -1414,17 +1584,35 @@ See also: #### Prerequisites -Before using the `migrate diff` command, if you are using the `--from-schema-datasource` or `--to-schema-datasource` you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. +Before using the `migrate diff` command, if you are using the `--from-schema-datasource` or `--to-schema-datasource` you must configure your database connection in your `prisma.config.ts` file. -For example, the following `datasource` defines a SQLite database file within the current directory: +For example: + +```prisma file=schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} -```prisma datasource db { provider = "sqlite" - url = "file:my-database.db" } ``` +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + #### Options One of the following `--from-...` options is required: @@ -1521,17 +1709,35 @@ The `studio` command allows you to interact with and manage your data interactiv #### Prerequisites -Before using the `studio` command, you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. +Before using the `studio` command, you must configure your database connection in your `prisma.config.ts` file. -For example, the following `datasource` defines a SQLite database file within the current directory: +For example: + +```prisma file=schema.prisma +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} -```prisma datasource db { provider = "sqlite" - url = "file:my-database.db" } ``` +```typescript file=prisma.config.ts +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: env('DATABASE_URL'), + }, +}) +``` + #### Options The `studio` command recognizes the following options: diff --git a/content/250-postgres/350-integrations/100-netlify.mdx b/content/250-postgres/350-integrations/100-netlify.mdx index 9cbd243363..06a1353719 100644 --- a/content/250-postgres/350-integrations/100-netlify.mdx +++ b/content/250-postgres/350-integrations/100-netlify.mdx @@ -120,7 +120,7 @@ In this section, you are going to add Prisma Postgres to the starter project _on ```terminal npm install prisma --save-dev ``` -1. Initialize Prisma ORM to create Prisma schema and `.env` file: +1. Initialize Prisma ORM to create Prisma schema, config and `.env` file: ```terminal npx prisma init ``` diff --git a/content/600-about/30-docs-components/01-mdx-examples.mdx b/content/600-about/30-docs-components/01-mdx-examples.mdx index 4496424195..2a18475965 100644 --- a/content/600-about/30-docs-components/01-mdx-examples.mdx +++ b/content/600-about/30-docs-components/01-mdx-examples.mdx @@ -341,17 +341,25 @@ yarn run v1.22.0 warning package.json: No license field $ /Users/janedoe/Desktop/tsdf/node_modules/.bin/prisma init -✔ Your Prisma schema was created at prisma/schema.prisma. - You can now open it in your favorite editor. +Initialized Prisma in your project -Next steps: -1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started. -2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. -3. Run `prisma db pull` to introspect your database schema and update the Prisma schema data models accordingly. -4. Run `prisma generate` to install Prisma Client. You can then start querying your database. + prisma/ + schema.prisma + prisma.config.ts -More information in our documentation: -https://pris.ly/d/getting-started +Next, choose how you want to set up your database: + +CONNECT EXISTING DATABASE: + 1. Configure your DATABASE_URL in `prisma.config.ts` + 2. Run `npx prisma db pull` to introspect your database. + +CREATE NEW DATABASE: + Local: npx prisma dev (runs Postgres locally in your terminal) + Cloud: npx create-db (creates a free Prisma Postgres database) + + Then, define your models in `prisma/schema.prisma` and run `npx prisma migrate dev` to apply your schema. + +Learn more: https://pris.ly/getting-started ``` @@ -379,17 +387,25 @@ yarn run v1.22.0 warning package.json: No license field $ /Users/janedoe/Desktop/tsdf/node_modules/.bin/prisma init -✔ Your Prisma schema was created at prisma/schema.prisma. - You can now open it in your favorite editor. +Initialized Prisma in your project + + prisma/ + schema.prisma + prisma.config.ts -Next steps: -1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started. -2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. -3. Run `prisma db pull` to introspect your database schema and update the Prisma schema data models accordingly. -4. Run `prisma generate` to install Prisma Client. You can then start querying your database. +Next, choose how you want to set up your database: -More information in our documentation: -https://pris.ly/d/getting-started +CONNECT EXISTING DATABASE: + 1. Configure your DATABASE_URL in `prisma.config.ts` + 2. Run `npx prisma db pull` to introspect your database. + +CREATE NEW DATABASE: + Local: npx prisma dev (runs Postgres locally in your terminal) + Cloud: npx create-db (creates a free Prisma Postgres database) + + Then, define your models in `prisma/schema.prisma` and run `npx prisma migrate dev` to apply your schema. + +Learn more: https://pris.ly/getting-started ``` @@ -417,17 +433,26 @@ yarn run v1.22.0 warning package.json: No license field $ /Users/janedoe/Desktop/tsdf/node_modules/.bin/prisma init -✔ Your Prisma schema was created at prisma/schema.prisma. - You can now open it in your favorite editor. -Next steps: -1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started. -2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. -3. Run `prisma db pull` to introspect your database schema and update the Prisma schema data models accordingly. -4. Run `prisma generate` to install Prisma Client. You can then start querying your database. +Initialized Prisma in your project + + prisma/ + schema.prisma + prisma.config.ts -More information in our documentation: -https://pris.ly/d/getting-started +Next, choose how you want to set up your database: + +CONNECT EXISTING DATABASE: + 1. Configure your DATABASE_URL in `prisma.config.ts` + 2. Run `npx prisma db pull` to introspect your database. + +CREATE NEW DATABASE: + Local: npx prisma dev (runs Postgres locally in your terminal) + Cloud: npx create-db (creates a free Prisma Postgres database) + + Then, define your models in `prisma/schema.prisma` and run `npx prisma migrate dev` to apply your schema. + +Learn more: https://pris.ly/getting-started ``` @@ -455,17 +480,25 @@ yarn run v1.22.0 warning package.json: No license field $ /Users/janedoe/Desktop/tsdf/node_modules/.bin/prisma init -✔ Your Prisma schema was created at prisma/schema.prisma. - You can now open it in your favorite editor. +Initialized Prisma in your project + + prisma/ + schema.prisma + prisma.config.ts + +Next, choose how you want to set up your database: + +CONNECT EXISTING DATABASE: + 1. Configure your DATABASE_URL in `prisma.config.ts` + 2. Run `npx prisma db pull` to introspect your database. + +CREATE NEW DATABASE: + Local: npx prisma dev (runs Postgres locally in your terminal) + Cloud: npx create-db (creates a free Prisma Postgres database) -Next steps: -1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started. -2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. -3. Run `prisma db pull` to introspect your database schema and update the Prisma schema data models accordingly. -4. Run `prisma generate` to install Prisma Client. You can then start querying your database. + Then, define your models in `prisma/schema.prisma` and run `npx prisma migrate dev` to apply your schema. -More information in our documentation: -https://pris.ly/d/getting-started +Learn more: https://pris.ly/getting-started ``` From f489364f2a978975fcf99cbf6cf543a511a89eb5 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Mon, 17 Nov 2025 19:08:33 +0530 Subject: [PATCH 14/23] Update docs to perform migrations with connection pooling and Prisma config (#7266) --- .../500-databases/880-supabase.mdx | 40 +++++++++++------- .../050-overview/500-databases/890-neon.mdx | 38 +++++++++++------ .../200-pgbouncer.mdx | 36 +++++++++++----- .../050-databases-connections/index.mdx | 36 ++++++++++------ .../100-queries/037-relation-queries.mdx | 2 +- .../150-using-raw-sql/100-typedsql.mdx | 2 +- .../301-edge/485-deploy-to-vercel.mdx | 8 ++-- .../300-accelerate/200-getting-started.mdx | 42 ++++++++++--------- 8 files changed, 126 insertions(+), 78 deletions(-) diff --git a/content/200-orm/050-overview/500-databases/880-supabase.mdx b/content/200-orm/050-overview/500-databases/880-supabase.mdx index b17558b8fa..6c3475a379 100644 --- a/content/200-orm/050-overview/500-databases/880-supabase.mdx +++ b/content/200-orm/050-overview/500-databases/880-supabase.mdx @@ -26,7 +26,7 @@ Many aspects of using Prisma ORM with Supabase are just like using Prisma ORM wi ## Specific considerations -If you'd like to use the [connection pooling feature](https://supabase.com/docs/guides/database/connecting-to-postgres#connection-pooling-in-depth) available with Supabase, you will need to use the connection pooling connection string available via your [Supabase database settings](https://supabase.com/dashboard/project/_/settings/database) with `?pgbouncer=true` appended to the end of your `DATABASE_URL` environment variable: +If you'd like to use the [connection pooling feature](https://supabase.com/docs/guides/database/connecting-to-postgres#connection-pooling-in-depth) available with Supabase, you will need to use the connection pooling connection string available via your [Supabase database settings](https://supabase.com/dashboard/project/_/settings/database) with `?pgbouncer=true` appended to the end of the environment variable that Prisma Client reads when you instantiate it with a driver adapter: ```env file=.env # Connect to Supabase via connection pooling with Supavisor. @@ -41,33 +41,41 @@ Supabase provides three types of connection strings for each database: 3. **Session Pooler Connection string** – `postgresql://postgres.[your-project-ref]:password@aws-0-[region].pooler.supabase.com:5432/postgres` -If you would like to use the Prisma CLI in order to perform other actions on your database (e.g. migrations), your setup depends on the connection string used: +Prisma CLI commands (for example, migrations and introspection) now read the direct, non-pooled connection string from `prisma.config.ts`. Configure two environment variables — the pooled connection string for Prisma Client (`DATABASE_URL`) and a direct connection string for the Prisma CLI (`DIRECT_URL`): -- If your `DATABASE_URL` uses the Transaction Pooler (connection string 2), you must provide a `DIRECT_URL` with either the Direct Database (1) or Session Pooler (3) connection string in order for Prisma Migrate to work. - -- If your `DATABASE_URL` already uses the Session Pooler (connection string 3), you do not need to provide a `DIRECT_URL`. Prisma Migrate will work without it. - -```env file=.env highlight=4-5;add showLineNumbers +```env file=.env highlight=5-7;add showLineNumbers # Connect to Supabase via connection pooling with Supavisor. DATABASE_URL="postgres://postgres.[your-supabase-project]:[password]@aws-0-[aws-region].pooler.supabase.com:6543/postgres?pgbouncer=true" -//add-start -# Direct connection to the database. Used for migrations. +# Direct connection to the database used by the Prisma CLI. DIRECT_URL="postgres://postgres.[your-supabase-project]:[password]@aws-0-[aws-region].pooler.supabase.com:5432/postgres" # or DIRECT_URL="postgresql://postgres:password@db.[your-project-ref].supabase.co:5432/postgres" -//add-end ``` -You can then update your `schema.prisma` to use the new direct URL: +Point `prisma.config.ts` to the direct connection string: + +```ts file=prisma.config.ts showLineNumbers +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' -```prisma file=schema.prisma highlight=4;add showLineNumbers -datasource db { - provider = "postgresql" -} +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DIRECT_URL'), + }, +}) ``` -More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields). +At runtime, instantiate Prisma Client with a driver adapter using the pooled `DATABASE_URL`. This keeps the direct connection string scoped to Prisma CLI workflows while your application connections continue to flow through Supavisor. + +```ts file=src/db/client.ts showLineNumbers +import { PrismaClient } from '../prisma/generated/client' +import { PrismaPg } from '@prisma/adapter-pg' + +const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) +export const prisma = new PrismaClient({ adapter }) +``` :::info diff --git a/content/200-orm/050-overview/500-databases/890-neon.mdx b/content/200-orm/050-overview/500-databases/890-neon.mdx index 046bc1674d..114faeef54 100644 --- a/content/200-orm/050-overview/500-databases/890-neon.mdx +++ b/content/200-orm/050-overview/500-databases/890-neon.mdx @@ -39,34 +39,46 @@ There are a few differences between Neon and PostgreSQL you should be aware of t ## How to use Neon's connection pooling If you would like to use the [connection pooling](https://neon.tech/docs/guides/prisma#use-connection-pooling-with-prisma) available in Neon, you will -need to add `-pooler` in the hostname of your `DATABASE_URL` environment variable used in the `url` property of the `datasource` block of your Prisma schema: +need to add `-pooler` in the hostname of the connection string that Prisma Client uses via a driver adapter: ```bash file=.env # Connect to Neon with Pooling. DATABASE_URL=postgres://daniel:@ep-mute-rain-952417-pooler.us-east-2.aws.neon.tech:5432/neondb?sslmode=require ``` -If you would like to use Prisma CLI in order to perform other actions on your database (e.g. for migrations) you will need to add a `DIRECT_URL` environment variable to use in the `directUrl` property of the `datasource` block of your Prisma schema so that the CLI will use a direct connection string (without PgBouncer): +Prisma CLI commands (for example, `prisma migrate` or `prisma db pull`) now read the direct connection string from `prisma.config.ts`. Configure both a pooled and non-pooled environment variable: -```env file=.env highlight=4-5;add showLineNumbers -# Connect to Neon with Pooling. +```env file=.env highlight=5-6;add showLineNumbers +# Connect to Neon with pooling (used by Prisma Client via the adapter). DATABASE_URL=postgres://daniel:@ep-mute-rain-952417-pooler.us-east-2.aws.neon.tech/neondb?sslmode=require -//add-start -# Direct connection to the database used by Prisma CLI for e.g. migrations. +# Direct connection to the database used by the Prisma CLI. DIRECT_URL="postgres://daniel:@ep-mute-rain-952417.us-east-2.aws.neon.tech/neondb" -//add-end ``` -You can then update your `schema.prisma` to use the new direct URL: +Point `prisma.config.ts` to the direct connection string: + +```ts file=prisma.config.ts showLineNumbers +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' -```prisma file=schema.prisma highlight=4;add showLineNumbers -datasource db { - provider = "postgresql" -} +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DIRECT_URL'), + }, +}) ``` -More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields). +At runtime, instantiate Prisma Client with the pooled connection string using `@prisma/adapter-neon`: + +```ts file=src/db/client.ts showLineNumbers +import { PrismaClient } from '../prisma/generated/client' +import { PrismaNeon } from '@prisma/adapter-neon' + +const adapter = new PrismaNeon({ connectionString: process.env.DATABASE_URL }) +export const prisma = new PrismaClient({ adapter }) +``` :::info diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/200-pgbouncer.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/200-pgbouncer.mdx index 744c8a3b3a..1c562d8504 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/200-pgbouncer.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/200-pgbouncer.mdx @@ -65,21 +65,37 @@ Error: undefined: Database error Error querying the database: db error: ERROR: prepared statement "s0" already exists ``` -To work around this issue, you must connect directly to the database rather than going through PgBouncer. To achieve this, you can use the [`directUrl`](/orm/reference/prisma-schema-reference#fields) field in your [`datasource`](/orm/reference/prisma-schema-reference#datasource) block. +To work around this issue, configure a **direct** connection for Prisma CLI commands in `prisma.config.ts`, while Prisma Client continues to use the PgBouncer URL via a driver adapter. -For example, consider the following `datasource` block: +```env file=.env highlight=4-6;add showLineNumbers +# PgBouncer (pooled) connection string used by Prisma Client. +DATABASE_URL="postgres://USER:PASSWORD@HOST:PORT/DATABASE?pgbouncer=true" -```prisma -datasource db { - provider = "postgresql" - url = "postgres://USER:PASSWORD@HOST:PORT/DATABASE?pgbouncer=true" - directUrl = "postgres://USER:PASSWORD@HOST:PORT/DATABASE" -} +# Direct database connection string used by Prisma CLI. +DIRECT_URL="postgres://USER:PASSWORD@HOST:PORT/DATABASE" ``` -The block above uses a PgBouncer connection string as the primary URL using `url`, allowing Prisma Client to take advantage of the PgBouncer connection pooler. +```ts file=prisma.config.ts showLineNumbers +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' -It also provides a connection string directly to the database, without PgBouncer, using the `directUrl` field. This connection string will be used when commands that require a single connection to the database, such as `prisma migrate dev` or `prisma db push`, are invoked. +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DIRECT_URL'), + }, +}) +``` + +```ts file=src/db/client.ts showLineNumbers +import { PrismaClient } from '../prisma/generated/client' +import { PrismaPg } from '@prisma/adapter-pg' + +const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) +export const prisma = new PrismaClient({ adapter }) +``` + +With this setup, PgBouncer stays in the path for runtime traffic, while Prisma CLI commands (`prisma migrate dev`, `prisma db push`, `prisma db pull`, and so on) always use the direct connection string defined in `prisma.config.ts`. ### PgBouncer with different database providers diff --git a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx index d94e3e2e48..3dba249f14 100644 --- a/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx +++ b/content/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx @@ -336,29 +336,39 @@ datasource db { Connection poolers like [Prisma Accelerate](/accelerate) and PgBouncer prevent your application from exhausting the database's connection limit. -If you would like to use the Prisma CLI in order to perform other actions on your database ,e.g. migrations and introspection, you will need to add an environment variable that provides a direct connection to your database in the `datasource.directUrl` property in your Prisma schema: +To keep Prisma Client on the pooled connection while allowing Prisma CLI commands (for example, migrations or introspection) to connect directly, define two environment variables: -```env file=.env highlight=4,5;add showLineNumbers +```env file=.env highlight=4-6;add showLineNumbers # Connection URL to your database using PgBouncer. DATABASE_URL="postgres://root:password@127.0.0.1:54321/postgres?pgbouncer=true" -//add-start -# Direct connection URL to the database used for migrations +# Direct connection URL to the database used for Prisma CLI commands. DIRECT_URL="postgres://root:password@127.0.0.1:5432/postgres" -//add-end ``` -You can then update your `schema.prisma` to use the new direct URL: +Configure `prisma.config.ts` to point to the direct connection string. Prisma CLI commands always read from this configuration. -```prisma file=schema.prisma highlight=4;add showLineNumbers -datasource db { - provider = "postgresql" - //add-next-line - directUrl = env("DIRECT_URL") -} +```ts file=prisma.config.ts showLineNumbers +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DIRECT_URL'), + }, +}) ``` -More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields). +At runtime, instantiate Prisma Client with a driver adapter (for example, `@prisma/adapter-pg`) that uses the pooled connection string: + +```ts file=src/db/client.ts showLineNumbers +import { PrismaClient } from '../prisma/generated/client' +import { PrismaPg } from '@prisma/adapter-pg' + +const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }) +export const prisma = new PrismaClient({ adapter }) +``` ### Prisma Accelerate diff --git a/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx b/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx index ee1d12b671..8764971718 100644 --- a/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx +++ b/content/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx @@ -640,7 +640,7 @@ Here's a visual representation of how a nested create operation can write to sev #### Using nested `createMany` -The following query uses a nested [`createMany`](/orm/reference/prisma-client-reference#create) to create: +The following query uses a nested [`createMany`](/orm/reference/prisma-client-reference#createmany) to create: - One user - Two posts diff --git a/content/200-orm/200-prisma-client/150-using-raw-sql/100-typedsql.mdx b/content/200-orm/200-prisma-client/150-using-raw-sql/100-typedsql.mdx index ab961eb88d..27c7b506b6 100644 --- a/content/200-orm/200-prisma-client/150-using-raw-sql/100-typedsql.mdx +++ b/content/200-orm/200-prisma-client/150-using-raw-sql/100-typedsql.mdx @@ -244,7 +244,7 @@ TypedSQL does not work with MongoDB, as it is specifically designed for SQL data ### Active Database Connection Required -TypedSQL requires an active database connection to function properly. This means you need to have a running database instance that Prisma can connect to when generating the client with the `--sql` flag. If a `directUrl` is provided in your Prisma configuration, TypedSQL will use that for the connection. +TypedSQL requires an active database connection to function properly. This means you need to have a running database instance that Prisma can connect to when generating the client with the `--sql` flag. TypedSQL uses the connection string defined in `prisma.config.ts` (`datasource.url`) to establish this connection. ### Dynamic SQL Queries with Dynamic Columns diff --git a/content/200-orm/200-prisma-client/500-deployment/301-edge/485-deploy-to-vercel.mdx b/content/200-orm/200-prisma-client/500-deployment/301-edge/485-deploy-to-vercel.mdx index f5d06377d7..e1420e3cca 100644 --- a/content/200-orm/200-prisma-client/500-deployment/301-edge/485-deploy-to-vercel.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/301-edge/485-deploy-to-vercel.mdx @@ -170,15 +170,14 @@ model User { If you are using Vercel Postgres, you need to: - use the `@prisma/adapter-neon` database adapter because Vercel Postgres uses [Neon](https://neon.tech/) under the hood -- be aware that Vercel by default calls the environment variable for the database connection string `POSTGRES_PRISMA_URL` while the default name used in the Prisma docs is typically `DATABASE_URL`; using Vercel's naming, you need to configure these in `prisma.config.ts`: +- be aware that Vercel by default calls the pooled connection string `POSTGRES_PRISMA_URL` while the direct, non-pooled connection string is exposed as `POSTGRES_URL_NON_POOLING`. Configure `prisma.config.ts` so that the Prisma CLI uses the direct connection string: ```ts file=prisma.config.ts import { defineConfig, env } from 'prisma/config' export default defineConfig({ schema: 'prisma/schema.prisma', datasource: { - url: env('POSTGRES_PRISMA_URL'), // uses connection pooling - directUrl: env('POSTGRES_URL_NON_POOLING'), // uses a direct connection + url: env('POSTGRES_URL_NON_POOLING'), // direct connection for Prisma CLI }, }) ``` @@ -211,8 +210,7 @@ import { defineConfig, env } from 'prisma/config' export default defineConfig({ schema: 'prisma/schema.prisma', datasource: { - url: env('POSTGRES_PRISMA_URL'), // uses connection pooling - directUrl: env('POSTGRES_URL_NON_POOLING'), // uses a direct connection + url: env('POSTGRES_URL_NON_POOLING'), // direct connection for Prisma CLI }, }) ``` diff --git a/content/300-accelerate/200-getting-started.mdx b/content/300-accelerate/200-getting-started.mdx index b06abc67a4..2401e0f1b3 100644 --- a/content/300-accelerate/200-getting-started.mdx +++ b/content/300-accelerate/200-getting-started.mdx @@ -41,14 +41,7 @@ DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=__API_KEY__" # DATABASE_URL="postgresql://user:password@host:port/db_name?schema=public" ``` -Your updated connection string will be used as the datasource `url` in your Prisma schema file; - -```prisma -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} -``` +Prisma Client reads the `prisma://` URL from `DATABASE_URL` at runtime, while Prisma CLI commands use the connection string defined in `prisma.config.ts`. Prisma Migrate and Introspection do not work with a `prisma://` connection string. In order to continue using these features add a new variable to the `.env` file named `DIRECT_DATABASE_URL` whose value is the direct database connection string: @@ -57,15 +50,18 @@ DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=__API_KEY__" DIRECT_DATABASE_URL="postgresql://user:password@host:port/db_name?schema=public" ``` -Then in your Prisma schema's `datasource` block add a field named `directUrl` with the following: +Then point `prisma.config.ts` to the direct connection string: -```prisma -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -//add-next-line - directUrl = env("DIRECT_DATABASE_URL") -} +```ts file=prisma.config.ts showLineNumbers +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config' + +export default defineConfig({ + schema: 'prisma/schema.prisma', + datasource: { + url: env('DIRECT_DATABASE_URL'), + }, +}) ``` Migrations and introspections will use the `directUrl` connection string rather than the one defined in `url` when this configuration is provided. @@ -134,7 +130,9 @@ Add the following to extend your existing Prisma Client instance with the Accele import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' -const prisma = new PrismaClient().$extends(withAccelerate()) +const prisma = new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()) ``` If you are going to deploy to an edge runtime (like Cloudflare Workers, Vercel Edge Functions, Deno Deploy, or Supabase Edge Functions), use our edge client instead: @@ -143,7 +141,9 @@ If you are going to deploy to an edge runtime (like Cloudflare Workers, Vercel E import { PrismaClient } from '@prisma/client/edge' import { withAccelerate } from '@prisma/extension-accelerate' -const prisma = new PrismaClient().$extends(withAccelerate()) +const prisma = new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}).$extends(withAccelerate()) ``` If VS Code does not recognize the `$extends` method, refer to [this section](/accelerate/faq#vs-code-does-not-recognize-the-extends-method) on how to resolve the issue. @@ -155,7 +155,11 @@ Since [extensions are applied one after another](/orm/prisma-client/client-exten If you are using [Prisma Optimize](/optimize) in your application, make sure you apply it _before_ the Accelerate extension. For example: ```ts -const prisma = new PrismaClient().$extends(withOptimize()).$extends(withAccelerate()) +const prisma = new PrismaClient({ + accelerateUrl: process.env.DATABASE_URL, +}) + .$extends(withOptimize()) + .$extends(withAccelerate()) ``` ### 2.5. Use Accelerate in your database queries From 50b8d99deb9d9bf8f3b2b886ca294365f9fe1ed6 Mon Sep 17 00:00:00 2001 From: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> Date: Tue, 18 Nov 2025 03:04:39 +0600 Subject: [PATCH 15/23] feat: add mentions of new Prisma Studio (#7270) * feat: add mentions of new Prisma Studio * feat: add note for Studio for SQLite * Update content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx * Update content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx * fix: make prisma studio docs more accurate * fix: add missing punctuation --- .../100-quickstart/200-sqlite.mdx | 8 + .../100-quickstart/700-cockroachdb.mdx | 6 +- .../100-quickstart/800-mongodb.mdx | 6 +- .../200-sqlite.mdx | 9 + .../700-cockroachdb.mdx | 6 +- .../800-mongodb.mdx | 6 +- .../_components/_explore-data.mdx | 6 + .../200-orm/400-tools/06-prisma-studio.mdx | 283 +++++------------- .../200-prisma-cli-reference.mdx | 34 ++- .../50-studio-in-vs-code.mdx | 8 + 10 files changed, 159 insertions(+), 213 deletions(-) diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx index 14f227368c..09a11a2665 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx @@ -266,6 +266,14 @@ You should see the created user and all users printed to the console! +:::note[SQLite requirements for Prisma Studio] +- File paths must have a `file:` protocol right now in the database url for SQLite +- Node.js 22.5+: Works out of the box with the built-in `node:sqlite` module +- Node.js 20: Requires installing `better-sqlite3` as a dependency + - If using pnpm 10+, you'll also need to allow the `better-sqlite3` install script + +::: + ## Next steps diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx index 601a6a775b..043ae8af05 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx @@ -268,9 +268,11 @@ npx tsx script.ts You should see the created user and all users printed to the console! -## 9. Explore your data with Prisma Studio +## 9. Explore your data - +Explore the options suggested by [CockroachDB](https://www.cockroachlabs.com/blog/cockroachdb-gui-options/) to view and manage your data. + +[Prisma Studio](/orm/tools/prisma-studio) does not currently support CockroachDB. Support may be added in a future release. See [Databases supported by Prisma Studio](/orm/tools/prisma-studio#databases-supported-by-prisma-studio) for more information. ## Next steps diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx index 13b0375a2e..b9914f6bb0 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx @@ -276,9 +276,11 @@ npx tsx script.ts You should see the created user and all users printed to the console! -## 9. Explore your data with Prisma Studio +## 9. Explore your data - +You can use [MongoDB Atlas](https://www.mongodb.com/cloud/atlas), the MongoDB shell, or MongoDB Compass to view and manage your data. + +[Prisma Studio](/orm/tools/prisma-studio) does not currently support MongoDB. Support may be added in a future release. See [Databases supported by Prisma Studio](/orm/tools/prisma-studio#databases-supported-by-prisma-studio) for more information. ## Next steps diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx index 4829c9be51..2730ac382c 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/200-sqlite.mdx @@ -249,6 +249,15 @@ This command will: +:::note[SQLite requirements for Prisma Studio] + +- File paths must have a `file:` protocol right now in the database url for SQLite +- Node.js 22.5+: Works out of the box with the built-in `node:sqlite` module +- Node.js 20: Requires installing `better-sqlite3` as a dependency + - If using pnpm 10+, you'll also need to allow the `better-sqlite3` install script + +::: + ## Next steps diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx index 5b878d723c..e556f84f32 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/700-cockroachdb.mdx @@ -246,9 +246,11 @@ This command will: - Apply the migration to your database - Regenerate Prisma Client -## 10. Explore your data with Prisma Studio +## 10. Explore your data - +Explore the options suggested by [CockroachDB](https://www.cockroachlabs.com/blog/cockroachdb-gui-options/) to view and manage your data. + +[Prisma Studio](/orm/tools/prisma-studio) does not currently support CockroachDB. Support may be added in a future release. See [Databases supported by Prisma Studio](/orm/tools/prisma-studio#databases-supported-by-prisma-studio) for more information. ## Next steps diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx index b0cf0e76b9..e1c7e068ab 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx @@ -292,9 +292,11 @@ Prisma Migrate is not supported for MongoDB. Use `prisma db push` to sync your s ::: -## 9. Explore your data with Prisma Studio +## 9. Explore your data - +You can use [MongoDB Atlas](https://www.mongodb.com/cloud/atlas), the MongoDB shell, or MongoDB Compass to view and manage your data. + +[Prisma Studio](/orm/tools/prisma-studio) does not currently support MongoDB. Support may be added in a future release. See [Databases supported by Prisma Studio](/orm/tools/prisma-studio#databases-supported-by-prisma-studio) for more information. ## Next steps diff --git a/content/100-getting-started/_components/_explore-data.mdx b/content/100-getting-started/_components/_explore-data.mdx index 8e1ecd0362..e69f7fce73 100644 --- a/content/100-getting-started/_components/_explore-data.mdx +++ b/content/100-getting-started/_components/_explore-data.mdx @@ -5,3 +5,9 @@ npx prisma studio --config ./prisma.config.ts ``` This opens a web interface where you can view and edit your data. + +:::info[Supported databases] + +Prisma Studio currently supports PostgreSQL, MySQL, and SQLite. For more details, see [Databases supported by Prisma Studio](/orm/tools/prisma-studio#databases-supported-by-prisma-studio). + +::: diff --git a/content/200-orm/400-tools/06-prisma-studio.mdx b/content/200-orm/400-tools/06-prisma-studio.mdx index 48a1594924..95832603ab 100644 --- a/content/200-orm/400-tools/06-prisma-studio.mdx +++ b/content/200-orm/400-tools/06-prisma-studio.mdx @@ -5,262 +5,145 @@ metaDescription: 'Prisma Studio is a visual database editor.' toc_max_heading_level: 2 --- -import StudioStringSvg from '/img/studio/string.svg'; -import StudioNumberSvg from '/img/studio/number.svg'; -import StudioDatetimeSvg from '/img/studio/datetime.svg'; -import StudioBooleanSvg from '/img/studio/boolean.svg'; -import StudioEnumSvg from '/img/studio/enum.svg'; -import StudioArraySvg from '/img/studio/array.svg'; -import StudioObjectSvg from '/img/studio/object.svg'; +Prisma Studio is a standalone visual database editor that lets you view and manipulate data directly in your browser. Unlike previous versions, Prisma Studio is now SQL-driven and works independently of Prisma ORM—you can use it with any database without needing a Prisma schema or project. -Prisma Studio is a visual editor for the data in your database. Note that Prisma Studio is not open source but you can still create issues in the [`prisma/studio`](https://github.com/prisma/studio) repo. +Note that Prisma Studio is not open source but you can still create issues in the [`prisma/studio`](https://github.com/prisma/studio) repo. -Run `npx prisma studio` in your terminal. +## Prerequisites -## Models (tables or collections) +Prisma Studio is a standalone tool that only requires a database connection. You have two options: -When you first open Prisma Studio, you will see a data table layout with a sidebar showing a list of all models defined in your Prisma schema file. +### Option 1: Use with any database (no Prisma project required) -![Prisma Studio - Models view](/img/studio/01-models-view.png) +Connect directly to any supported database using the `--url` flag: -:::info -**What is a model?**

- -The term **model** refers to the data model definitions that you add to the Prisma schema file. Depending on the database that you use, a model definition, such as `model User`, refers to a **table** in a relational database (PostgreSQL, MySQL, SQL Server, SQLite, CockroachDB) or a **collection** in MongoDB.

-For more information, see [Defining models](/orm/prisma-schema/data-model/models#defining-models). -::: - -You can select a model and its data opens in a new tab. In this example, the `User` model is selected. - - -![Prisma Studio - Models view with model open](/img/studio/02-open-model.png) - - -### Open and close models - -To open another model, locate the model in the sidebar and click on it. - -To close a model, click the the **X** button in the model tab. If there are multiple models open, you can also click "Close all" to close all models. - - -![Prisma Studio - Open and close models](/img/studio/03-open-close-models.png) - -### Icons of data types in models - -The data type for each field is indicated with an icon in the header. - -The table below lists all data types and their identifying icon. - -| Field data type | Description | -| :-------------------------------------------------------------------------------: | ------------------------------------ | -| | Text | -| | Integer | -| | Date-time

| -| | Boolean
| -| | Pre-defined list of values (`enum` data type) | -| | List of related records from another model | -| | The `{}` symbol can refer to one of the two types of fields.

• Relation field
• JSON field | - -### Keyboard shortcuts in models - -When you open a model, a number of keyboard shortcuts are available to browse and manipulate the data in the model. - - -:::info -**Note**

-With Prisma Studio open, you can open the keyboard shortcuts modal by pressing Cmd ⌘+/ on macOS or Ctrl+/ on Windows. -::: +```terminal +npx prisma studio --url="postgresql://user:password@localhost:5432/dbname" +``` +This approach works without any Prisma ORM setup—Studio will introspect your database schema directly. -![Prisma Studio - Keyboard shortcuts](/img/studio/04-model-view-keyboard-shortcuts.png) +### Option 2: Use with a Prisma ORM project -## Edit data +If you have an existing Prisma project, Studio can read your configuration: -Prisma Studio offers two mechanisms for editing existing data: [in-line editing](#in-line-editing) and [side panel editing](#side-panel-editing). +- A `prisma/schema.prisma` file with at least one model defined +- A `prisma.config.ts` configuration file +- A configured database connection -### In-line editing +## Getting started -To edit data in-line, double-click a cell to enter edit mode. Doing so will place your cursor in the cell and allow you to edit the data. Data can be copied and pasted into cells. +### Standalone usage (without Prisma ORM) -All changes (add, edit, or delete) must be confirmed before they will take effect. Confirm added and edited records with the **Save change** button. When you select records and click **Delete records**, confirm the deletion in a dialog box. +To launch Prisma Studio with any database, provide a connection URL: -You can accumulate multiple added records and edited cells, which you can then finalize with the **Save changes** button. +```terminal +npx prisma studio --url="postgresql://user:password@localhost:5432/dbname" +``` +### With a Prisma ORM project -![Prisma Studio - Save inline changes](/img/studio/11-save-inline-changes.png) -Once you have finished editing the data, click the green **Save** button. +If you have a Prisma project, run the following command in your project directory: +```terminal +npx prisma studio --config ./prisma.config.ts +``` -![Prisma Studio - Save inline changes](/img/studio/11-save-inline-changes.png) +Both commands start a local web server (default port `5555`) and open Prisma Studio in your browser. Studio connects to your database and introspects the schema to provide a visual interface for your data. -### Batch editing +## Core features -Multiple records can be edited at once. Double click any cell to edit values, moving to any additional cells as necessary. Once complete, click the green **Save** button. +Prisma Studio provides several key capabilities for working with your database: +### Browse your data -![Prisma Studio - Save multiple inline changes](/img/studio/12-save-multiple-inline-changes.png) +Studio displays all tables from your database in a sidebar. Select any table to view its data in a table format. You can open multiple tables in separate tabs to work with related data simultaneously. -### Side panel editing +### View and edit records -Prisma Studio also offers a side panel for editing data. To open the side panel, click the **Edit side panel** icon located beside the select checkbox at the far left of every visible record. +You can edit data in two ways: +- **Inline editing**: Double-click any cell to edit its value directly in the table +- **Side panel editing**: Click the edit icon next to a record to open a detailed view with all fields -![Prisma Studio - Open side panel](/img/studio/13-edit-side-panel-icon.png) +Changes are accumulated and must be saved explicitly using the save button. This lets you make multiple edits before committing them to the database. -Clicking the icon will open the side panel on the right where edits can be performed. Once complete, click outside the side panel and click the green **Save** button to save the changes. +### Add new records +Create new records by clicking the "Add record" button. Studio provides appropriate input controls based on each field's data type: -![Prisma Studio - Edit side panel](/img/studio/14-edit-data-in-sidepanel.png) +- Text fields for strings +- Number inputs for integers and decimals +- Date pickers for datetime fields +- Dropdowns for enums and boolean values +- Relation selectors for foreign keys ### Delete records -1. From the left column, select the check box for the records you want to delete. -2. Click **Delete _n_ record(s)**. -3. Click **Delete** in the confirmation dialog. - -You can select multiple records and delete them at once with the **Delete records** button. When you delete multiple records, the operation completes immediately (after you confirm it). - -In addition, if you have any accumulated added or edited records and then decide to delete records, the deletion also force-saves the accumulated edits. - -:::warning -**Warning**

-Deleting a record is a separate operation that cannot be accumulated. If you delete a record while having unsaved edits, the delete operation first force-saves the unsaved edits and then completes. -::: - - -![Prisma Studio - Delete records](/img/studio/15-delete-records.png) - -You can discard any accumulated changes with the **Discard changes** button. - -![Prisma Studio - Discard changes](/img/studio/16-discard-changes.png) - -### Copy and paste - -You can copy the value of any table cell using: - -- Cmd ⌘ + C   on macOS -- Ctrl + C     on Windows - -To paste in another cell, first double-click the cell to enter edit mode, and then use: - -- Cmd ⌘ + V   on macOS -- Ctrl + V     on Windows - -### Add a record - -1. In the model view, click **Add record**. -2. Based on the data allowed in each field, type the data for the record. - - | Field data type | Description | - | :-------------------------------------------------------------------------------: | ------------------ | - | | Text | - | | Integer

If such a field has `autoincrement()` pre-filled, do not edit the cell and do not add a number manually. | - | | Date-time

Date-time fields contain a long string of numbers, letters, and others. As a best practice, copy the value of another date-time cell and modify it as necessary before pasting in the field. | - | | Boolean

Select `true` or `false`. | - | | Pre-defined list

Double-click a cell in the field and select one of the pre-defined options. | - | | List of related records from another model

It typically refers to a list of records that exist in another model in the database. If you are adding a new record and records from the related model do not yet exist, you do not need to enter anything in the current model. | - | | The `{}` symbol can refer to one of the two types of fields.

• Relation field
• JSON field

**Relation with a model defined separately in the database**

Typically, you need to select the same value as any of the previous records
Click the name of the model to see the list of values which you can then select for the related field.

**JSON field**

Double-click the field to edit the JSON data. As a best practice, validate the edited JSON data in a validator and paste it back in the cell. | - -3. (Optional) If you are unhappy with your changes, click **Discard changes** and start over. -4. Click **Save 1 change**. - -## Filters - -### Filter data - -Use the **Filters** menu to filter data in the model by adding conditions. - -In the **Filters** menu, the first condition that you add is the `where` clause. - -When you add multiple conditions, Prisma Studio filters the results so that all conditions apply in combination. Each new condition indicates this with the `and` operator, which appears in front. - -**Steps** - -1. Click **Filters** to open the **Filters** menu. - - :::info - **Note**
- Click **Filters** again if you want to hide the menu. - ::: - -2. Click **Add a new filter**. -3. Configure the condition. - 1. Select the field by which you want to filter. - 2. Select a comparison operator. - - **equals** - - **in** - - **notin** - - **lt** - - **lte** - - **gt** - - **gte** - - **not** - 3. Type the value you want to use for the condition.
- **Step result**: **Prisma Studio** updates the data in the model immediately, based on the condition. -4. To add a new filter, click **Add a new filter** and repeat the steps above. -5. To remove a filter, click the **x** button on the right. - ![Prisma Studio - Add and remove filters](/img/studio/06-add-remove-filters.png) -6. To remove all filters, click **Clear all**. - -**Result** +Select one or more records using the checkboxes and click the delete button. Deletions require confirmation and are applied immediately (they cannot be batched with other changes). -- The data in the model is filtered based on the combination of all conditions you add. -- In the **Filters** menu, the default value of **None** changes to display the number of filters you add. +### Filter and search -### Show and hide fields +Use the Filters menu to narrow down your data: -You can select which fields to view or hide by using the **Fields** menu. +- Add conditions using comparison operators (equals, greater than, less than, etc.) +- Combine multiple filters with AND logic +- Clear individual filters or all filters at once -:::info -**What is a field?**
+### Control visibility -A **field** is a property of a model which you add in the data model definitions in the Prisma schema file. Depending on the database that you use, a field, such as the `title` field in `model User { title String }`, refers to a **column** in a relational database (PostgreSQL, MySQL, SQL Server, SQLite, CockroachDB) or a **document field** in MongoDB.
-For more information, see [Defining fields](/orm/prisma-schema/data-model/models#defining-fields). -::: +Customize your view: -**Steps** +- **Fields menu**: Show or hide specific columns +- **Showing menu**: Control pagination with "Take" (limit) and "Skip" (offset) options -1. Click the **Fields** menu. -2. Select only the fields you want to see and deselect any fields you want to hide. - ![Prisma Studio - Show and hide fields](/img/studio/07-show-hide-fields.png) +### Sort data -**Result** +Click any column header to sort by that field. Click again to toggle between ascending and descending order. -The model is immediately filtered to hide the data from any fields you have deselected. +### Keyboard shortcuts -Also, the **Fields** menu shows the number of fields that are currently selected. +Studio supports keyboard shortcuts for common operations. Press Cmd+/ (macOS) or Ctrl+/ (Windows) to view all available shortcuts. -### Show and hide records +## Understanding data types -You can also select to show or skip a specific number of records in the model view. +Studio displays visual indicators for different field types in your database: -:::info -**What is a record?**
+- **Text fields**: String values +- **Number fields**: Integers and decimals +- **Date/time fields**: Timestamps and dates +- **Boolean fields**: True/false values +- **Enum fields**: Predefined list of options +- **Relation fields**: References to records in other tables (foreign keys) +- **JSON fields**: Structured JSON data -A **record** refers to a **row of data in a table** in a relational database (PostgreSQL, MySQL, SQL Server, SQLite, CockroachDB) or a **document** in MongoDB. -::: +These visual cues help you quickly understand your data structure as Studio introspects it directly from your database. -**Steps** +## Working with relations -1. Click the **Showing** menu. -2. In the **Take** box, specify the maximum number of records that you want the model view to show. -3. In the **Skip** box, specify how many of the first records you want to hide. - ![Prisma Studio - Show and hide records](/img/studio/08-show-hide-records.png) +When your database tables have foreign key relationships, Studio provides tools to navigate and edit related data: -**Result** +- Click on a relation field to view the related record +- Use relation selectors when creating or editing records to link to existing data +- Open related tables in separate tabs to work with connected data simultaneously -The model is immediately filtered to show or hide records based on your selection. +## Databases supported by Prisma Studio -The **Showing** menu indicates how many records are shown out of how many available records are in the model. +Prisma Studio currently supports the following databases: PostgreSQL, MySQL, and SQLite. -## Sort data +### SQLite requirements for Prisma Studio -Click a field title to sort by the field data. +- File paths must have a `file:` protocol right now in the database url for SQLite +- Node.js 22.5+: Works out of the box with the built-in `node:sqlite` module +- Node.js 20: Requires installing `better-sqlite3` as a dependency + - If using pnpm 10+, you'll also need to allow the `better-sqlite3` install script -The first click sorts the data in ascending order, the second - in descending order. +### Databases not yet supported +Support for CockroachDB and MongoDB is not currently available but may be added in future releases. If you're using these databases: -![Prisma Studio - Sort data](/img/studio/09-model-sort.png) +- CockroachDB: Explore the options suggested by [CockroachDB](https://www.cockroachlabs.com/blog/cockroachdb-gui-options/) +- MongoDB: Use [MongoDB Atlas](https://www.mongodb.com/cloud/atlas), MongoDB Compass, or the MongoDB shell ## Troubleshooting diff --git a/content/200-orm/500-reference/200-prisma-cli-reference.mdx b/content/200-orm/500-reference/200-prisma-cli-reference.mdx index aac2536e20..fa53209561 100644 --- a/content/200-orm/500-reference/200-prisma-cli-reference.mdx +++ b/content/200-orm/500-reference/200-prisma-cli-reference.mdx @@ -1707,6 +1707,16 @@ Starts the [Prisma MCP server](/postgres/integrations/mcp-server). The `studio` command allows you to interact with and manage your data interactively. It does this by starting a local web server with a web app configured with your project's data schema and records. +Prisma ORM v7 introduces a more stable version of Prisma Studio with improved performance and a modernized architecture. + +:::info[Supported databases] + +Prisma Studio currently supports PostgreSQL, MySQL, and SQLite. Support for CockroachDB and MongoDB is not available yet but may be added in future releases. + +For detailed database support information, including SQLite requirements, see [Databases supported by Prisma Studio](/orm/tools/prisma-studio#databases-supported-by-prisma-studio). + +::: + #### Prerequisites Before using the `studio` command, you must configure your database connection in your `prisma.config.ts` file. @@ -1742,11 +1752,13 @@ export default defineConfig({ The `studio` command recognizes the following options: -| Option | Required | Description | Default | -| ----------------- | -------- | ----------------------------------- | ------------------------ | -| `-b`, `--browser` | No | The browser to auto-open Studio in. | `` | -| `-h`, `--help` | No | Show all available options and exit | | -| `-p`, `--port` | No | The port number to start Studio on. | 5555 | +| Option | Required | Description | Default | +| ----------------- | -------- | -------------------------------------------------------------------------------- | ------------------------ | +| `-b`, `--browser` | No | The browser to auto-open Studio in. | `` | +| `-h`, `--help` | No | Show all available options and exit | | +| `-p`, `--port` | No | The port number to start Studio on. | 5555 | +| `--config` | No | Custom path to your Prisma config file | | +| `--url` | No | Database connection string (overrides the one in your Prisma config) | | #### Arguments @@ -1780,6 +1792,18 @@ prisma studio --browser firefox prisma studio --browser none ``` +#### Start Studio with a custom Prisma config file + +```terminal +prisma studio --config=./prisma.config.ts +``` + +#### Start Studio with a direct database connection string + +```terminal +prisma studio --url="postgresql://user:password@localhost:5432/dbname" +``` + ## `package.json` entry options ### `schema` diff --git a/content/250-postgres/300-database/675-prisma-studio/50-studio-in-vs-code.mdx b/content/250-postgres/300-database/675-prisma-studio/50-studio-in-vs-code.mdx index 295333ab67..33869333f1 100644 --- a/content/250-postgres/300-database/675-prisma-studio/50-studio-in-vs-code.mdx +++ b/content/250-postgres/300-database/675-prisma-studio/50-studio-in-vs-code.mdx @@ -10,6 +10,14 @@ toc: true You can use Prisma Studio directly in VS Code via the [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma). +:::info[Supported databases] + +Prisma Studio currently supports PostgreSQL, MySQL, and SQLite. Support for CockroachDB and MongoDB is not available yet but may be added in future releases. + +For detailed database support information, including SQLite requirements, see [Databases supported by Prisma Studio](/orm/tools/prisma-studio#databases-supported-by-prisma-studio). + +::: + ## Usage 1. Install the [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) From 311bc165d6fe6eb8f58c4a36193c96639ce77751 Mon Sep 17 00:00:00 2001 From: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> Date: Tue, 18 Nov 2025 03:45:07 +0600 Subject: [PATCH 16/23] feat: add mention of mongo support coming for P7 (#7271) * feat: add mention of mongo support coming for mongo * fix: refinements * Update content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx --- .../100-quickstart/100-prisma-postgres.mdx | 1 - .../100-quickstart/200-sqlite.mdx | 1 - .../100-quickstart/300-postgresql.mdx | 1 - .../100-quickstart/400-mysql.mdx | 1 - .../100-quickstart/500-sql-server.mdx | 1 - .../100-quickstart/600-planetscale.mdx | 1 - .../100-quickstart/700-cockroachdb.mdx | 1 - .../100-quickstart/800-mongodb.mdx | 52 ++++++---- .../800-mongodb.mdx | 66 ++++++++----- .../03-prisma-postgres/100-from-the-cli.mdx | 6 +- .../500-databases/600-mongodb.mdx | 8 +- .../225-import-from-existing-database.mdx | 14 +++ .../800-guides/050-migrate-from-mongoose.mdx | 96 +++++++++++++------ 13 files changed, 166 insertions(+), 83 deletions(-) create mode 100644 content/250-postgres/100-introduction/225-import-from-existing-database.mdx diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx index a5cb227c42..b24bc0c59e 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/100-prisma-postgres.mdx @@ -90,7 +90,6 @@ This command does a few things: - Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models - Creates a new Prisma Postgres database (when using `--db` flag) - Creates a `.env` file in the root directory for environment variables -- Generates the Prisma Client in the `generated/prisma/` directory - Creates a `prisma.config.ts` file for Prisma configuration The generated `prisma.config.ts` file looks like this: diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx index 09a11a2665..289ee857df 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/200-sqlite.mdx @@ -84,7 +84,6 @@ This command does a few things: - Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models - Creates a `.env` file in the root directory for environment variables -- Generates the Prisma Client in the `generated/prisma/` directory - Creates a `prisma.config.ts` file for Prisma configuration The generated `prisma.config.ts` file looks like this: diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx index bb7b117053..2a0837fb3c 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/300-postgresql.mdx @@ -94,7 +94,6 @@ This command does a few things: - Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models - Creates a `.env` file in the root directory for environment variables -- Generates the Prisma Client in the `generated/prisma/` directory - Creates a `prisma.config.ts` file for Prisma configuration The generated `prisma.config.ts` file looks like this: diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx index 6a02d9858b..9e8076c696 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/400-mysql.mdx @@ -90,7 +90,6 @@ This command does a few things: - Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models - Creates a `.env` file in the root directory for environment variables -- Generates the Prisma Client in the `generated/prisma/` directory - Creates a `prisma.config.ts` file for Prisma configuration The generated `prisma.config.ts` file looks like this: diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx index 9083dff2f1..e165e628fb 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/500-sql-server.mdx @@ -89,7 +89,6 @@ This command does a few things: - Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models - Creates a `.env` file in the root directory for environment variables -- Generates the Prisma Client in the `generated/prisma/` directory - Creates a `prisma.config.ts` file for Prisma configuration The generated `prisma.config.ts` file looks like this: diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx index f5836d6792..556f9c54bc 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/600-planetscale.mdx @@ -93,7 +93,6 @@ This command does a few things: - Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models - Creates a `.env` file in the root directory for environment variables -- Generates the Prisma Client in the `generated/prisma/` directory - Creates a `prisma.config.ts` file for Prisma configuration The generated `prisma.config.ts` file looks like this: diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx index 043ae8af05..7d8c33bbd7 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/700-cockroachdb.mdx @@ -88,7 +88,6 @@ This command does a few things: - Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models - Creates a `.env` file in the root directory for environment variables -- Generates the Prisma Client in the `generated/prisma/` directory - Creates a `prisma.config.ts` file for Prisma configuration The generated `prisma.config.ts` file looks like this: diff --git a/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx b/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx index b9914f6bb0..2cafd74597 100644 --- a/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx +++ b/content/100-getting-started/02-prisma-orm/100-quickstart/800-mongodb.mdx @@ -12,18 +12,17 @@ import NextSteps from '../../_components/_next-steps.mdx' [MongoDB](https://www.mongodb.com) is a popular NoSQL document database. In this guide, you will learn how to set up a new TypeScript project from scratch, connect it to MongoDB using Prisma ORM, and generate a Prisma Client for easy, type-safe access to your database. -:::warning[Do not upgrade to Prisma ORM v7 if you are using MongoDB] +:::warning[MongoDB support for Prisma ORM v7] -Prisma ORM v7 is not yet compatible with MongoDB. Please use Prisma ORM v6 instead. Support for MongoDB is coming in a future release. +**MongoDB support for Prisma ORM v7 is coming in the near future.** In the meantime, please use **Prisma ORM v6.19** (the latest v6 release) when working with MongoDB. + +This guide uses Prisma ORM v6.19 to ensure full compatibility with MongoDB. ::: ## Prerequisites - - -You also need: - +- Node.js installed in your system [with the supported version](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#minimum-supported-nodejs-versions) - A [MongoDB](https://www.mongodb.com/) database accessible via connection string ## 1. Create a new project @@ -35,10 +34,18 @@ You also need: Install the packages needed for this quickstart: ```terminal -npm install prisma @types/node --save-dev -npm install @prisma/client dotenv +npm install prisma@6.19 @types/node --save-dev +npm install @prisma/client@6.19 dotenv ``` +:::info[Why Prisma v6.19?] + +This is the latest stable version of Prisma ORM v6 that fully supports MongoDB. MongoDB support for Prisma ORM v7 is coming soon. + +You can also install `prisma@6` and `@prisma/client@6` to automatically get the latest v6 release. + +::: + Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma init`, `prisma db push`, and `prisma generate` @@ -94,11 +101,16 @@ npx prisma init --datasource-provider mongodb --output ../generated/prisma This command does a few things: -- Creates a `prisma/` directory with a `schema.prisma` file containing your database connection and schema models +- Creates a `prisma/` directory with a `schema.prisma` file for your database connection and schema models - Creates a `.env` file in the root directory for environment variables -- Generates the Prisma Client in the `generated/prisma/` directory - Creates a `prisma.config.ts` file for Prisma configuration +:::note + +Prisma Client will be generated in the `generated/prisma/` directory when you run `npx prisma generate` later in this guide. + +::: + The generated `prisma.config.ts` file looks like this: ```typescript file=prisma.config.ts @@ -156,7 +168,11 @@ Update your `.env` file with your MongoDB connection string: DATABASE_URL="mongodb+srv://username:password@cluster.mongodb.net/mydb" ``` -Replace with your actual MongoDB connection string. +:::tip + +Replace `username`, `password`, `cluster`, and `mydb` with your actual MongoDB credentials and database name. You can get your connection string from [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) or your MongoDB deployment. + +::: ## 5. Define your data model @@ -194,19 +210,21 @@ model Post { ## 6. Push your schema to MongoDB -Since MongoDB doesn't use migrations, push your schema directly: +MongoDB doesn't support migrations like relational databases. Instead, use `db push` to sync your schema: ```terminal npx prisma db push ``` -This command creates the collections based on your schema. +This command: +- Creates the collections in MongoDB based on your schema +- Automatically generates Prisma Client -Now run the following command to generate the Prisma Client: +:::info -```terminal -npx prisma generate -``` +Unlike relational databases, MongoDB uses a flexible schema. The `db push` command ensures your Prisma schema is reflected in your database without creating migration files. + +::: ## 7. Instantiate Prisma Client diff --git a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx index e1c7e068ab..fffdb11731 100644 --- a/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx +++ b/content/100-getting-started/02-prisma-orm/200-add-to-existing-project/800-mongodb.mdx @@ -11,6 +11,14 @@ import NextSteps from '../../_components/_next-steps.mdx' [MongoDB](https://www.mongodb.com/) is a popular document-based NoSQL database known for its flexibility, scalability, and developer-friendly features. In this guide, you will learn how to add Prisma ORM to an existing TypeScript project, connect it to MongoDB, introspect your existing database schema, and start querying with type-safe Prisma Client. +:::warning[MongoDB support for Prisma ORM v7] + +**MongoDB support for Prisma ORM v7 is coming in the near future.** In the meantime, please use **Prisma ORM v6.19** (the latest v6 release) when working with MongoDB. + +This guide uses Prisma ORM v6.19 to ensure full compatibility with MongoDB. + +::: + :::tip If you're migrating to Prisma ORM from Mongoose, see our [Migrate from Mongoose guide](/guides/migrate-from-mongoose). @@ -21,7 +29,7 @@ If you're migrating to Prisma ORM from Mongoose, see our [Migrate from Mongoose In order to successfully complete this guide, you need: -- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) +- [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#minimum-supported-nodejs-versions) for officially supported versions) - An existing TypeScript project with a `package.json` file - Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). @@ -44,8 +52,8 @@ If your project contains multiple directories with `package.json` files (e.g., ` Navigate to your existing project directory and install the required dependencies: ```terminal -npm install prisma @types/node --save-dev -npm install @prisma/client dotenv +npm install prisma@6.19 @types/node --save-dev +npm install @prisma/client@6.19 dotenv ``` Here's what each package does: @@ -54,9 +62,11 @@ Here's what each package does: - **`@prisma/client`** - The Prisma Client library for querying your database - **`dotenv`** - Loads environment variables from your `.env` file -:::info +:::info[Why Prisma v6.19?] + +This is the latest stable version of Prisma ORM v6 that fully supports MongoDB. MongoDB support for Prisma ORM v7 is coming soon. -MongoDB does not require a driver adapter like relational databases. Prisma Client connects directly to MongoDB. +You can also install `prisma@6` and `@prisma/client@6` to automatically get the latest v6 release. ::: @@ -121,6 +131,7 @@ generator client { datasource db { provider = "mongodb" + url = env("DATABASE_URL") } ``` @@ -138,23 +149,23 @@ For MongoDB Atlas, the connection URL format is: mongodb+srv://USERNAME:PASSWORD@CLUSTER.mongodb.net/DATABASE ``` -The [format of the connection URL](/orm/reference/connection-urls) for MongoDB looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): +Self-hosted MongoDB connection URL format: ``` mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE ``` -Here's a short explanation of each component: +Connection URL components: -- **`USERNAME`**: The name of your database user -- **`PASSWORD`**: The password for your database user -- **`HOST`**: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running -- **`PORT`**: The port where your database server is running (typically `27017` for MongoDB) -- **`DATABASE`**: The name of the database +- **`USERNAME`**: Your database user name +- **`PASSWORD`**: Your database user password +- **`HOST`**: The host where [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos) is running +- **`PORT`**: The port where your database server is running (typically `27017`) +- **`DATABASE`**: The name of your database :::tip -If you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. +For MongoDB Atlas, you can manually append the database name to the connection URL, as Atlas doesn't include it by default. ::: @@ -176,15 +187,20 @@ Run the following command to introspect your existing database: npx prisma db pull ``` -This command reads the `DATABASE_URL` environment variable, connects to your database, and introspects the database schema. Prisma ORM introspects a MongoDB schema by sampling the data stored in the database and inferring the schema. +This command: +- Reads the `DATABASE_URL` from your `.env` file +- Connects to your MongoDB database +- Samples documents in your collections to infer the schema +- Generates Prisma models in your `schema.prisma` file ![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) -After introspection, your Prisma schema will contain models that represent your existing MongoDB collections. - :::info -MongoDB introspection works by sampling documents in your collections. You may need to manually add relation fields using the `@relation` attribute to enable relational queries. +**MongoDB introspection limitations:** Prisma introspects MongoDB by sampling documents. You may need to manually: +- Add relation fields using the `@relation` attribute +- Adjust field types if the sampling didn't capture all variations +- Add indexes and constraints not detected during introspection ::: @@ -244,11 +260,11 @@ npx tsx script.ts ## 8. Evolve your schema -MongoDB does not use migrations. To make changes to your database schema: +MongoDB doesn't support migrations like relational databases. Instead, use `db push` to sync schema changes: ### 8.1. Update your Prisma schema file -Update your Prisma schema file to reflect the changes you want to make to your database schema. For example, add a new model: +Modify your Prisma schema file with the changes you want. For example, add a new model: ```prisma file=prisma/schema.prisma // add-start @@ -276,19 +292,19 @@ In MongoDB, the `id` field is mapped to `_id` and uses `@db.ObjectId` type. Rela ::: -### 8.2. Push the changes to your database: +### 8.2. Push the changes to your database ```terminal npx prisma db push ``` -This command will: -- Apply the schema changes to your MongoDB database -- Regenerate Prisma Client +This command: +- Applies schema changes to your MongoDB database +- Automatically regenerates Prisma Client -:::info +:::info[Why `db push` instead of migrations?] -Prisma Migrate is not supported for MongoDB. Use `prisma db push` to sync your schema changes. +MongoDB uses a flexible schema model. Prisma Migrate (which creates migration files) is not supported for MongoDB. Always use `prisma db push` to sync your schema changes. ::: diff --git a/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx b/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx index 8c8c91ccb6..adecf0e0e9 100644 --- a/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx +++ b/content/100-getting-started/03-prisma-postgres/100-from-the-cli.mdx @@ -129,7 +129,7 @@ Initialize a TypeScript project and add the Prisma CLI as a development dependen ```terminal npm init -y -npm install typescript tsx @types/node --save-dev +npm install typescript tsx @types/node @types/pg --save-dev ``` This creates a `package.json` file with an initial setup for your TypeScript app. @@ -173,7 +173,7 @@ Install the required dependencies to use Prisma Postgres: ```terminal npm install prisma --save-dev -npm install @prisma/client @prisma/adapter-pg dotenv +npm install @prisma/client @prisma/adapter-pg pg dotenv ``` Here's what each package does: @@ -181,6 +181,8 @@ Here's what each package does: - **`prisma`** - The Prisma CLI for running commands like `prisma migrate` and `prisma generate` - **`@prisma/client`** - The Prisma Client library for querying your database - **`@prisma/adapter-pg`** - The [`node-postgres` driver adapter](/orm/overview/databases/postgresql#using-the-node-postgres-driver) that connects Prisma Client to your database +- **`pg`** - The node-postgres database driver +- **`@types/pg`** - TypeScript type definitions for node-postgres - **`dotenv`** - Loads environment variables from your `.env` file ### 2.4. Create prisma.config.ts diff --git a/content/200-orm/050-overview/500-databases/600-mongodb.mdx b/content/200-orm/050-overview/500-databases/600-mongodb.mdx index a88868ec91..fe30f1ac21 100644 --- a/content/200-orm/050-overview/500-databases/600-mongodb.mdx +++ b/content/200-orm/050-overview/500-databases/600-mongodb.mdx @@ -12,9 +12,13 @@ codeStyle: false This guide discusses the concepts behind using Prisma ORM and MongoDB, explains the commonalities and differences between MongoDB and other database providers, and leads you through the process for configuring your application to integrate with MongoDB using Prisma ORM. -:::info +:::warning[MongoDB support for Prisma ORM v7] + +**MongoDB support for Prisma ORM v7 is coming in the near future.** In the meantime, please use **Prisma ORM v6.19** (the latest v6 release) when working with MongoDB. -To connect Prisma ORM with MongoDB, refer to our [Getting Started documentation](/getting-started/prisma-orm/quickstart/mongodb). +For getting started guides using Prisma ORM v6.19 with MongoDB, see: +- [Quickstart with MongoDB](/getting-started/prisma-orm/quickstart/mongodb) +- [Add to existing MongoDB project](/getting-started/prisma-orm/add-to-existing-project/mongodb) ::: diff --git a/content/250-postgres/100-introduction/225-import-from-existing-database.mdx b/content/250-postgres/100-introduction/225-import-from-existing-database.mdx new file mode 100644 index 0000000000..7420adf337 --- /dev/null +++ b/content/250-postgres/100-introduction/225-import-from-existing-database.mdx @@ -0,0 +1,14 @@ +--- +title: 'Import data from an existing PostgreSQL database' +sidebar_label: 'Import from existing database' +metaTitle: 'Import from existing Postgres database into Prisma Postgres' +metaDescription: 'Learn how to import data from an existing database into Prisma Postgres.' +tocDepth: 3 +toc: true +search: true +--- + +If you have an existing database and want to import your data into Prisma Postgres, you can use one of our guides: + +- [Import from PostgreSQL](/getting-started/prisma-postgres/import-from-existing-database-postgresql) +- [Import from MySQL](/getting-started/prisma-postgres/import-from-existing-database-mysql) \ No newline at end of file diff --git a/content/800-guides/050-migrate-from-mongoose.mdx b/content/800-guides/050-migrate-from-mongoose.mdx index e9a4b2b306..edfa5e2166 100644 --- a/content/800-guides/050-migrate-from-mongoose.mdx +++ b/content/800-guides/050-migrate-from-mongoose.mdx @@ -12,6 +12,14 @@ community_section: true This guide shows you how to migrate your application from Mongoose to Prisma ORM. We'll use an extended version of the [Mongoose Express example](https://github.com/Automattic/mongoose/tree/master/examples/express) as a [sample project](https://github.com/prisma/migrate-from-mongoose-to-prisma) to demonstrate the migration steps. +:::warning[MongoDB support for Prisma ORM v7] + +**MongoDB support for Prisma ORM v7 is coming in the near future.** In the meantime, please use **Prisma ORM v6.19** (the latest v6 release) when working with MongoDB. + +This guide uses Prisma ORM v6.19 to ensure full compatibility with MongoDB. + +::: + You can learn how Prisma ORM compares to Mongoose on the [Prisma ORM vs Mongoose](/orm/more/comparisons/prisma-and-mongoose) page. ## Prerequisites @@ -19,8 +27,8 @@ You can learn how Prisma ORM compares to Mongoose on the [Prisma ORM vs Mongoose Before starting this guide, make sure you have: - A Mongoose project you want to migrate -- Node.js installed (version 18 or higher) -- MongoDB database +- Node.js installed [with the supported version](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#minimum-supported-nodejs-versions) +- MongoDB database (4.2+ with replica set deployment recommended) - Basic familiarity with Mongoose and Express.js ## 1. Prepare for migration @@ -36,7 +44,24 @@ The steps for migrating from Mongoose to Prisma ORM are always the same, no matt These steps apply whether you're building a REST API (e.g., with Express, Koa, or NestJS), a GraphQL API (e.g., with Apollo Server, TypeGraphQL, or Nexus), or any other kind of application that uses Mongoose for database access. -### 1.2. Set up Prisma configuration +### 1.2. Install Prisma dependencies + +First, install the required Prisma packages: + +```terminal +npm install prisma@6.19 @types/node --save-dev +npm install @prisma/client@6.19 dotenv +``` + +:::info[Why Prisma v6.19?] + +This is the latest stable version of Prisma ORM v6 that fully supports MongoDB. MongoDB support for Prisma ORM v7 is coming soon. + +You can also install `prisma@6` and `@prisma/client@6` to automatically get the latest v6 release. + +::: + +### 1.3. Set up Prisma configuration Create a new Prisma schema file: @@ -48,21 +73,20 @@ This command creates: - A new directory called `prisma` that contains a `schema.prisma` file; your Prisma schema specifies your database connection and models - `.env`: A [`dotenv`](https://github.com/motdotla/dotenv) file at the root of your project (if it doesn't already exist), used to configure your database connection URL as an environment variable +- `prisma.config.ts`: Configuration file for Prisma -The Prisma schema currently looks as follows: +The Prisma schema uses the ESM-first `prisma-client` generator: ```prisma file=prisma/schema.prisma showLineNumbers -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema +generator client { + provider = "prisma-client" + output = "../generated/prisma" +} datasource db { provider = "mongodb" url = env("DATABASE_URL") } - -generator client { - provider = "prisma-client-js" -} ```
@@ -75,38 +99,54 @@ For an optimal development experience when working with Prisma ORM, refer to [ed Update the `DATABASE_URL` in the `.env` file with your MongoDB connection string: ```env -DATABASE_URL="mongodb://USER:PASSWORD@HOST:PORT/DATABASE" +DATABASE_URL="mongodb+srv://username:password@cluster.mongodb.net/mydb" ``` -### 1.3. Configure Prisma +:::tip + +Replace `username`, `password`, `cluster`, and `mydb` with your actual MongoDB credentials and database name. You can get your connection string from [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) or your MongoDB deployment. -Create a `prisma.config.ts` file in the root of your project with the following content: +::: + +### 1.4. Configure Prisma + +The generated `prisma.config.ts` file should look like this: ```typescript file=prisma.config.ts -import 'dotenv/config' -import { defineConfig, env } from 'prisma/config'; +import { defineConfig, env } from 'prisma/config' export default defineConfig({ schema: 'prisma/schema.prisma', migrations: { path: 'prisma/migrations', }, + engine: "classic", datasource: { url: env('DATABASE_URL'), }, -}); +}) ``` -:::note +Add `dotenv` to load environment variables from your `.env` file: -You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: +```typescript file=prisma.config.ts +// add-start +import 'dotenv/config' +// add-end +import { defineConfig, env } from 'prisma/config' -```bash -npm install dotenv +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + engine: "classic", + datasource: { + url: env('DATABASE_URL'), + }, +}) ``` -::: - ## 2. Migrate the database schema ### 2.1. Introspect your database @@ -261,20 +301,16 @@ model users { ## 3. Update your application code -### 3.1. Install Prisma Client +### 3.1. Generate Prisma Client -Install the Prisma Client package: - -```terminal -npm install @prisma/client -``` - -After installing the Prisma Client package, generate Prisma Client: +Generate Prisma Client based on your schema: ```terminal npx prisma generate ``` +This creates a type-safe Prisma Client in the `generated/prisma` directory. + ### 3.2. Replace Mongoose queries Start replacing your Mongoose queries with Prisma Client. Here's an example of how to convert some common queries: From e54a8cd38e094cfc79392069e0e9f0866fe4e47b Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Mon, 10 Nov 2025 15:53:27 -0500 Subject: [PATCH 17/23] docs(postgres): remove accelerate reference Remove reference to accelerate and rework the docs to account for the new v7 changes --- .../100-introduction/250-overview.mdx | 18 +- .../250-postgres/300-database/350-caching.mdx | 249 ------------------ .../300-database/400-connection-pooling.mdx | 30 +-- .../300-database/550-local-development.mdx | 2 - .../300-database/650-direct-connections.mdx | 20 +- .../300-database/750-serverless-driver.mdx | 12 +- .../800-api-reference/100-caching-api.mdx | 231 ---------------- .../800-api-reference/200-error-reference.mdx | 6 +- .../350-integrations/100-netlify.mdx | 45 ++-- .../350-integrations/200-vercel.mdx | 26 +- .../400-query-optimization/100-setup.mdx | 27 +- .../400-repeated-query.mdx | 8 +- static/img/postgres/connection-string.png | Bin 0 -> 263537 bytes 13 files changed, 63 insertions(+), 611 deletions(-) delete mode 100644 content/250-postgres/300-database/350-caching.mdx delete mode 100644 content/250-postgres/300-database/800-api-reference/100-caching-api.mdx create mode 100644 static/img/postgres/connection-string.png diff --git a/content/250-postgres/100-introduction/250-overview.mdx b/content/250-postgres/100-introduction/250-overview.mdx index 8b5300dc91..a5bffb88ca 100644 --- a/content/250-postgres/100-introduction/250-overview.mdx +++ b/content/250-postgres/100-introduction/250-overview.mdx @@ -12,7 +12,7 @@ toc: true It supports the following workflows: - Schema migrations and queries (via [Prisma ORM](https://www.prisma.io/orm) or any other ORM/database library) -- Connection pooling and caching (via [Prisma Accelerate](https://www.prisma.io/accelerate)) +- Connection pooling and caching - Local database workflows via [`prisma dev`](/postgres/database/local-development) ## Usage metrics @@ -63,22 +63,6 @@ When changing your subscription from Free to Starter/Pro/Business or from Starte This is temporary. In the future, there won't be any downtime when up- or downgrading a plan. ::: -## Bundling with Prisma Accelerate - -Prisma Postgres comes bundled with [Prisma Accelerate](/accelerate). - -### Using the Client extension for Prisma Accelerate (required) - -Because all traffic to Prisma Postgres is routed through Accelerate's connection pool, your project must have the [`@prisma/extension-accelerate`](https://www.npmjs.com/package/@prisma/extension-accelerate) npm package installed. The extension then needs to be applied to the `PrismaClient` instance you use to interact with your database: - -```ts -import { PrismaClient } from '@prisma/client' -import { withAccelerate } from '@prisma/extension-accelerate' - -const prisma = new PrismaClient() - .$extends(withAccelerate()) -``` - ## Technical details ### PostgreSQL version diff --git a/content/250-postgres/300-database/350-caching.mdx b/content/250-postgres/300-database/350-caching.mdx deleted file mode 100644 index 10586c6bce..0000000000 --- a/content/250-postgres/300-database/350-caching.mdx +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: 'Caching queries in Prisma Postgres' -sidebar_label: 'Caching' -metaTitle: 'Caching queries in Prisma Postgres' -metaDescription: 'Learn about caching queries in Prisma Postgres' -tocDepth: 3 -toc: true ---- - -Prisma Postgres supports built-in query caching to reduce database load and improve query performance. You can configure cache behavior using the `cacheStrategy` option available in all read queries. - -This feature is powered by an internal caching layer enabled through [Prisma Accelerate](/accelerate), but you do not need to interact with Accelerate directly unless you're using your own database. - -## Cache strategies - -For all read queries in Prisma Client, you can define the `cacheStrategy` parameter that configures cache behavior. The cache strategy allows you to define two main characteristics of the cache: - -- **Time-to-live (TTL):** Duration in seconds a cached response is considered _fresh_. -- **Stale-while-Revalidating (SWR):** Duration in seconds a stale cache response is considered acceptable while the cache is refreshed in the background - -## Time-to-live (TTL) - -Time-to-Live (TTL) determines how long cached data is considered fresh. By specifying the `ttl` in seconds, you can control the duration for which data in the cache remains valid. When a read query is executed, if the cached response is within the `ttl` limit, Prisma Client retrieves the data from the cache without querying the database. If the cached data is not available or has expired, Prisma Client queries the database and stores the results in the cache for future requests. - -Use `ttl` in `cacheStrategy` and specify the TTL of the query in seconds: - -```javascript -await prisma.user.findMany({ - cacheStrategy: { - //add-next-line - ttl: 60, - }, -}); -``` - -With a specified TTL of 60 seconds, the majority of requests will result in -a cache hit throughout the TTL duration: - -![TTL](/img/accelerate/ttl.png) - -TTL is useful for reducing database load and latency for data that does not require frequent updates. - -### Invalidate the TTL and keep your cached query results up-to-date - -If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `ttl` (Time-To-Live). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed. - -For example, if a dashboard displays customer information and a customer’s contact details change, TTL (Time-To-Live) settings ensure the cache automatically expires after a set duration. This allows the system to refresh only the updated data at the next access, ensuring support staff always see the latest information without manually refreshing the cache. - -However, in cases where immediate updates are required before the TTL expires, cache invalidation allows the system to proactively clear specific data from the cache. This forces a refresh of the updated information instantly, so support staff always have the most current details without waiting for the TTL to trigger. - - -To invalidate a cached query result, you can add tags and then use the `$accelerate.invalidate` API. - -:::note - -On-demand cache invalidation is available with our paid plans. For more details, please see our [pricing](https://www.prisma.io/pricing#accelerate). - -::: - -To invalidate the query below, you need to provide the cache tag in the `$accelerate.invalidate` API: - -```ts -await prisma.user.findMany({ - cacheStrategy: { - ttl: 60, - //add-next-line - tags: ["findMany_users"], - }, -}); - -// This is how you would invalidate the cached query above. -//add-start -await prisma.$accelerate.invalidate({ - tags: ["findMany_users"], -}); -//add-end -``` - -## Stale-While-Revalidate (SWR) - -Stale-While-Revalidate (SWR) allows you to control how long Prisma Postgres can serve stale cache data while fetching fresh data in the background. When a read query is executed, Prisma Postgres checks the age of the cached response against the `swr` duration. If the cache data is within the `swr` limit, Prisma Postgres serves the stale data while simultaneously refreshing the cache by fetching the latest data from the database. - -Use `swr` in `cacheStrategy` and specify the SWR of the query in seconds: - -```javascript -await prisma.user.findMany({ - cacheStrategy: { - //add-next-line - swr: 60, - }, -}); -``` - -When specifying a SWR of 60 seconds, the cache serves stale data until the cache refreshes itself in the background after each request: - -![SWR](/img/accelerate/swr.png) - -### Invalidate the SWR and keep your cached query results up-to-date - -If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `swr` (Stale-While-Revalidate). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed. - -For example, consider a dashboard that displays stock levels for products in a warehouse. With SWR (Stale-While-Revalidate) settings, the dashboard can immediately display the last known stock data, even if it’s slightly outdated, while new data is fetched in the background. This ensures that staff can continue working with recent information without waiting, with the stock levels updating as soon as revalidation completes. - -However, in cases where stock data needs to be updated immediately—for instance, if a product is low in stock and the count needs real-time accuracy—cache invalidation allows the system to proactively clear specific data from the cache. This forces a refresh of the latest stock data instantly, so staff always have the most up-to-date information without waiting for SWR to complete the revalidation. - -To invalidate a cached query result, you can add tags and then use the `$accelerate.invalidate` API. - -:::note - -On-demand cache invalidation is available with our paid plans. For more details, please see our [pricing](https://www.prisma.io/pricing#accelerate). - -::: - -To invalidate the query below, you need to provide the cache tag in the `$accelerate.invalidate` API: - -```ts -await prisma.user.findMany({ - cacheStrategy: { - swr: 60, - //add-next-line - tags: ["findMany_users"], - }, -}); - -// This is how you would invalidate the cached query above. -//add-start -await prisma.$accelerate.invalidate({ - tags: ["findMany_users"], -}); -//add-end -``` - -## Selecting a cache strategy - -Caching helps you improve query response times and reduce database load. However, it also means you might serve stale data to the client. Whether or not serving stale data is acceptable and to what extent depends on your use case. `ttl` and `swr` are parameters you can use the tweak the cache behavior. - -### Cache strategy using TTL - -Use TTL to reduce database load when stale cached data is acceptable. - -#### Use case: Product catalog in e-commerce applications - -Consider an e-commerce application with a product catalog that doesn't frequently change. By setting a `ttl` of, let's say, 1 hour, Prisma Client can serve cached product data for subsequent user requests within that hour without hitting the database. This significantly reduces the database load and improves the response time for product listing pages. - -**When to invalidate:** If there are critical updates to the catalog, such as a major price change or product availability adjustment, the [cache should be invalidated](/postgres/database/caching#on-demand-cache-invalidation) immediately to prevent customers from seeing outdated information. - -### Cache strategy using SWR - -Use SWR to respond quickly to requests with minimal stale data. While it does not reduce database load, it can improve response times significantly. - -#### Use case: User profile in social media platforms - -Imagine a social media platform where user profiles are frequently accessed. By leveraging `swr` with a duration of, let's say, 5 minutes, Prisma Postgres can serve the cached user profile information quickly, reducing the latency for profile pages. Meanwhile, in the background, it refreshes the cache after every request, ensuring that any updates made to the profile are eventually reflected for subsequent requests. - -**When to invalidate:** If a user makes significant updates to their profile, such as changing their profile picture or bio, the cache should be [invalidated](/postgres/database/caching#on-demand-cache-invalidation) immediately to ensure that followers see the latest updates without waiting for the SWR refresh. - -### Cache strategy using TTL + SWR - -For very fast response times and reduced database load, use both TTL and SWR. You can use this strategy to fine-tune your application’s tolerance for stale data. - -Use `ttl` and `swr` in `cacheStrategy` and specify the TTL and SWR of the query in seconds: - -```javascript -await prisma.user.findMany({ - cacheStrategy: { - //add-start - ttl: 30, - swr: 60, - //add-end - }, -}); -``` - -When specifying a TTL of 30 seconds and SWR of 60 seconds, the cache serves fresh data for the initial 30 seconds. Subsequently, it serves stale data until the cache refreshes itself in the background after each request: - -![ttl_and_swr.png](/img/accelerate/ttl_and_swr.png) - -#### Use case: News articles - -Consider a news application where articles are frequently accessed but don't require real-time updates. By setting a `ttl` of 2 hours and an `swr` duration of 5 minutes, Prisma Client can serve cached articles quickly, reducing latency for readers. As long as the articles are within the `ttl`, users get fast responses. After the `ttl` expires, Prisma Client continues to serve the stale articles for up to an additional 5 minutes, revalidating the cache with the latest news from the database in response to a new query. This helps maintain a balance between performance and freshness. - -**When to invalidate:** If a critical update or breaking news article is published, the cache should be [invalidated](/postgres/database/caching#on-demand-cache-invalidation) immediately to ensure readers see the latest information without delay. This approach is especially useful for applications where certain news items may need to override the normal cache cycle for timeliness. - -## On-demand cache invalidation - -If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `ttl` (Time-To-Live) or `swr` (Stale-While-Revalidate) [cache strategy](/postgres/database/caching#cache-strategies). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed. - -You can invalidate the cache using the [`$accelerate.invalidate` API](/postgres/database/api-reference/caching-api#accelerateinvalidate): - -:::note - -To programmatically invalidate cached queries, a paid plan is required. See our [pricing for more details](https://www.prisma.io/pricing#accelerate). - -::: - -```ts -await prisma.user.findMany({ - where: { - email: { - contains: "alice@prisma.io", - }, - }, - cacheStrategy: { - swr: 60, - ttl: 60, - // highlight-start - tags: ["emails_with_alice"], - // highlight-end - }, -}); -``` - -You need to provide the cache tag in the `$accelerate.invalidate` API: - -```ts -try { - // highlight-start - await prisma.$accelerate.invalidate({ - tags: ["emails_with_alice"], - }); - // highlight-end -} catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - // The .code property can be accessed in a type-safe manner - if (e.code === "P6003") { - console.log( - "The cache invalidation rate limit has been reached. Please try again later." - ); - } - } - throw e; -} -``` - -Explore the [demo app](https://pris.ly/test-cache-invalidation) to see how cached query results in Prisma Postgres are invalidated on demand, shown in a clear timeline. - -## Default cache strategy - -Prisma Postgres defaults to **no cache** to avoid unexpected issues. While caching can improve performance, incorrect usage may lead to errors. - -For instance, if a query is executed on a critical path without specifying a cache strategy, the result may be incorrect, with no clear explanation. This issue often arises when implicit caching is unintentionally left enabled. - -To avoid such problems, you must explicitly opt-in to caching. This ensures you are aware that caching is not enabled by default, preventing potential errors. - -:::note - -When no cache strategy is specified or during a cache miss, the cache layer routes all queries to the database through a connection pool instance near the database region. - -::: \ No newline at end of file diff --git a/content/250-postgres/300-database/400-connection-pooling.mdx b/content/250-postgres/300-database/400-connection-pooling.mdx index 83f92d3e5e..38564bf582 100644 --- a/content/250-postgres/300-database/400-connection-pooling.mdx +++ b/content/250-postgres/300-database/400-connection-pooling.mdx @@ -6,40 +6,30 @@ tocDepth: 3 toc: true --- -Prisma Postgres provides built-in [connection pooling](https://www.prisma.io/dataguide/database-tools/connection-pooling) by default, enabled by [Prisma Accelerate](/accelerate/). By using Prisma Postgres, you get the benefits of connection pooling without having to configure anything. The efficient management of database connections allows the database to process more queries without exhausting the available database connections, making your application more scalable. - -In some cases, however, it may be beneficial to further configure connection pooling in order to optimize the performance of your application. - -:::note - -This document focuses on the connection pooling features of Prisma Postgres. For more information about the internal connection pool of Prisma ORM specifically, see our [ORM connection pooling documentation](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool). - -::: +Prisma Postgres provides built-in [connection pooling](https://www.prisma.io/dataguide/database-tools/connection-pooling) without you having to configure anything. The efficient management of database connections allows the database to process more queries without exhausting the available database connections, making your application more scalable. ### Connection pooling in Prisma Postgres -Currently, Prisma Postgres allows a maximum of 10 concurrent database connections per Prisma Schema. This limit is typically sufficient due to Prisma Postgres's efficient unikernel-based architecture, which minimizes the need for large connection pools. -:::note +For Prisma Postgres, the connection limit depends on the plan you have signed up for. -If you're using **your own database** with Prisma Accelerate, the connection limits differ: +| | Free | Starter | Pro | Business | +|---------------------------|------|---------|-----|----------| +| Connection Limit (Pooled) | 10 | 100 | 500 | 1000 | -- **Free plan**: Maximum of `10` connections. -- **Starter plan**: Maximum of `10` connections. This is often sufficient for most workloads, but if you're expecting high traffic or intensive compute operations, you may want to [increase this limit](#configuring-the-connection-pool-size). -- **Pro plan**: Supports up to `100` concurrent connections. -- **Business plan**: Supports up to `1000` concurrent connections. +:::note +For the **Starter plan**, this is often sufficient for most workloads, but if you're expecting high traffic or intensive compute operations, you may want to [increase this limit](#configuring-the-connection-pool-size). +::: You can compare plans on the [Prisma pricing page](https://www.prisma.io/pricing). -::: - ### Configuring the connection pool size -If you're **not using Prisma Postgres**, you can configure the connection pool size for Prisma ORM by specifying it [in the connection string](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#setting-the-connection-pool-size). +For Prisma Postgres, the connection limit is managed automatically for you. -For Prisma Postgres, the connection limit is currently **fixed at `10`** and cannot be changed. +If you're **not using Prisma Postgres**, you can configure the connection pool size for Prisma ORM by specifying it [in the connection string](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#setting-the-connection-pool-size). If you're using Prisma Accelerate with your own database, you can configure the connection pool size through the `Connection limit` setting in your project on the [Accelerate setup page](/accelerate/getting-started). diff --git a/content/250-postgres/300-database/550-local-development.mdx b/content/250-postgres/300-database/550-local-development.mdx index e74f746867..7c4b227212 100644 --- a/content/250-postgres/300-database/550-local-development.mdx +++ b/content/250-postgres/300-database/550-local-development.mdx @@ -21,9 +21,7 @@ Local Prisma Postgres is in [Preview](/orm/more/releases#preview) and is being a Follow these steps to set up local Prisma Postgres for development. :::note - Please ensure you're running Node.js 20 or later, as it's required for local Prisma Postgres. - ::: ### 1. Launching local Prisma Postgres diff --git a/content/250-postgres/300-database/650-direct-connections.mdx b/content/250-postgres/300-database/650-direct-connections.mdx index b63e7f4687..43b78648f0 100644 --- a/content/250-postgres/300-database/650-direct-connections.mdx +++ b/content/250-postgres/300-database/650-direct-connections.mdx @@ -8,7 +8,7 @@ toc: true ## Overview -Prisma Postgres is the perfect choice for your applications, whether you connect to it via [Prisma ORM](/orm) or any other ORM, database library / tool of your choice. If you use it with Prisma ORM, Prisma Postgres comes with built-in connection pooling and an integrated caching layer (powered by [Prisma Accelerate](/accelerate/)). +Prisma Postgres is the perfect choice for your applications, whether you connect to it via [Prisma ORM](/orm) or any other ORM, database library / tool of your choice. If you use it with Prisma ORM, Prisma Postgres comes with built-in connection pooling, and an integrated caching layer (powered by [Prisma Accelerate](/accelerate/)). If you connect to it via another tool, you can do so with a [direct connection string](#connection-string) following the conventional PostgreSQL format. @@ -18,10 +18,12 @@ In order to get a direct connection string, you need to: 1. Open a project in your [Prisma Console](https://console.prisma.io) account (or create a new one) 1. Navigate to your active Prisma Postgres instance. -1. Click the **API Keys** tab in the project's sidenav. -1. Click the **Create API key** button. -1. In the popup, provide a **Name** for the API key and click **Create**. -1. Copy the connection string starting with `postgres://`, this is your direct connection string. +1. Click the **Connect to your database** button in your dashboard. +1. Click the **Generate new connection string** button. +1. If enabling connection pooling, click the toggle button +1. Copy the connection string that is generated below. + +![](/img/postgres/connection-string.png) ## Connection string @@ -45,7 +47,7 @@ SSL mode is required when connecting to Prisma Postgres via direct TCP, so you n ## Billing -When using direct TCP to connect to a Prisma Postgres instance, every SQL query is counted as a [billable operation](/postgres/introduction/overview#usage-based-pricing). Learn more on our [pricing page](https://www.prisma.io/pricing). +When using direct TCP to connect to a Prisma Postgres instance, every request is counted asd a [billable operation](/postgres/introduction/overview#usage-based-pricing). Learn more on our [pricing page](https://www.prisma.io/pricing). ## Temporary limitations @@ -55,16 +57,12 @@ Prisma Postgres closes idle connections after an extended period of time. If tha ### Connection limit -While direct connections are in Early Access, the following connection limits apply: - | | Free | Starter | Pro | Business | | ------------------------------------ | ---------------- | ---------------- | ---------------- | ---------------- | | **Connection limit** | Max 10 | Max 10 | Max 50 | Max 100 | ### Query and transaction timeouts -While direct connections are in Early Access, the following timeouts apply: - | | Free | Starter | Pro | Business | | ------------------------------------ | ---------------- | ---------------- | ---------------- | ---------------- | | **Query timeout** | Up to 10 seconds | Up to 10 seconds | Up to 10 seconds | Up to 10 seconds | @@ -190,4 +188,4 @@ When using the TCP tunnel, keep the following in mind: - The tunnel does not support schema management (i.e., DDL queries outside of Prisma Migrate). - The tunnel should not be exposed to untrusted networks. - Always store API keys securely and avoid hardcoding them. -- Ensure that only necessary users have direct access to the Prisma Postgres database. \ No newline at end of file +- Ensure that only necessary users have direct access to the Prisma Postgres database. diff --git a/content/250-postgres/300-database/750-serverless-driver.mdx b/content/250-postgres/300-database/750-serverless-driver.mdx index 0fcba998fa..34f03e1223 100644 --- a/content/250-postgres/300-database/750-serverless-driver.mdx +++ b/content/250-postgres/300-database/750-serverless-driver.mdx @@ -9,12 +9,6 @@ sidebar_class_name: early-access-badge The serverless driver for Prisma Postgres is a lightweight and minimal client library that can talk to Prisma Postgres using raw SQL. You can use it via the [`@prisma/ppg`](https://github.com/prisma/ppg-client/tree/main) npm package. -:::warning - -The Prisma Postgres serverless driver is currently in [Early Access](/orm/more/releases#early-access) and not yet recommended for production scenarios. - -::: - ## Installation Install the serverless driver via npm: @@ -38,7 +32,7 @@ type Post = { authorId: number | null; } -const sql = ppg("prisma+postgres://accelerate.prisma-data.net/?api_key=..."); +const sql = ppg(YOUR_DATABASE_URL); const authorId = 1; const posts = await sql`SELECT * FROM "Post" WHERE "authorId" = ${authorId}`; @@ -103,7 +97,7 @@ type User = { email: string } -const sql = ppg("prisma+postgres://accelerate.prisma-data.net/?api_key=..."); +const sql = ppg(YOUR_DATABASE_URL); const posts: Post[] = await sql`SELECT * FROM "Post"` @@ -138,7 +132,7 @@ The `query` function it exposes: import { Client } from "@prisma/ppg"; const client = new Client({ - connectionString: "prisma+postgres://accelerate.prisma-data.net/?api_key=...", + connectionString: YOUR_DATABASE_URL, }); const posts = await client.query('SELECT * FROM "Post" WHERE "authorId" = $1', [1]); diff --git a/content/250-postgres/300-database/800-api-reference/100-caching-api.mdx b/content/250-postgres/300-database/800-api-reference/100-caching-api.mdx deleted file mode 100644 index eb1c6ebde4..0000000000 --- a/content/250-postgres/300-database/800-api-reference/100-caching-api.mdx +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: "Cache API" -metaTitle: "Prisma Postgres: Cache API Reference" -metaDescription: "Cache API reference documentation for Prisma Postgres." ---- - -## Overview - -The Prisma Postgres API reference documentation is based on the following schema: - -```prisma -model User { - id Int @id @default(autoincrement()) - name String? - email String @unique -} -``` - -All example are based on the `User` model. - -## `cacheStrategy` - -With [the Prisma client extension for Prisma Postgres](https://www.npmjs.com/package/@prisma/extension-accelerate), you can use the `cacheStrategy` parameter for model queries and use the [`ttl`](/postgres/database/caching#time-to-live-ttl) and [`swr`](/postgres/database/caching#stale-while-revalidate-swr) parameters to define a cache strategy for your Prisma Postgres queries. The client extension requires that you install Prisma Client version `4.10.0`. - -### Options - -The `cacheStrategy` parameter takes an option with the following keys: - -| Option | Example | Type | Required | Description | -| ------ | ---------- | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `swr` | `60` | `Int` | No | The stale-while-revalidate time in seconds. | -| `ttl` | `60` | `Int` | No | The time-to-live time in seconds. | -| `tags` | `["user"]` | `String[]` | No | The `tag` array can control the [invalidation](/accelerate/api-reference#accelerateinvalidate) of cached query results. Each tag can only contain alphanumeric characters and underscores with a maximum length of 64 characters. | - -| - -### Examples - -Add a caching strategy to the query, defining a 60-second stale-while-revalidate (SWR) value, a 60-second time-to-live (TTL) value, and a cache tag of `"emails_with_alice"`: - -```ts -await prisma.user.findMany({ - where: { - email: { - contains: "alice@prisma.io", - }, - }, - // highlight-start - cacheStrategy: { - swr: 60, - ttl: 60, - tags: ["emails_with_alice"], - }, - // highlight-end -}); -``` - -### Supported Prisma Client operations - -The following is a list of all read query operations that support `cacheStrategy`: - -- [`findUnique()`](/orm/reference/prisma-client-reference#findunique) -- [`findUniqueOrThrow()`](/orm/reference/prisma-client-reference#finduniqueorthrow) -- [`findFirst()`](/orm/reference/prisma-client-reference#findfirst) -- [`findFirstOrThrow()`](/orm/reference/prisma-client-reference#findfirstorthrow) -- [`findMany()`](/orm/reference/prisma-client-reference#findmany) -- [`count()`](/orm/reference/prisma-client-reference#count) -- [`aggregate()`](/orm/reference/prisma-client-reference#aggregate) -- [`groupBy()`](/orm/reference/prisma-client-reference#groupby) - - - -The `cacheStrategy` parameter is not supported on any write operations, such as `create()`. - - - -## `withAccelerateInfo` - -Any query that supports the `cacheStrategy` can append `withAccelerateInfo()` to wrap the response data and include additional information about the cached response. - -To retrieve the status of the response, use: - -```ts -const { data, info } = await prisma.user - .count({ - cacheStrategy: { ttl: 60, swr: 600 }, - where: { myField: "value" }, - }) - .withAccelerateInfo(); - -console.dir(info); -``` - -:::info -Notice the `info` property of the response object. This is where the request information is stored. -::: - -### Return type - -The `info` object is of type `AccelerateInfo` and follows the interface below: - -```ts -interface AccelerateInfo { - cacheStatus: "ttl" | "swr" | "miss" | "none"; - lastModified: Date; - region: string; - requestId: string; - signature: string; -} -``` - -| Property | Type | Description | -| -------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `cacheStatus` | `"ttl" \| "swr" \| "miss" \| "none" ` | The cache status of the response.
  • `ttl` indicates a cache hit within the `ttl` duration and no database query was executed
  • `swr` indicates a cache hit within the `swr` duration and the data is being refreshed by Prisma Postgres in the background
  • `miss` indicates that both `ttl` and `swr` have expired and the database query was executed by the request
  • `none` indicates that no cache strategy was specified and the database query was executed by the request
| -| `lastModified` | `Date` | The date the response was last refreshed. | -| `region` | `String` | The data center region that received the request. | -| `requestId` | `String` | Unique identifier of the request. Useful for troubleshooting. | -| `signature` | `String` | The unique signature of the Prisma operation. | - -## `$accelerate.invalidate` - -You can invalidate the cache using the [`$accelerate.invalidate` API](/accelerate/). - -:::note - -To invalidate cached query results on-demand, a paid plan is required. Each plan has specific limits on the number of cache tag-based invalidations allowed per day, though there are no limits on calling the `$accelerate.invalidate` API itself. See our [pricing for more details](https://www.prisma.io/pricing#accelerate). - -::: - -### Example - -To invalidate the query below: - -```ts -await prisma.user.findMany({ - where: { - email: { - contains: "alice@prisma.io", - }, - }, - cacheStrategy: { - swr: 60, - ttl: 60, - // highlight-start - tags: ["emails_with_alice"], - // highlight-end - }, -}); -``` - -You need to provide the cache tag in the `$accelerate.invalidate` API: - -```ts -try { - // highlight-start - await prisma.$accelerate.invalidate({ - tags: ["emails_with_alice"], - }); - // highlight-end -} catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - // The .code property can be accessed in a type-safe manner - if (e.code === "P6003") { - console.log("The cache invalidation rate limit has been reached. Please try again later."); - } - } - throw e; -} -``` - -:::note -You can invalidate up to 5 tags per call. -::: - -## `$accelerate.invalidateAll` - -You can invalidate the entire cache using the `$accelerate.invalidateAll` API. - -### Example - -To invalidate the query below: - -```ts -await prisma.user.findMany({ - where: { - email: { - contains: "alice@prisma.io", - }, - }, - cacheStrategy: { - swr: 60, - ttl: 60, - // highlight-start - tags: ["emails_with_alice"], - // highlight-end - }, -}); -``` - -Just call the `$accelerate.invalidateAll` API: - -```ts -try { - // highlight-start - await prisma.$accelerate.invalidateAll(); - // highlight-end -} catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - if (e.code === "P6003") { - console.log("The cache invalidation rate limit has been reached. Please try again later."); - } - } - throw e; -} -``` - -### Why use `$accelerate.invalidateAll`? - -This method offers better editor support (e.g. IntelliSense) than alternatives like `invalidate("all")`. - -:::warning - -This clears cache for the entire environment—use with care. - -::: - -## Errors - -Prisma Postgres-related errors start with `P6xxx`. - -You can find the full error code reference for Prisma Postgres [here](/postgres/database/api-reference/error-reference). diff --git a/content/250-postgres/300-database/800-api-reference/200-error-reference.mdx b/content/250-postgres/300-database/800-api-reference/200-error-reference.mdx index 0b5e253e56..bf55117094 100644 --- a/content/250-postgres/300-database/800-api-reference/200-error-reference.mdx +++ b/content/250-postgres/300-database/800-api-reference/200-error-reference.mdx @@ -88,13 +88,13 @@ This error indicates that Prisma ORM cannot establish a connection to your Prism If the database's server address (hostname) and port are incorrect or unreachable then you may encounter this error. -**Suggested solution:** Verify the hostname/port of the database connection string that was provided while creating the Prisma Accelerate project. Additionally, attempt to connect to the database using a Database GUI tool (e.g., [Prisma Studio](https://www.prisma.io/studio), [TablePlus](https://tableplus.com/), or [DataGrip](https://www.jetbrains.com/datagrip/)) for further investigation. +**Suggested solution:** Verify the hostname/port of the database connection string that was provided while creating the project. Additionally, attempt to connect to the database using a Database GUI tool (e.g., [Prisma Studio](https://www.prisma.io/studio), [TablePlus](https://tableplus.com/), or [DataGrip](https://www.jetbrains.com/datagrip/)) for further investigation. #### Incorrect username/password/database name This error can happen when the wrong credentials are provided, preventing it from establishing a connection to your database. -**Suggested solution:** Verify the correctness of your database's username, password, and name in the connection string provided to Prisma Accelerate. Ensure that these credentials match those required by your database. Testing the connection using a direct database GUI tool can also help in confirming if the provided credentials are correct. +**Suggested solution:** Verify the correctness of your database's username, password, and name in the connection string provided to Prisma Postgres. Ensure that these credentials match those required by your database. Testing the connection using a direct database GUI tool can also help in confirming if the provided credentials are correct. ## [`P5011`](/orm/reference/error-reference#p5011-too-many-requests) (`TooManyRequests`) @@ -109,14 +109,12 @@ If your application retries queries immediately or with minimal delay, especiall **Suggested solution:** - Implement an exponential backoff strategy. Rather than retrying immediately or with a fixed delay, gradually increase the delay period after each failed attempt. -- This allows the system time to recover and reduces the likelihood of overwhelming Prisma Accelerate and your database. #### Sudden traffic spikes Unpredicted traffic surges (for example, during product launches, flash sales, or viral growth events) can cause the threshold to be met and result into `P5011`. **Suggested solution:** -- Consider proactive scaling strategies for both Prisma Accelerate and your database. - Monitor traffic and resource usage. If you anticipate a surge, please contact [support](/platform/support) for capacity planning and potential configuration adjustments. #### Prolonged or planned high workloads diff --git a/content/250-postgres/350-integrations/100-netlify.mdx b/content/250-postgres/350-integrations/100-netlify.mdx index 06a1353719..ee006a00f6 100644 --- a/content/250-postgres/350-integrations/100-netlify.mdx +++ b/content/250-postgres/350-integrations/100-netlify.mdx @@ -47,18 +47,17 @@ Perform the following steps _for every Netlify site_ in which you want to use Pr ### Ensure your project uses the `DATABASE_URL` environment variable -Ensure that the data source in your `schema.prisma` file is configured to use the `DATABASE_URL` environment variable: - -```prisma -// schema.prisma -generator client { - provider = "prisma-client-js" -} - -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} +Ensure that the data source in your `prisma.config.ts` file is configured to use the `DATABASE_URL` environment variable: + +```typescript +// prisma.config.ts +import { defineConfig, env } from '@prisma/config'; +export default defineConfig({ + datasource: { + url: env('DATABASE_URL'), + }, + schema: './prisma/schema.prisma', +}); ``` ### Generate Prisma Client in a `postinstall` script in `package.json` @@ -100,12 +99,13 @@ Once you're done with this, you'll be able to access the deployed version of thi Next, set up a Prisma Postgres instance: -1. Log in to [Prisma Data Platform](https://console.prisma.io/) and open the Console. +1. Log in to [Prisma Platform](https://console.prisma.io/) and open the Console. 1. In a [workspace](/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. +1. Click the **Connect to your Database** button 1. Save the `DATABASE_URL` environment variable, you'll need it in the next section. ### 3. Locally add Prisma Postgres to the project @@ -130,12 +130,12 @@ In this section, you are going to add Prisma Postgres to the starter project _on 1. Open the newly created `schema.prisma` file and add the following model to it: ```prisma file=schema.prisma generator client { - provider = "prisma-client-js" + provider = "prisma-client" + output = "../src/generated/prisma" } datasource db { provider = "postgresql" - url = env("DATABASE_URL") } // add-start @@ -161,9 +161,15 @@ In this section, you are going to add Prisma Postgres to the starter project _on Open the `app/page.jsx` file and replace the entire contents with this code: ```js file=app/page.jsx -import { PrismaClient } from '@prisma/client' +import 'dotenv/config'; +import { PrismaClient } from '../generated/prisma/client.js'; +import {PrismaPg} from '@prisma/adapter-pg' -const prisma = new PrismaClient(); +const databaseUrl = process.env.DATABASE_URL; +const adapter = new PrismaPg({ + connectionString: process.env.DATABASE_URL!, +}); +const prisma = new PrismaClient({ adapter }) export default async function Page() { const users = await prisma.user.findMany(); @@ -216,8 +222,7 @@ As mentioned [above](#generate-prisma-client-in-a-postinstall-script-in-packagej }, "dependencies": { "@netlify/blobs": "^8.1.0", - "@prisma/client": "^6.3.0", - "@prisma/extension-accelerate": "^1.2.1", + "@prisma/client": "^7.0.0", "blobshape": "^1.0.0", "bright": "^0.8.5", "markdown-to-jsx": "^7.4.5", @@ -232,7 +237,7 @@ As mentioned [above](#generate-prisma-client-in-a-postinstall-script-in-packagej "eslint": "8.57.1", "eslint-config-next": "15.1.6", "postcss": "^8.4.36", - "prisma": "^6.3.0", + "prisma": "^7.0.0", "tailwindcss": "^3.4.1" } } diff --git a/content/250-postgres/350-integrations/200-vercel.mdx b/content/250-postgres/350-integrations/200-vercel.mdx index 106e5264c2..e10ca24d57 100644 --- a/content/250-postgres/350-integrations/200-vercel.mdx +++ b/content/250-postgres/350-integrations/200-vercel.mdx @@ -6,11 +6,9 @@ tocDepth: 3 toc: true --- -The [Vercel Marketplace integration for Prisma Postgres](https://www.vercel.com/marketplace/prisma) connects your Vercel projects with Prisma Postgres instances. Once connected, the integration will automatically set the following environment variables on your deployed Vercel app: +The [Vercel Marketplace integration for Prisma Postgres](https://www.vercel.com/marketplace/prisma) connects your Vercel projects with Prisma Postgres instances. Once connected, the integration will automatically set the following environment variable on your deployed Vercel app: -`POSTGRES_URL`: The [direct TCP connection URL](/postgres/database/direct-connections) starting with `postgres://...` -`PRISMA_DATABASE_URL`: The connection URL used by Prisma ORM starting with `prisma+postgres://accelerate.prisma-data.net/?api_key=ey...` -`DATABASE_URL`: The [direct TCP connection URL](/postgres/database/direct-connections) starting with `postgres://...` +- `DATABASE_URL`: The [direct TCP connection URL](/postgres/database/direct-connections) starting with `postgres://...` These enable you to connect to the Prisma Postgres instances via any ORM or database library you want to use (Prisma ORM, Drizzle, Kysely, ...). @@ -68,18 +66,16 @@ npx prisma studio ### Ensure your project uses the correct environment variable -Ensure that the data source in your `schema.prisma` file is configured to use the `DATABASE_URL` or `PRISMA_DATABASE_URL` environment variable (depending on which one is being exported in the **Settings** of your Vercel project): +Ensure that the data source in your `prisma.config.ts` file is configured to use the `DATABASE_URL` environment variable: -```prisma -// schema.prisma -generator client { - provider = "prisma-client-js" -} - -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} +```ts +import { defineConfig, env } from '@prisma/config'; +export default defineConfig({ + datasource: { + url: env('DATABASE_URL'), + }, + schema: './prisma/schema.prisma', +}); ``` ### Generate Prisma Client in a `postinstall` script in `package.json` diff --git a/content/250-postgres/400-query-optimization/100-setup.mdx b/content/250-postgres/400-query-optimization/100-setup.mdx index a7a19dd194..ed9ce8d71f 100644 --- a/content/250-postgres/400-query-optimization/100-setup.mdx +++ b/content/250-postgres/400-query-optimization/100-setup.mdx @@ -39,20 +39,6 @@ Run the following command in your terminal to install the necessary dependencies npm install @prisma/extension-optimize ``` -
-Enabling tracing in older versions of Prisma ORM - -For versions of Prisma ORM between `4.2.0` and `6.1.0`, you need to enable the `tracing` preview feature in your Prisma schema file. - -```prisma -generator client { - provider = "prisma-client-js" - previewFeatures = ["tracing"] -} -``` - -
- ### 2.2. Add the Optimize API Key to your `.env` file Copy the Prisma Optimize API key and add it to your `.env` file: @@ -66,8 +52,7 @@ OPTIMIZE_API_KEY="YOUR_OPTIMIZE_API_KEY" Extend your existing Prisma Client instance with the Optimize extension: ```ts -import { PrismaClient } from "@prisma/client"; -import { withAccelerate } from "@prisma/extension-optimize"; +import { PrismaClient } from '../generated/prisma/client.js'; import { withOptimize } from "@prisma/extension-optimize"; const prisma = new PrismaClient().$extends( @@ -75,16 +60,6 @@ const prisma = new PrismaClient().$extends( ).$extends(withAccelerate()); ``` -#### Using the Optimize extension with other extensions - -Since [extensions are applied one after another](/orm/prisma-client/client-extensions#conflicts-in-combined-extensions), make sure you apply them in the correct order. Extensions cannot share behavior and the last extension applied takes precedence. - -```ts -const prisma = new PrismaClient() - .$extends(withOptimize()) - .$extends(withAccelerate()) -``` - ### 2.5. Use Prisma Optimize to generate insights Follow these steps to start generating query insights with Prisma Optimize: diff --git a/content/250-postgres/400-query-optimization/300-recommendations/400-repeated-query.mdx b/content/250-postgres/400-query-optimization/300-recommendations/400-repeated-query.mdx index 2da4c4d17e..ec2f37b1f0 100644 --- a/content/250-postgres/400-query-optimization/300-recommendations/400-repeated-query.mdx +++ b/content/250-postgres/400-query-optimization/300-recommendations/400-repeated-query.mdx @@ -25,10 +25,4 @@ When the same query is executed multiple times with the same parameters within a - **Time waste:** A new connection may be established between the application and database, the query and its parameters are sent to the database, the database processes the query, and the results are sent back to the application. - **Increased resource usage:** Query execution increases CPU and memory usage, as well as disk I/O, putting strain on your database's system resources. -- **Higher costs:** In serverless database pricing models, higher resource usage can result in increased costs. - -:::info - -To learn more about avoiding repeated queries with caching in Prisma Postgres, refer to the [caching documentation](/postgres/database/caching). - -::: \ No newline at end of file +- **Higher costs:** In serverless database pricing models, higher resource usage can result in increased costs. \ No newline at end of file diff --git a/static/img/postgres/connection-string.png b/static/img/postgres/connection-string.png new file mode 100644 index 0000000000000000000000000000000000000000..4401837d4ab63f142f758e2f59021cab859bd94d GIT binary patch literal 263537 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
LQ5Ul-f6MpScs?SCCY?pu*ctAgC* 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 From 30bc6679043794b9b25d70065143309b9d8bd431 Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Tue, 11 Nov 2025 12:01:04 -0500 Subject: [PATCH 19/23] docs(): update with feedback --- content/250-postgres/300-database/650-direct-connections.mdx | 2 +- content/250-postgres/400-query-optimization/100-setup.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/250-postgres/300-database/650-direct-connections.mdx b/content/250-postgres/300-database/650-direct-connections.mdx index 43b78648f0..bc258e2ac7 100644 --- a/content/250-postgres/300-database/650-direct-connections.mdx +++ b/content/250-postgres/300-database/650-direct-connections.mdx @@ -47,7 +47,7 @@ SSL mode is required when connecting to Prisma Postgres via direct TCP, so you n ## Billing -When using direct TCP to connect to a Prisma Postgres instance, every request is counted asd a [billable operation](/postgres/introduction/overview#usage-based-pricing). Learn more on our [pricing page](https://www.prisma.io/pricing). +When using direct TCP to connect to a Prisma Postgres instance, every request is counted as a [billable operation](/postgres/introduction/overview#usage-based-pricing). Learn more on our [pricing page](https://www.prisma.io/pricing). ## Temporary limitations diff --git a/content/250-postgres/400-query-optimization/100-setup.mdx b/content/250-postgres/400-query-optimization/100-setup.mdx index ed9ce8d71f..ccc145376d 100644 --- a/content/250-postgres/400-query-optimization/100-setup.mdx +++ b/content/250-postgres/400-query-optimization/100-setup.mdx @@ -57,7 +57,7 @@ import { withOptimize } from "@prisma/extension-optimize"; const prisma = new PrismaClient().$extends( withOptimize({ apiKey: process.env.OPTIMIZE_API_KEY }), -).$extends(withAccelerate()); +); ``` ### 2.5. Use Prisma Optimize to generate insights From d6dc9757bb5bc7e2d79ae8da541b2921af59ef41 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 17:02:11 +0000 Subject: [PATCH 20/23] Optimised images with calibre/image-actions --- static/img/postgres/connection-string.png | Bin 61466 -> 56535 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/static/img/postgres/connection-string.png b/static/img/postgres/connection-string.png index 1f267c76818c23518f298811d47a56a3a4e8237e..19e872cb5c823e10a71dd930cccfd6da567549af 100644 GIT binary patch literal 56535 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 literal 61466 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∾lLkia)R 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 A^Z)<= From 3d11b9f99799cea1be4c27dd0f0d8f83f6ab2eeb Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Sun, 16 Nov 2025 19:37:19 -0500 Subject: [PATCH 21/23] docs(ppg): updates --- .../100-introduction/220-npx-create-db.mdx | 31 +++++++------------ content/250-postgres/1200-more/1000-faq.mdx | 3 -- .../1200-more/900-troubleshooting.mdx | 22 ------------- .../300-database/400-connection-pooling.mdx | 15 +-------- .../300-database/550-local-development.mdx | 18 +---------- .../300-database/750-serverless-driver.mdx | 12 +++++-- .../250-postgres/50-getting-started/index.mdx | 13 +------- 7 files changed, 23 insertions(+), 91 deletions(-) diff --git a/content/250-postgres/100-introduction/220-npx-create-db.mdx b/content/250-postgres/100-introduction/220-npx-create-db.mdx index c0fa7a3289..172e950fa7 100644 --- a/content/250-postgres/100-introduction/220-npx-create-db.mdx +++ b/content/250-postgres/100-introduction/220-npx-create-db.mdx @@ -96,37 +96,28 @@ Here is an example output: ┌ 🚀 Creating a Prisma Postgres database │ │ Provisioning a temporary database in us-east-1... -│ │ It will be automatically deleted in 24 hours, but you can claim it. -│ ◇ Database created successfully! │ -● Connect to your database → -│ -│ Use this connection string optimized for Prisma ORM: -│ prisma+postgres://accelerate.prisma-data.net/?api_key=... -│ -│ Use this connection string for everything else: +● Database Connection +│ Connection String: │ postgresql://:@db.prisma.io:5432/postgres │ ◆ Claim your database → -│ -│ Want to keep your database? Claim for free: +│ Keep your database for free: │ https://create-db.prisma.io?projectID=proj_... └ ``` -Once you have the output, take the **Prisma ORM-optimized connection string** (`prisma+postgres://...`) and add it to your `.env` file as `DATABASE_URL`: +Once you have the output, take the connection string and add it to your `.env` file as `DATABASE_URL`: ```env -DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=..." +DATABASE_URL="postgresql://:@db.prisma.io:5432/postgres" ``` You can now follow the [Prisma Postgres quickstart guide](/getting-started/prisma-orm/quickstart/prisma-postgres) to connect your Prisma project to this database. -If you're using other tools or libraries, use the **standard PostgreSQL connection string** (`postgresql://...`) with any PostgreSQL-compatible client, such as `psql`, `pgAdmin`, `node-postgres`, or an ORM of your choice. Detailed instructions are available in the guide for [connecting via direct PostgreSQL connection string](/postgres/database/direct-connections). - ## Claiming your database @@ -163,12 +154,12 @@ When you claim a database: Here are the CLI flags for the `npx create-db` command: -| Flag | Shorthand | Description | -|---------------|-----------|----------------------------------------------------------------------------------------------| -| `--region` | `-r` | Specify a region.
**Available regions:** `ap-southeast-1`, `ap-northeast-1`, `eu-central-1`, `eu-west-3`, `us-east-1`, `us-west-1` | -| `--interactive` | `-i` | Run in interactive mode (select region from a list). | -| `--json` | `-j` | Output machine-readable JSON and exit. | -| `--help` | `-h` | Show this help message. | +| Flag | Shorthand | Description | +|-----------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------| +| `--region` | `-r` | Specify a region.
**Available regions:** `ap-southeast-1`, `ap-northeast-1`, `eu-central-1`, `eu-west-3`, `us-east-1`, `us-west-1` | +| `--interactive` | `-i` | Run in interactive mode (select region from a list). | +| `--json` | `-j` | Output machine-readable JSON and exit. | +| `--help` | `-h` | Show this help message. | To view all CLI options use the `--help` or `-h` flag: diff --git a/content/250-postgres/1200-more/1000-faq.mdx b/content/250-postgres/1200-more/1000-faq.mdx index bca6c2d8c4..262b477d00 100644 --- a/content/250-postgres/1200-more/1000-faq.mdx +++ b/content/250-postgres/1200-more/1000-faq.mdx @@ -29,11 +29,8 @@ If you previously signed up using GitHub and want to switch to email and passwor 3. Test Your Login - Log out and try logging in with your email and the password you just created. -:::note - If you encounter any issues, please contact our support team for help linking your accounts. -::: ### VS Code does not recognize the `$extends` method diff --git a/content/250-postgres/1200-more/900-troubleshooting.mdx b/content/250-postgres/1200-more/900-troubleshooting.mdx index 13fb26186d..ff7113630d 100644 --- a/content/250-postgres/1200-more/900-troubleshooting.mdx +++ b/content/250-postgres/1200-more/900-troubleshooting.mdx @@ -33,28 +33,6 @@ npx prisma@latest init --db This ensures that you're using the most up-to-date CLI, preventing issues with outdated command syntax. -## Warning: In production, we recommend using `prisma generate --no-engine` - -### Problem - -You're seeing the following error in your logs: - -``` -prisma:warn: In production, we recommend using 'prisma generate --no-engine' -``` - -### Cause - -Prisma ORM by default uses a [query engine](/orm/overview/) binary that's deployed as part of the `@prisma/client` package. However, with Prisma Postgres, this is not needed. - -### Solution - -To remove this warning and generate Prisma Client without the query engine, you can run the following command: - -``` -npx prisma generate --no-engine -``` - ## Workspace plan limit reached when running `prisma init --db` ### Problem diff --git a/content/250-postgres/300-database/400-connection-pooling.mdx b/content/250-postgres/300-database/400-connection-pooling.mdx index 38564bf582..874a5dec90 100644 --- a/content/250-postgres/300-database/400-connection-pooling.mdx +++ b/content/250-postgres/300-database/400-connection-pooling.mdx @@ -18,26 +18,13 @@ For Prisma Postgres, the connection limit depends on the plan you have signed up |---------------------------|------|---------|-----|----------| | Connection Limit (Pooled) | 10 | 100 | 500 | 1000 | -:::note -For the **Starter plan**, this is often sufficient for most workloads, but if you're expecting high traffic or intensive compute operations, you may want to [increase this limit](#configuring-the-connection-pool-size). -::: - You can compare plans on the [Prisma pricing page](https://www.prisma.io/pricing). -### Configuring the connection pool size - -For Prisma Postgres, the connection limit is managed automatically for you. - -If you're **not using Prisma Postgres**, you can configure the connection pool size for Prisma ORM by specifying it [in the connection string](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#setting-the-connection-pool-size). - -If you're using Prisma Accelerate with your own database, you can configure the connection pool size through the `Connection limit` setting in your project on the [Accelerate setup page](/accelerate/getting-started). - -### Configuring the connection pool timeout +### Connection pool timeout The connection pool timeout is the maximum number of seconds that a query will block while waiting for a connection from Prisma Postgres's internal connection pool. This occurs if the number of concurrent requests exceeds the connection limit, resulting in queueing of additional requests until a free connection becomes available. An exception is thrown if a free connection does not become available within the pool timeout. The connection pool timeout can be disabled by setting the value to 0. -Similar to the connection pool size, you may also configure the connection pool timeout via the _database connection string_. To adjust this value, you may add the `pool_timeout` parameter to the database connection string. For example: diff --git a/content/250-postgres/300-database/550-local-development.mdx b/content/250-postgres/300-database/550-local-development.mdx index 7c4b227212..c3a1f5d5ed 100644 --- a/content/250-postgres/300-database/550-local-development.mdx +++ b/content/250-postgres/300-database/550-local-development.mdx @@ -10,19 +10,13 @@ sidebar_class_name: preview-badge [Prisma Postgres](/postgres) is a production-grade, cloud-native database and is ideal for staging and production environments. For rapid iteration and isolated testing, you can run a _local_ Prisma Postgres instance (powered by [PGlite](https://pglite.dev)) via the `prisma dev` command. This page explains how to install and launch a local Prisma Postgres database. -:::note - Local Prisma Postgres is in [Preview](/orm/more/releases#preview) and is being actively developed. -::: - ## Setting up local development for Prisma Postgres Follow these steps to set up local Prisma Postgres for development. -:::note -Please ensure you're running Node.js 20 or later, as it's required for local Prisma Postgres. -::: +Node.js v20 or later is required for local Prisma Postgres ### 1. Launching local Prisma Postgres @@ -56,16 +50,6 @@ If you want to connect via Prisma ORM, hit h on your keyboard, copy t DATABASE_URL="prisma+postgres://localhost:51213/?api_key=__API_KEY__" ``` -The `DATABASE_URL` is a connection string that Prisma uses to connect to the local Prisma Postgres server and is compatible with the [Prisma Postgres extension](https://www.npmjs.com/package/@prisma/extension-accelerate): - -```ts -import { withAccelerate } from '@prisma/extension-accelerate' - -const prisma = new PrismaClient().$extends(withAccelerate()) -``` - -This ensures no additional code changes are needed when switching from local Prisma Postgres to Prisma Postgres in production. - Keep the local Prisma Postgres server running in the background while you work on your application. ### 2. Applying migrations and seeding data diff --git a/content/250-postgres/300-database/750-serverless-driver.mdx b/content/250-postgres/300-database/750-serverless-driver.mdx index 34f03e1223..0fcba998fa 100644 --- a/content/250-postgres/300-database/750-serverless-driver.mdx +++ b/content/250-postgres/300-database/750-serverless-driver.mdx @@ -9,6 +9,12 @@ sidebar_class_name: early-access-badge The serverless driver for Prisma Postgres is a lightweight and minimal client library that can talk to Prisma Postgres using raw SQL. You can use it via the [`@prisma/ppg`](https://github.com/prisma/ppg-client/tree/main) npm package. +:::warning + +The Prisma Postgres serverless driver is currently in [Early Access](/orm/more/releases#early-access) and not yet recommended for production scenarios. + +::: + ## Installation Install the serverless driver via npm: @@ -32,7 +38,7 @@ type Post = { authorId: number | null; } -const sql = ppg(YOUR_DATABASE_URL); +const sql = ppg("prisma+postgres://accelerate.prisma-data.net/?api_key=..."); const authorId = 1; const posts = await sql`SELECT * FROM "Post" WHERE "authorId" = ${authorId}`; @@ -97,7 +103,7 @@ type User = { email: string } -const sql = ppg(YOUR_DATABASE_URL); +const sql = ppg("prisma+postgres://accelerate.prisma-data.net/?api_key=..."); const posts: Post[] = await sql`SELECT * FROM "Post"` @@ -132,7 +138,7 @@ The `query` function it exposes: import { Client } from "@prisma/ppg"; const client = new Client({ - connectionString: YOUR_DATABASE_URL, + connectionString: "prisma+postgres://accelerate.prisma-data.net/?api_key=...", }); const posts = await client.query('SELECT * FROM "Post" WHERE "authorId" = $1', [1]); diff --git a/content/250-postgres/50-getting-started/index.mdx b/content/250-postgres/50-getting-started/index.mdx index 9a63cf6c87..797fb2f2b3 100644 --- a/content/250-postgres/50-getting-started/index.mdx +++ b/content/250-postgres/50-getting-started/index.mdx @@ -16,7 +16,6 @@ npx prisma init --db After running this command, the terminal will guide you with next steps. Follow [this page](/getting-started/prisma-postgres/from-the-cli) to complete the setup for your first Prisma Postgres project. -:::note If you need a database quickly for testing, or want to try out Prisma Postgres, you can run the following command to spin up a temporary 24-hour database: ```terminal @@ -24,7 +23,6 @@ npx create-db@latest ``` You can learn more about `npx create-db` in [the dedicated documentation](/postgres/introduction/npx-create-db). -::: ## Prisma ORM @@ -40,16 +38,7 @@ If you are looking to explore Prisma Postgres in a fullstack project, check out ## Connect via any database library / tool -You can access Prisma Postgres with any ORM or database tool of your choice via [direct TCP connections](/postgres/database/direct-connections). - -In order to get a direct TCP connection string, you need to: -1. Navigate to your active Prisma Postgres instance. -1. Click the **API Keys** tab in the project's sidenav. -1. Click the **Create API key** button. -1. In the popup, provide a **Name** for the API key and click **Create**. -1. Copy the connection string starting with `postgres://`, this is your direct connection string. - -Once you have the connection string, you can follow the setup docs for PostgreSQL of any ORM or database tool: +You can access Prisma Postgres with any ORM or database tool of your choice. Once you have the connection string, you can follow the setup docs for PostgreSQL of any ORM or database tool: - [Drizzle ORM](https://orm.drizzle.team/docs/get-started/postgresql-new) - [Kysely](https://kysely.dev/docs/getting-started) From 83013e42c37975f5f15cf2140078e1af70aa2a5e Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Mon, 17 Nov 2025 17:17:47 -0500 Subject: [PATCH 22/23] docs(): update based on feedback --- content/250-postgres/350-integrations/100-netlify.mdx | 8 ++++---- content/250-postgres/350-integrations/200-vercel.mdx | 5 ++--- content/250-postgres/400-query-optimization/100-setup.mdx | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/content/250-postgres/350-integrations/100-netlify.mdx b/content/250-postgres/350-integrations/100-netlify.mdx index ee006a00f6..929a1cc2f3 100644 --- a/content/250-postgres/350-integrations/100-netlify.mdx +++ b/content/250-postgres/350-integrations/100-netlify.mdx @@ -51,6 +51,7 @@ Ensure that the data source in your `prisma.config.ts` file is configured to use ```typescript // prisma.config.ts +import 'dotenv/config'; import { defineConfig, env } from '@prisma/config'; export default defineConfig({ datasource: { @@ -70,13 +71,12 @@ To ensure the generated Prisma Client library is available on your deployed Netl "scripts": { // ... // add-next-line - "postinstall": "prisma generate --no-engine" + "postinstall": "prisma generate" } // } ``` -The `--no-engine` flag ensures that the query engine binary is kept out of the generated Prisma Client library. It's not needed when using Prisma Postgres. ## Example: Deploy a Next.js template with Prisma Postgres @@ -162,7 +162,7 @@ Open the `app/page.jsx` file and replace the entire contents with this code: ```js file=app/page.jsx import 'dotenv/config'; -import { PrismaClient } from '../generated/prisma/client.js'; +import { PrismaClient } from '../path/to/generated/prisma/client'; import {PrismaPg} from '@prisma/adapter-pg' const databaseUrl = process.env.DATABASE_URL; @@ -218,7 +218,7 @@ As mentioned [above](#generate-prisma-client-in-a-postinstall-script-in-packagej "start": "next start", "lint": "next lint", // add-next-line - "postinstall": "prisma generate --no-engine" + "postinstall": "prisma generate" }, "dependencies": { "@netlify/blobs": "^8.1.0", diff --git a/content/250-postgres/350-integrations/200-vercel.mdx b/content/250-postgres/350-integrations/200-vercel.mdx index e10ca24d57..ba1b4962ba 100644 --- a/content/250-postgres/350-integrations/200-vercel.mdx +++ b/content/250-postgres/350-integrations/200-vercel.mdx @@ -69,6 +69,7 @@ npx prisma studio Ensure that the data source in your `prisma.config.ts` file is configured to use the `DATABASE_URL` environment variable: ```ts +import 'dotenv/config'; import { defineConfig, env } from '@prisma/config'; export default defineConfig({ datasource: { @@ -88,10 +89,8 @@ To ensure the generated Prisma Client library is available on your deployed Verc "scripts": { // ... // add-next-line - "postinstall": "prisma generate --no-engine" + "postinstall": "prisma generate" } // } ``` - -The `--no-engine` flag ensures that the query engine binary is kept out of the generated Prisma Client library. It's not needed when using Prisma Postgres. diff --git a/content/250-postgres/400-query-optimization/100-setup.mdx b/content/250-postgres/400-query-optimization/100-setup.mdx index ccc145376d..6410fe7ebd 100644 --- a/content/250-postgres/400-query-optimization/100-setup.mdx +++ b/content/250-postgres/400-query-optimization/100-setup.mdx @@ -52,7 +52,7 @@ OPTIMIZE_API_KEY="YOUR_OPTIMIZE_API_KEY" Extend your existing Prisma Client instance with the Optimize extension: ```ts -import { PrismaClient } from '../generated/prisma/client.js'; +import { PrismaClient } from '../path/to/generated/prisma/client'; import { withOptimize } from "@prisma/extension-optimize"; const prisma = new PrismaClient().$extends( From 858a2315be20628334eda396b2fea8bc39097af6 Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Tue, 18 Nov 2025 15:10:37 -0500 Subject: [PATCH 23/23] docs(): update based on feedback --- .../350-integrations/100-netlify.mdx | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/content/250-postgres/350-integrations/100-netlify.mdx b/content/250-postgres/350-integrations/100-netlify.mdx index 929a1cc2f3..d6a4ec1267 100644 --- a/content/250-postgres/350-integrations/100-netlify.mdx +++ b/content/250-postgres/350-integrations/100-netlify.mdx @@ -120,6 +120,10 @@ In this section, you are going to add Prisma Postgres to the starter project _on ```terminal npm install prisma --save-dev ``` +1. Install the Prisma Accelerate Extension as a dependency: + ```terminal + npm install @prisma/extension-accelerate + ``` 1. Initialize Prisma ORM to create Prisma schema, config and `.env` file: ```terminal npx prisma init @@ -160,16 +164,14 @@ In this section, you are going to add Prisma Postgres to the starter project _on Open the `app/page.jsx` file and replace the entire contents with this code: -```js file=app/page.jsx +```tsx file=app/page.jsx import 'dotenv/config'; import { PrismaClient } from '../path/to/generated/prisma/client'; -import {PrismaPg} from '@prisma/adapter-pg' - +import { withAccelerate } from '@prisam/extension-accelerate'; const databaseUrl = process.env.DATABASE_URL; -const adapter = new PrismaPg({ - connectionString: process.env.DATABASE_URL!, -}); -const prisma = new PrismaClient({ adapter }) +const prisma = new PrismaClient({ + accelerateUrl: databaseUrl, +}).$extends(withAccelerate()); export default async function Page() { const users = await prisma.user.findMany(); @@ -179,11 +181,17 @@ export default async function Page() {

Users

    {users.length > 0 ? ( - users.map(user => ( + users.map((user) => (
  • -

    ID: {user.id}

    -

    Name: {user.name || 'N/A'}

    -

    Email: {user.email}

    +

    + ID: {user.id} +

    +

    + Name: {user.name || 'N/A'} +

    +

    + Email: {user.email} +

  • )) ) : ( @@ -223,6 +231,7 @@ As mentioned [above](#generate-prisma-client-in-a-postinstall-script-in-packagej "dependencies": { "@netlify/blobs": "^8.1.0", "@prisma/client": "^7.0.0", + "@prisma/extension-accelerate": "^1.2.1", "blobshape": "^1.0.0", "bright": "^0.8.5", "markdown-to-jsx": "^7.4.5", @@ -251,4 +260,4 @@ After having completed these steps, find the **Trigger deploy** button and selec ### 5. Validate the deployment -Open the deployed site by clicking the **Open production deploy** button. You should now see the same UI as you did at the end of step 3 when you were running the app locally. +Open the deployed site by clicking the **Open production deploy** button. You should now see the same UI as you did at the end of step 3 when you were running the app locally. \ No newline at end of file

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 literal 0 HcmV?d00001 From cae1f1c8910b767a5102e5e6d33739aacb3e0d04 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 16:43:14 +0000 Subject: [PATCH 18/23] Optimised images with calibre/image-actions --- static/img/postgres/connection-string.png | Bin 263537 -> 61466 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/static/img/postgres/connection-string.png b/static/img/postgres/connection-string.png index 4401837d4ab63f142f758e2f59021cab859bd94d..1f267c76818c23518f298811d47a56a3a4e8237e 100644 GIT binary patch literal 61466 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∾lLkia)R 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 A^Z)<= literal 263537 zcmeFZc{r5q`#)}ZP)h145?Oi_WzU+imq^y^yAUyq5r(Won@XrG*(tI!wy_(P;>nuK z*anmA!`Q|)#`3+Up5^`de%{aVJAQwEAID*4?(Mqo`@F8}Twdqvyq*{tXtS|$v(nMg zvFTjXG^V3t%BQ1aE<3;s_B_#Pgn%!4Ut{gdbfw*==fK8O7fT&ieSJC+@cRJWFZA4W zOte$LzbZY?U%$2J&(ksf*v~*m7wJy-%OB?$fN$F0bMQ~Q=I1x#%SUu9VCz@#e>aQa z&$F5Gvl##U&0GeK(P@}m(a{0lCeA)CE?&NFaKG5_W?Qi1p!YQ^UphL@bF_bY9pkgh zp#4F2Q%gTfeLaXX946s-3-071aTn%IYllwxE(H99x%fE>+=Y31`9kih{PyDv2>4Cg zE%}?kk5l|SRDQG6Hxjr4_i+)BmynW>`c0KpKtMp*=awtPSX1kd%fXh)Z*G2m-VjO2 zfPesr02v9m&uz(zii(PoQqq#r(&FF@ao<2MKgYY`UcQ1q8~L*xO&4EhA9rs*ces}T ztzAbaIKofmx8Gr@gHC8$}s_Tl@tE1Pygxp)WcI?|0GoP zo9BUKB0qHN9s8%}1D($H-}?KYYnJ zLOA2@2mMUdQI+L)jEkB3J9#!YBbZi^DCF+^Xqs=gVoIeD{C^oiE_L8n&{;nFVc(=w znf7*m*L!3*V!oiaUsNJ@tTvq&YwuPl6bv#5h@s?*a+&M^_W zF1Ki}5%ENDdAWtX!2+|I(91Bd{Gp}&ynabU@KRHa(%#ktwRQAP8}BIXC}#ZdU&F!) z7-VOW!#~_Gu1$vKohivtP8-h`3KPA#Wl`eQNz{=U)fxXGmsj#bQsN9~ri{SpQvs`= zg|*uVu$s}44*QLYS-9Qdo#6q@^oi%9x%vvD*rp9MO8m$){1>5z?=)GB468!p>DF@w zuUa1XDep%TzyX>q3TOCf)kVC=0%z*d{f95W9fH2Nn@kv{%6H9~x%|qIEuJ;J7bRA4 z%};)t#DThdb*)B%xscai&fQ3lu(we&3OdB@bSL3}9&5yt6ImH<)bsR2o${!%qd(2W zVLQ;9Uo7aEe!MT2=C|63m=1g_->nqLM7MN@n1M!pfk|Hfsq{NX-Ne+x>o4*i|Lx1Q za5{uwwe|61S*4#oUi-t|7@Yx!86Ic;a9mnr!&BDp_N9(ZVlOy}bjjmA4Z1kQns-(g zfw!w{B?CX}j(|JN zZwz}#=J~&Mo^#mWexLM)Gp*Mn@c|;t)_DHGe*Lj7twl{-*u? zXZqnmN5xzJP{a}O!1;_n-11Y3(eEZ=)fP=F75l5&7Akudy=upqYlfjkY^L^d)Rn}V z#!o66gU+FS;#FTRFTQ8t_iGP+z6K_8+wM3!(i^!m!B0ja_sE%}42Q(NC0aTiteJeN zTkrD9P9E-a>$$Sr;uUt4$y-Kxy5i{g)Y}<>T8GUArZ@2L0Cwf&@ZhyxZF2XP{d%Fr zR0m|KksQNSvk)ts86w@2eX0B2A&EhYE4u}G89vQhpCngTa1Yu;$XzqCJqZ@}iVllT zeER!g+jDuo4&wN=xxP`~9+jD~v-E z?I)CUOtoX~`wd>Q#_vDAm$>sfbOVm0+7P&a7V^NPuk9L1f6EA7ywjsh)+2CP6FS5y z^$5#@;k~QZc-j4m1E)kCPKjP8lo56p19~UsiX3*Kc`RX{;!|e6M@cSDXCn8;W+7g- zK%E7~U58W?EtkhOF$!uM>srL+4!eNS1peb|Wp`SiouZ^l5^pV+z(eOBPiPF#Lz|+> zm6^L@YVvN1=#tr_Ea#>@_e`9P3gWBfVzyl(J`whu4jpq93e}yzGQ*aB5_e+Ysc7k7 zfJEg^Y6$U?_e8Y9G`Y9Vg!-mi$6unK@}?-qrEV(GCXFw|gW|_mK~nF?3thb`8Fa&< zvZE&yB0Q&@PcErel5@{R`gX}#+$Nt9{5fG-Z3P5>C`|#WZYBd&%4BDzK=!^WIk`tx zq6xkzn36ZWKDrcE-hCEw0Sro2PM4Xx#_bbY>cJ2TY3 zx|Q4G>`Y!@yI)aBb-M&mA!Ahql9<4huZ{5zL;_;K?p1rWPi=LLDaNcNPe0W>xmk;g zL~1ravvbX1Z}nAnMntw-=%v!T=`Y4<90>bCUUyvGNBw8OrGeFr^ zIn#l|?s-!a)X2!8+iKJyF@LeGRt3zluF5&}uK7lCcSnc=eXq+Gf71PXL+4)EeocMI zUMAeOPTx6p*UX``_WRSFq-m=Bwdp(xRp?Cxuw$3{LW;gxE@Wrl@UoHE_cy^hwebd2 z-H_h@_FFK4I`*mw%$%5*qKQo~Hj^nVSDM_Jci&8GT*ym%Nny!OWQp4VBRUT5?aun1$3OSkBWOCd8#$*3V7yO{5d z9Cr^fDilyGnDRMfH{`xTyG%NYz9pbOC8pT<)!t)ag`Rlznh0n5C2YGdQ;S^8y_L12);-OZ)GTWsPhK7w;ZXaSBl)vRrllO zxx~p=F!8>O0n5rYub~fZUXWHV`PPi|J)?*!I}BM20nK;Y-yMIbY;<~$GYoY+3$r;E zEXr^BFmO0PMQQ|Szlxbm5YjjiqajB@ShjD(mNH-qIf$tO7t$??Pg6-X4n=h9as#$;&AY#L zG%QLn6_~hJF<`UpylgTm=+MyTG;fIiZhGkV=V7mL}n;6nGSV&@|W?xFUJ^G^;(N*kt z7Wa!ia(6v$inYUX-H!ehZ2-TGdck__!g97nP|@@;>SzsbD#afXM;1S1WS9;?_bRUk z)xc}y6b-2wa*nCkN1_sW_vnMrO$Lyimn@$-o+zIjq}_jcu-Zk5fE z*&x%n!zbeai- zicjwa_cma4N`&tD$BrA3)k}jxTpqF5m3J)p*=+|!ky`~ZcqeM%hCV4982r2qHUb~~ zj-Nu?Y2QnP2RFhx$@I_~Fikh2Wqzk4Oui&{<((D2F_S=CGoNqUxPcgf>ZCtwtv8?_2a(}& zwIFW$ZKKjAU=%S*1*R(`Y?u!bvkd1|B-~c_3vuXEA_(ua6k`axSMnPLwbL!4KC98) zfq222cQ=}1p5va3106UWvVV#aW|Zbyg6?ncvHLW>Q4@0oBK)@d;?mtVrPW>2^ozt= zzjd625~0`(C1~H#rn*T$B4_x8hBE)0ysAu)13qy~Kdnf%(6{?9daZT$9(iM@trE+j zusq1`s|xRv+3#HyZl+A9>Ut>U<(jw_aL4Vn|5lR>+-9=>#VFqQ1&N6%66GsTGet|P zjH`;dlL|F>r(au8L(BX%`8G!b95$+Jn#2_i(H9H3zZS$7(ic$*bvST2&(6tN{kC5g zvJo1qvhi5|CA*2zw+_kX5I=}MYML*EE(abYUX$Wh9{3M!h%;Vb0&1mpbfDxh&mIw{4QO&LEJcWfsI-2#@i#}u#xY18&jsnq}}gZ+cvuw zn-1-#S?{(li5!Tr+&MRuq^h^wy<=3IJ+~Q;!)bE79ZVh zI3vApbP*&yY9!N6g+?DpZxvg_d+pRuzQDudc|k$T+k}Dwd?MU+|E)g1XmcY!<#9<*?)A zSrL+S&%_1gPm6R64N`-m2?IAvL-eh>0zX2Uu#68a>2x0&;j_!vUpr>*ObW+MVcA)2 z^M*gJ%NfM=8BEfxO92yq>pKgKr5sV%Ey*D(u3Hd3{X{r}E8UZeX50nZK4LGvAIOT4 zxDCyiZk)*oJ~DC;>ZkQ00?OSoZL%YV?}<;i*Hdsab1H$=DAW7HLCTe@OqMX)(Cw6p z7sfHCa||3?+!v@kAmVr-sI>>>0UF;2cqT=V^SBmOGy$$Po)T-lz zWc3~_XLf5`-Jt;jX~u5kD7W|wZQ{&r#5?7;?E;6lwoS{nK=7)cD3Zr8HomoC*Jp>o zne_$^sspPypl5A(_76Y15=3w-jsE9(X!An7!oLW*6odHMMF0*YPgCHUevm11v+0;A zi)Z~oGyV6LB8QIP=0T3E82K=J z14HoX5byP&xtht4*F|y0ayLy#$s)^kvb}^tv-H9`%v=WIFSG93_{qW8Fr)K8NP7QVsC;UC=QY(a;CsCVtSE`r}eXlP&`2;q)QzK8vlJ=PAmLY@>3>z| ztWg*ah$}|Cg8DdvNIg0xlbBWte-swZu;@tl9#a(f+$m_GyzQkvOMFu`?{v1nb2y8f zNn6mk8txZETz`5#J<$=i|2klFX}HyMG%^#@wSJ59N667Pdqzu)twRu@%w-MW*ern zef3A<3$LaJ9k5q$X#JTxyeUg_vT`K?e_$C^oYzK+i*gq%g_**iD#UCD&%J%cmwz6r zrj!^vEE@x4)*jH!!J`5ZLy$9rcI(B|)1eaCmz#f&x6xl9h8 zLj5_7_C+P(m_*%O$l;f3MhewUMY)iJKaz?ODv!5PVmt3z-Cg zI82nox7>~_^B%1OHl-2HxtCzONehqRccJe9UgaLJH6FRS+xYQU-C7#h2(L|Ck2f)x zZsu5_bk*$ZOmKp zY3WG0`Xyn9)S+|`Uxl`Wk}q^OmyRlouuP`Gk(J<{;Yf~Q%5bk>*hZJ^B?sSLN|p}1 z7HLNa1sKoLF3ch1c2qZuc^W*ppBb?|r*zqmh6&0V?oQ*c$L#fgQs>V?s1AO8mB1dR z=wMO~zkBJXB_3({NCQJ<(e4fy9#VJ$4{H^#?35OKE zJ!SJpkEyEjsu-+sjIb}Gs7eIWs{}&~8+1lVX@MsrWk#Sa3!~?8c$suTiJy+dV?xc{ zxIrpHyo68x9y)u4|7i@75!=lomfif8dE1pc4e8NJF_2D&a|`XyC_V5~b<1Ek)Xy7N zRVVFSshT_w+vvTOyT9uw+uj7iw+4WNVc`7*WGlksectB~Nn+zSs_`{_PToa+QwTvU zip~SiqO~WA1;z=1{zOef>)9oTKH^R#$nCDG?+u z&&iI*?sZAc5YDo)tYbRryjJ0Inkcg)Dr-i-0Shie5 zHNfC5vKVVW+PgKj3E$t{P!NZpv~fG#p~RVaf)@Ef%G!t``_y zojK*|e#;V`Z z^UFN9zr(p5^nWRs_9^D2{`Mt|N>VV|`$RF@Eg`*n@FSc3?k-2xlh~Dd*YiIFqAu~g z-qEBj&^evc&aZd2Yl4QIM?8H=JZz-!syua2g28w~MZIJoyU42)zqjbo7h`D%g`Q2! zL%AzDHJ0ut{Zyg)yBtPOOB@`IS4ehX@0XdrGe32>BRgv1z2-rqqAUG_kdeC+(bRs& zAv#3P$qwxn5Us22jI&p+_uEJ+hKdld%jK*_v1ULo5JNYH@;npPc5|!KOk6R{euORg zZ#i)W?bs1B=&;74S4{bG&9wP9^x=@?h?_mJ$Z5bXperL}RYx?4Fau!fzVl1<9b50& z!^+?pf8+peHqxjNk{)HMAa+e^OCwO%*XcBK){r-6lnof;k! zg`_D&zm>3Jb2(7(E;Pjm%e$Y$18=r~?lcW1gG};<@cs936ko(TgE(%2yzLMAquP;zBb zu3qx@Fmfv41WUlirY7uu5KwVETc%1A!z{S4imx~e2U5QSau+k?wjYZw@en*h8)O<5 zFe7%K!_qYxs-ZICi)AfG=2Jhi42}Y19IK!#rw(JGX5Cr44b(}sM(8IFi`p&)!U%iF&6dTSUOm$q&B7_C$4pY0qf_W>Rxya9lC360_v;`a{NdmVBqf3qoyoHg8PaB9=_>FxAvGXrfe=YERFH>V79uCW=|a1t`97 zeG3#=%qBP1deO9@RMm~&*T|vtlottZ;aP9i~!K@mdr*js~+h$)aW?q1d0XdnSPMhjyWKTnl{k9=;`B5%llqy|@&*mc! z?tf9GFtWxR%vLUc7qYyGQ1b}Tn>4ciYJWKWXu4VyOS@(ZC~7rr9-^N)@89})rhXx z(telZ5n+*NCAdR^BclvZ%B?ox!vlW$iR-zkUWMpJ?h726IO#S9EY#zYYw@%yz+L!F zyJ^_*6L7M&jJnD*A9iT!2b0_PF8ZP+?evIAm*f{gE`zAId&=}2!kQ};;~ox?SCi9y z!*Z#d;x=fkD~?mJBBp4Xe*H)f{TKM<9*Kr(yMANt{Ug3T=@0j-VocCfVQ4sQww7?*kbc?k;>lZdT#*p3yH<1Mh+@v! zwtcF*C0`_8kXuzJvFe7LVv%wC6|D(z^^!1Vr+I@GQ{8H>)vofhJa{E`{VRMzV4Pywir9umeOGg2`=yDxjwpF)Plmpo0~RX zie5WCuiV9O1_S%#u8DN(W)^lF=-&Ge zXh4oupMu_dAtwH{>uWUJ-!6?jZnynO;)I1d@|11PZ9Jw|!; z_jZc=16cKt5Tt2(Kvv!EHb3tViCPCB_)>CGs-F+gQX#iX)hoh8_sAse&1fE;Z}^)_ zspf&77_in3?G{r;CKoez7jDZmsf<%!IBKejER2%v^Cu?9ZvL~pj3Qx0z_RZPu z@Di$;Xezw3v|+J+MJ+O<;K3f(W?M#&ZHQejH9^mVU9PLat?unW@cJ-p;o3nn`9z>uRl6Oq)Ut*io0Yk zZX|P1ZJkcQyr{`7ci4a2Z^I51+h%M9GbWs}^L#lb1ryd4E7$Z3gAQCuIAL1p!=bkR zbki-@RR3!|=_I=|b?JjMNJ|lA2JV*(H1Dm4wwUOXKDJ*x9P3e9my7DG=A{^@$947P z%li;Zj-`evGv}MgwVF+f*NjxGz0XRlTWEZ(>_ksAeOG0WiVw0(A>!4^MXW|OL)wuy z76HPZI1u2Mzfn39>(Og_c)%Mf#xu(7Xgzf&Cr`a33q5W33ug<)!Xl1|# zWu+7O-v?Y9dWF2BUO04Q>eQjJ`S*qG#yfcmXv{7NezJ0jYQtU+bmRtRF2TX9VLLSW z;!ieW#KjYUx%gR^`BQ^D*DHm?8tK65 zzv&YR=jzWvnTR%{yw5Sp6GF(dAshm%4sC{A0bF?G=kM4(9qOx+zQP`jVKo1v$bNk* zmN1B_eyY6q(nmvl={+}=)86WHD{XqM&f(S?(?CxM*6m@fTs)C|_~X#H!9?-(Q-_S^ z?;hiEpu()EYihf5hLu^ST(xt0YDc4~iDIJhj3y$@ z*1X7`>OUl>DW+aRp=By!z1WA@JE~dGS20`PqqOtvZl@!hq7n;+VzII`YC=VaM1vS4 zoq2CkSWO3W=5^$qKf}=fi5_LD7y6!Upuoum-+am%LgtR_ZAv6%DTzvLQ$Av`z8ecnh`f*o}sV zIJ^7u28Al&IMKNl@0I|re|zuS6>_4B)$=RwpB2UjMdPcF;~wBVX2ICDHZy134Fi#? zFiZ~K^dzghp{f(gEtm+f_Sgi+FOEH`R8Mz-&Jo-}`-{)bt1e(t4Q#-9EBWH zUF-LbCHyL~MrzDK&ySTx4sM!;TeAl`O?V_hMVCO^Lsw7Q#jAY-d4W{&612N$;eC5- z*jo1F>#258l$c7Jo6SHfQ@yJq$n33J6Cv7f+w;c@BC9@MUS|Ah2b=*7Cg|DwWM0~) zdN6%cYw>_xhgU1}u09$*FVvLSu(v%QAdSQ=>oPHvD9f0DQM2=oksZq_)Nj?s%9k(L zSeP^LWq#5^E@rq?!sEBr_7~8G`lMzCc)7)hc&3ILZn|JqtXp^^KqOqcAHSc~k;JWr zJ9xWxp&<9BaUgU{O8LZNTfo$Umb7_O*6i?OtvvA4>Hdw(`8aXvoK%^YV zryN=LbZ9)rvj)c*oAJCTuNLTNf1Bkh!XX^qliD|pA<-SvTi_R7U;G#uH3q)_S=q5-03cD-r+IjhmU zhDn@2KHurtGd9GMm_j;q`>-oN@4OEP3=v^{cgkxG+Ch#50y3AMj8gn;_2g>I5}Ugl z3fK8~ggLUzHT*iqoT9|v^nF^r&en&?Q-Bn{y!V}THLn_Py7y_^2Hu2lX_zr{84vga z3kIyAb<6WI?6l2@8^>w^lu^m+Klpl0Zuomw%5Djd4KAgmZ^hnfJQi5m$)a!aD3D~o zw7$IrtO=^3IJmj%89h|IarnEbu-nyU2y))chpCQ5A6n!8CH!eSc`=|_Y1kYww1Zp8 zyLZm4!$jE9L_YI7Jcui9IQK)vY{FKdEGHgmc8a)H8g5t!vk>0|j;q=5XJ|U*89H(} zTU`F_(bAUX2FPxF#8=J3MnxmTx5q%j#cWZ=+6$Ma`u(wB5Ies~1O`kavI)K)6+Ai* z?J^{rMm`&`4=xdc{Txj$G#|^Smb%zLc1`>MySQ#QGX)qw7IC=iPzB_3793=3Z_W_e z&VRPG-H0>GJi@QroD9)tn1Ftte17FfLFkwQ9chASBWONW;Rx*)8rc(9Q~iUhfC3(A z+kDDv+aD*^vPkNf=AiIQg*)GJFyhl z6MS8%q);T1;Za^@SdeshcCIIOaoa7YC^XusiC7v_QfYNen7}J71 zt6nn45pSB>rz=r+%TKKrlN}faGU;3^?<)1#prQe(p?<~fb{tv#6|+h8AWw6a|L6s} z;4d01F3@_{FFEem5JQj&E8$1a?E~sU$!6JQczu=1^o2p&eyf5hRQExg&K!tiWoO^4 zw+`@dgY4e+%d)^Z6LwQm#{FJxev*FAA0eaAy?0_FIcmv&5*JP|03W@IjI!9=qgc47 zvmaJ+5bdXQ$EC4LKO6ShwuW~PaQb4{dUrCBO^TT{({(f)6l4|qDeA5HUC4^t#fS?I z`-RB8p62$&5YmmBFP9HZVN|n-A#JYd(r)&Bd4@|RCj6ZU8iA7hUU){S&E2jOkW0x`Qcr**$%%!ws;jy48O1#`qVKHA+H;s=BtP;ZE7Yk@^ov z1O>|X5F^$4!2ZHd0{n^NyiTh;UO}Ptu50bQ~&z27NP-@)M z8ZE3`IA)Xz5W|MrfRLyWL0fTr55aAh)tPFk%xwqF^28n)T%n4naBWQS2a zV7{bgdcJeuQcvt1z#)4^X5Vqj9^lIbPe2_9;WQ>>cZ(&FQs2AXOR;Ffmc~`r0gvXA zn%b=GYv1PTL;SVf`xGJfw58i``i8dEYsls?u~!FQ6By)MF-N{=VwSFKhk} zp&V*7rr_Hlke41=Y2zm-q|yJFPk($!ZG%~+O-NGwi)VY_u+`0_rp*}U*Jd8pUGiJi zHj%cMU1R@hH~d}a1@MT|wo77iKP>@xLU*RpdZGwW;sa9}x6yN<04l2I@v1#j-w6Eq zA|+B)-<#%(M}GiJe|%^;02MjQBg67jW76K?;)x^(qOjrHy+a~1`A2@iea?V1o&8B& z`y&$YrZGa>((C>%@OgIc9gShg3F1)&=hkQKBY+AveMEKZTl)$Z{r|Y1A?;Js%f3_3R3dRag-^DY3iSW;R|1o&fd1%z#wIt5}6#U;00D_Bh zAdyx-y~qF8g@0{+(E@Z^9+ljGEKm4X3_p70UoreEhQFugzoX&b(eUqR_*(-1j)uQw z@vm<9|1lc!j}H(1xfZ~`uGGICJ7 zpT)BPCRudtOd9_YWrHNA!JD@{gs9cehGAdR0e{CUJ6hi7cG{gsseszj77)R5ew0@7 z6aa`iQzpfLd9?_LG88(K*s*-T`%dbUM^){tb~JnfHMwi9THQaQS~OE>^Ip&W7HaoWa`gs5Zs5%i>X=tQ)dHe-YZqfXjlAR)r!W7xV?6;C@`(g8 z8pqR9R%y)6xXU-6oJ;g(SKZ1oS>6C_q>K|CCnP@Zkb9N@6`{Ef(4~4VSn6{(Gk}`u zMm#8cCNp3r&q;o+(H-rO*S8IpO>l;Qm_I861m{5p$HT-Ju)9Uefb3X618!FNPlQ_m z#xqrWd+8_xR);%`%OwI}tUbE`QbnMGa782Ik^C8HczTx8-!P!CZMs=hy-@wa9FoCM zc|~(c=qkE{hLi5^4t~c2I$s7Vl~$S>D8Xup0(@q1pVJO;zh?0{%sW?APpqKh<6XHJ zg1%(eOvM{0PMx4tepZVx7f{26H!|Qdsdb{R9$)q=6J>5|~ZdUyj zUlzo3N$>vYq60>eJ|Ws5xv8ZgAlP++LDlUgrAv5!#>0rcv2)MeSG7b{Sa%iud$16# zoN>;Ha_HMwEruB}SG)6A{S^bIIt)XiWZibJ#+=Grn2a;*#wPf)d+m^;QX%Q;~Fa<>+ln^$e zMCCcujiXzD<`PG#IV3|kVYAUd*p+}pYQ&hy%%inW#Lx);@6I2nz43dTSlesRgL?^= z!|MqT&P*8I-0laRNYOtPYZc?d zgGGX3y%E3;C(^2x@{TakI-;gix}$azv)M#j5}>FnJ4PF8u(rENSi+WnTJ4a`4A80u zdS{?pQ2q_V|8BS9%o^lnaEHy6NvToSvQZY08w zc2NPd8=sSq32oT`(;|RI*cm%EMPtZ>SPeKJLpPsVG`{iK*3jMpiyAELFqtnF`uhT$ zIH6IH2eGyRYObpM{fSbfM?7BM0KyKCY+Sx)11)$v!tGH!K1S&dsJC)WK9}4BQo!&$ z1KoI9ExUc5N4qZUQ-O0jjUBlNN`pNX>)tUOI!mr!!cf!T8Rz!xND|bWr6zkP9YV^f zLp@=MHKWBOtw48spgFarQQz6^N?&Po!5de!@{reuH^i)X`nHv-`UtNd_P>w6U?O`d z8R%XK8a-LT0ZClYhG}8O+2G!^RK}0x2PXZt$9V`_T4Pp)!{o~9G&BkcICt$eqUfc( zP)Aw;P)*d=PUfxN=E6BsFC|RA!a9x9QDAbdWFJ(Ip(SfTF*Tkd|CV%}bisyI9EL9^ zV2>0b7H+jMkYUYScA(!Z`L_V>a4*D)T=7mZ8$3oEE7Q{nP~a+-XQ{|5*qgG)q8=0 zxjSKB`~^}ymoT3>13*pUOcYoa0$&RhzF586kLq@XW=hwN0&l|@DC5;`>w9-dqE>(~ zvla>xl|>^1vKhv4q^Jv$$`tjP-vgTF?QYQ9$++$JD}D!>v0I75ftIfFEiAp?@l{}E zsql_7eg_oKG16dQMe(SZ-g zEZ=ZqPx(6)tco#{f!w3)U@oWg5{HEn!+_pym`63M?z;mP6#^AX@*ppbmp9bz%PX3H zDpm1g&zW~GLE5p;+H1DK?V{Lx2s}2W-btkqXvz6{U3_Y_49S;9Xd)YAw@~}NA)&E$ z1GIHSdQf(Yjbww(wLZg{P49Y#uX5{A_G@pPI2VQ0C^{IGxyXQK>Zlh;{>}3UpB6Yd zx>PVyK0o1Yi=i1nl?V;N;b&?WnOfg4qnkgsW2=h@wQu%!uHN?Vyx3;Su&wSgegAE* zay+f-aif#)z-&5>`-~aJyLOn&W>OB=u7b%{JbvST+l!JuGRO*c;n=Xvlh21#sS9zG zEO$Svskg&XdmqFgyIG94AFQ`OD8OuD(; z%mrs{cq~fy7=*|Qzco2-q^g?rn;5FdC77x5^Ei-A@f~|_WK&)#??zvdmZZM!SpSOM z@y(>#`knH$TEEaBg)700^9#6OT9Uq!)Jc}F&Y?vMq%Em0hYd{dxN5vtDr%x)hqyC+ zzdU(3_%PdtC9sTx>Ba>AeywCtg*%{gZ*VUz4cpVoaWE8O67;jOsYh{A{m7U&9NCgU z;X!w*9het=mH3%(;x_b({D{!g4!1zFQ0Qn%+;G+geTgTqW{YfnU*EN{$Y|9xwHC2G=`^R{yR6`t-2JdT$9WVi43QK&&#&34rE|oig4f0s zc33P{Lp7Ce^C@}u%^!2FHLQ3_1#r@&`5PBtYSp}ReJls0_m2va*^frah9VW@22^>w zWj00^wp~-Wq{eE@>;i^-w%h5Syxk&vGXz$nX{84;U%bD&On}$BF0)I=4fv?K#ghPo zBpHSMqENz?AFSNBWj4WC6S%JA+)-p`*C4OI_Z~UT9~S$2&*}zywG2VgHv^H*jaB7J zr?Au~BeQtB3 zLkzdyxyu^z*YMd|j#UF5^8ntEv!Hx@5}JbDw=?BPCGxon=;eIX2p7 z_%qtHK1Wj8&6-wB{rA<+D3+pbVRGLuYb6wGU)`zHd^!(>?>Z!H0!Oq3n{JQ`}=>P&+F3tl;7J zSEysyRMnkd?axE;y{q|$Q(6byKx>u9@EP}(gKD2&2NqI(Ixo%VIwqR4rq7#4Ty^1~ zxG}vFFG~np&)9bVhNvK^;gi4<)WwtwN4a&!*~(BQWB84!d5>qewyR(one_)@aoB^7 zmR_T^#54W01qtA7@{%Ma5O$0{wwgmD>W0|fM)O#6<{jMJTteVJR82|p$bm$;s%z9(Rtzh0tKJ_ zi+37^XXX>pU3VnYv@NCY*2`CQ+xKEh zoWnb71@lZii-ZHSskev1S1=`DU5w@hQl!iKi#A$zgwMBt6SZ(idVV|tML*nOIB(Q; zjW-rCTIg}i7gxV7S0s)9^R+QVe{r_>139`I#p>n(QF-1QT2HD>e6=z9z2%HbNKL36-p`Dw5UkNu zU?IO>ZChn~SQE^=r@(!V`Ymn^p8jkh$3$6Uz-kiYc`s$!XO>riveu2&0h6yzY`0aI zYUq+Al1zQyB*{jnV-b#d$9Oxj$( z_a6^tit8F`*0M-*S%RM$x?5k@%k&W0B(gu+teQy~$X`8#xsMtJOJ&^l;3TJY1vsCm5033XPUk-)b4G z$K_uS^APXY1m-KJWJ14in%sSz-{==drWLGcM$6befLDALQh_t!j0=j^zb4eRTh*`; zzx>9T)n5%&7?w7RF8$8d4k*uZPNzxm@>>e;>d$=9FO={?#}*|wKj;r)fgKoAhasnRGe$9E zYzG5Y;2P=?RBeEC$Kp1;-V4KKfO_E6qXu#5y{LinIewJJ^E;NPkv#Oj3gGX&qK2eb z_#;NIKYG4fs$K&B)$QXYv67PcRU7cVzOC?Coz;2x+B za>Q_YV#()#C&^9RQGQM&;&$pcK{Cus8&H&CDZk`bvGAX#x_qeCD z^uG2jZpy^B`|OJe=hlrZs8I-Bc?H7|lBk3N8do zpZKYr96Ra3b8zWo%c@zZMORSp;A=ysPf>99f;W%tB4=g%^$wvt%)DR?n1YPP>c#|( z1dR_QhYlmXai0XU6MY-5)F-7^Q%?sxC4-gIjwUIBFtq3NydvtVi!cRyu>RQ_5p`HZ z6m5B{z+YEMhh~JWn7o_~jcF=;?BO+$+Sk%F&vhyKq*7p_xb~J!AFbw@wtCfv;vfRz zh7z~3zsjSB7QgT;&ijcnI3Vln(r!Webo~(Ez?A~FlgLZRxWm8 zveJj*{}ATAWTN1(L8Yx3G`9TxB+j#ZrAp-l+lQ#D(RsoP1&2;D-4K@~EZW>L7qmy< zt~xEO+vw-GR0}kD4LY&Q*V{_kB^NCq;Fu3l)0W}Z^vFun=#=<6udZ6p_}) zVA8Z3qGOFwS&{l@w>I>(CvR-BcM;l4VCNE!C@;U$>k{<@(Xt@JXZbw=1%dI0jnF5v z^bS_iv4G>4nBBEedNY!*|2+Tb^7+Rcy2EXz_d7<`3P{;Htc=)p?e`A`8R@1Q4GA1-Y z77; z`XZ`o`gP@9OaR32Bi|cQ2VRzz8aiik5hUZ`R1vqr$TXr;Cq1)8xd;;}cP3Pg<8v>d zq^)H<@ia|zGM2ef*jrR%f{j-va$C|Pib@J1%L`05xpg?yiUSMTLA`0g!YV6wwf(x3 ze4^NL?uwuODGz(SzPVu&xewyagFH{|5_CB6Yc>`8!O3W~tWn#P5ikuLj=t zGW^2W5~()4AEmQtV($LAyJXna3Gci0&7Sh;g0g?!B9cWB^@y6;$RTC$wruD{#k7ub zpGWPO7Mj{ltMU4LgI#TBd2Bnj3BheY0Hunn>Qz2Nbip?1hW(>1*uv|zba;R0Ad~GfJ0uuIQZYX>GLdf@W^DS5;Wsz$^kG5y1z3zG=N!_4&m;|W%c-5{Iy_c*05@$P*hx_t0W`PAdQMT*5xT1g{2qK}RK}n00v`R_}3?0%iL&G4gsI-8Bw1hM>3_Zk< z(jg!*bV!#2f^@m>dDmL|x8Ak){(t&^T;Di2o|)&F`?>DxzUn;BO0H_E867%U#yh%* zZf#+At@~4axoRmRqK3e!Czo3*I~q(1wn9B$qD?V^Rn`T*ziAAqFAe)BWiZ(BHomdM z+~ik5kXz`MCgWqMt!)0JIHv%Ilc7mMwHWAcBLiw4B{s*{f)M^>n-2^hemyY_+(K9} z!@)RE<;(gRC@m>t0voQ}(|APaAFdgdVW=M=8K3UtgL>aqN!M~#gL4fitb93}r0wiI zEUEHf?Q2B59>s#rTg}?>~E!oRYs5`%Jy%kBKT-JUmvFVde(L;GMgLN(5aGPwn ze<0F<;OjSMIHzO;z$ zm}jJ`3Bo2>Yd>+KOcD|2@y^pQRt7Ww)_hM}gR)BRJz0_X<_mDF@Ed}F_;dnP!EmLq z`D?AOUv;>UU6WY23v_1A1!p$$GnAQ;I+iPE?3_joEN`52AZ0;QJdOgrgd zy=}|3%#e%gm6Nq_W@O4JQGOL*-Rb6O4l%%Vk!U9X4>mP}!$s)3 zJa+zSccN4NU_ylVipkGHB__sk&%!M=?P*-~hJOR1&V=az!&ik%DRXu&T;Hk7iAsYo zGg%^;_q(T|GssKx0&r_5?`zz$(|h7oO9jU|FAO&xJLk0aaer|x9cOl=7kAOXGHr_xM_`#xHBlmM;PAAk)L17^tt&csGgs$kDqrv)&Ul48E1-O3hyfYYV&zoL^GSR{q#+}!# za=3zU`Rz~(9kt@wmVK_h?&6VjzINi8i%5pCq0{E8N8*#U-gxMU)0XGg;t32~YfLVx zGMfGVl&1ySE!-Q*Wb}}=tx4@4wt|YU*bf4%J_oc0kJ%;CjMU`o%`?s0^g6KtsNjuL zJIAm4g7iOBrg37%&L%&9L*&U;Mwg9mEDy=oIL3mJ z$8V0)z;c-Q6zMjm;`7$EDLy*a9i~%yhcW2H^lH^KR9>! zmM>?4AHX0jcvoxWE@gB35l7A-V?9Db*M?VOeBASFt{64wUBCt^bEB92r*4KN+IAR1aK@#SCO2J~cYr8+&Ag&UG|!uHPH!R`!UrL-znghM?{c z=enI%;0s@)@5_+WpMU_MsdxgW+obvUbl$JI5lJu%QR}%C-BfZoc_+`CS_XfkQ8WZVS<>Mz3QnHf3Q_j|nyb(ON?(8-x|VCNoRJlo=K2tc8E724IOH0)Cuz)ed;lVB9lM6pxfC6FSH7kqbx#9 z+t#|zi?osb-E;xh?#VKF%IR0C7R)y9j2@j2L%kzeRBBH{h{K7~2ZkSf1jAg#PF6a#U2oFc z{N>PBu?ld6RNZ4ISv+pASaeb_4|Sz88wS;NBgJ%tX2YGNrZ#o zr#5~21@1KjErz0CIN#h^%Hw*5uFOT!Qz?PcCOG6Z=J3V6rRyS=S;QS} z!;qR!#WO#j6YqH982PdqkTt?mJoj^5Qux%hSGFty;D0Jbg|MY%kk_Rb3Yc#jv=R9m z8m)RVLzXy^y+wW&1%0Kpo8FKkJ>07{!3uKCjf+*u5~WpI5gShq^w$^UN0s&`^)KhQ z_^y^HKa{d7?c;?<$~^%U6e2vLA%E;LlZ@YzdhuKKz<_*@ zn}}_fwQ;N~oKVQa4dSbZDJ?$XhYvulmHmS`Mgh|^r?8>4--p)_1M>A>cOev{>wH;} zdWM~y(Yh%bMWuSPcVp#MglJ_IHKkMwE^6V_qhDN9X@{nd0NV2 zI^dX8+tj%orQ7;TdRynEMLNk#2)8SE$08M6P2ZlQ4BsKT5VE+t5j=ynoTHL}?(n62 zIm056)rT{ahuptcp}wPP&k$?xR|!r6*B_a%ALpeYfLqb*AP_E!{VEdte8-oh&$#~t!bPxL}hz+JI9~hq~ub=X8iOtN&2iu;F;k#IBpqKu-x(s++)L>W!78SW+bD@YC# zgPF6>ggEy|+E$sdh>Sm%moMPDv%zy*?$``czpfHo)oy7SUV^(MI%8iF_MnWRWly@G zKWN|f(SEC37HmF2>3=uz#y;{KmD0W6_;?=@IV&Q|w0Q|bJPE3|g4kxgywJH)<&%&{ zQGmL$Xe4hC&!QmTs||_e7GX{YfsX7m05W)H6GJ{qj-IBz-}&WgC+2?L%@OShcID!y zhQwy#frwno#OB+&homqu_0ido>lxQllJbY<^e3%#Df{{K@$@9^;|9@v-5UU8Ui^)t zPIFLA_8(_bwESxfXz9e&+#0Sw;;OZ~*5d(CxCSFR>7H+M7lN?RQWDTWzjlBFoU6Lm z{MQ4!*7DNR3L*_AM=YhrDBLayGG7`t9AS&sziXyIsMeg~bw;aV&cFW8yooppqO67* z^U;iDHYcqLs{AY9MU&B)dYL=dP=D5nC9VA2CL#^LR4}_sS~v&*vvGgwn@PDBUsW9y zZ+cGcNt;2IT>>2Ygw3TF*8VCZ_t~o@<48xJ{$(+Lb2@}<35L)Dzdsc(5XmGZxiWbE zBRdhOMbrMDU#Rfa&Ob~yiIS-C|0@z@8;N|BbL;o|AweSPB^vJmZ4Rtq|F(1GxXlJ(4-Q2f z_wqx4g~OvmeCZYxm*gg8521Ag?eHPcx89x!!h*=xmJ|e52W|8ys{>)#i{L{xbp*$*be*z)ST4uUw z=}eOflpKy4a<{SBaacbYz(wD!Yk-r5>`;ZaGx-0?5#g* z1*_^pXfif^QYUwY&nj*wL?OYb#6f7t^MZv!<_Scqw^|l)2%Pz5QCT-F`yYuey&k@%)Zq1LT6j#hNQh+JF;=h_$B=Wyd{KzQ%75Cx$7 z&X2}1TCr}J%?jTT#7=wR&0v5w0!jvZsufK6HsPsCIuf$=zjWEqNwyl!!j6S2vw)$L zLmNd}KcA%+rKLjxpr0awG=!nqwZ7m8xb31O1}WMMxU&MCE@~lc@zXL%~NEB?9tFG z2|0)e8|=)m_;cJXld%N04G)Ed4)HrUu2pSaq7${^d_+MwzF(f?Q=q|CPY<1(!V~_8 z8tT_ttq&LYH-=my8lM$5Nm5Lh^gR^EBqwlQbqW%$TpR@c@+hC(m8)Q=v_zR>+Bm47 zXW>-eX{(aV)3VsVOFSwP%Qd<^2rVeMML)?`yV~jW0axAQKSS0H%ITmQxLM|3Ud>}p z{%3xY*<`cB+^87JUCDEw5@DFF$OPBX{drY(2yR_e*F1qJg-Jy|RHE;ngjO^9Tx#AQ zz~fbiTKvvXu+(4ToSzkD(VGsK`L~Dj)pJkJhbP@fwv*muw&D7BhTy(lYSOe9p}mtu z&0!I*qTOk6oe`N)=1q>UMn@yZeAdqXM(X*By;5zD> zfawu`=ScO?Dy}R24H*b-#D}|yAlyytW@XBay4rkI(ZmHYqQJGr>LA?i@gU1krj$CZ zP|w)4Z80brsxT@4{3n5H2$Sb3Xc@?^ztOnJjr^Ev9lAHc$ZhMY@1>o|FjOX_)P&%Y z^#^y~6Sx29j7U|Rz6oesY@}|~6HT(NK@{Be6wL}UbZ>qS$L?N*IpoiPKi{C}0N}HCnwO)%)sT}5?9&v`o_*CCwembIW8F}5&XQHlUZ+KZuCVsLu zZd%-_?Cg1ZLFFqwFi$n(Gw9{BN>}L$^%glQtYvyx(?5FO_FplyTj9E!%t$GR--oOW zJFc}mRgTU+`X;LQ^lAxK+z$(YPp0t4=N%q+P3uN14IB9zI;Ar3T&M#y7Sw<+wTjDD z|GPHDFSsMUiny~;8vPcY)h#k!l*DSo&^ettWdsB0)fJ3eU{hl?4L|*;Q(Yqi=e%V{ z3D;BDHKf_T5v-Qm6X?{!`;fA%KF37i#@cbgn zNucBsTg+gR5`)Lr=7OX=rCaU$noi53pI;4UvC_+6X7dA{#WU%RHmMwfC>Cos(xpyk zPwLki!d7Z)i_|l(SY9iy=qB7I3*Os+^KUb46`LKaCt*w6UtrKOTm7z6c zScBbt%Qq}kM4$^!=IDoTV~a-a4>^0fs&IZS65lsSZpnRm6ItYbgy|RF z5%qlc0SBgUc1#8FwUuy3V$7}K$V}*LKJTNmBHSG;^@r&zYYJ$tIP9~+WZlLMqV9d~ zIQx~9sqbp*x`4MOsThg;^U3s*jQ~r?+}F>hTYwPuMqr zb6JC_6Q&OAX>in#=ag=&x_K;pDTC#bUR-n2JHiBb-DqVNJj>s>coCtCiBsO-#_Iax z8!uBcy-LEz4!3%x_9`{TN)y{5xZENT>FfXAfTkB4?c)#ZxLSu<9zN~yQpCoYeut4S zxAJ7j#DkG@!~%x-?#38{bjFDHqdi)P-tru5Q=DQIqv`BiFrJocFX@b&6KrFajzb?n zhk`p4(J9FNIJiIZckD>c3?JEvVyLi;H7F2@Rj94rNl2#BVxFL_AYU~b3;wMSC^F9M zPhz@r-M{0NSL&3hQ!nl6#;1mW5m?-ekwE(icW3JD7s} zZ&gD4ye?j*seYjf3~Hi3ZHDcZm{QQAofeTH*G7okzyYnMl3$1sdA>wuqOsxgY!reJ zE`CwnUG%EJW*@_)r>|`^ItvYd=B&oWiSjpMa-W#I&lSz=*`Wm*Hl?T9Ee@$EdWf}8 zB@Y!Nk!#&r)0Qu%Eg`9}=n_fKEf|wTa3l7JIgJ=k8FPAWNFiOJj{TZzk`Q##4TgzZ z*pnTm?NiwCAagZ9mMa>U(loS2z(w|Lf`o0a;6`S0GN%gk>T{;M**hh3q$2CWdpd*4 zq7K}Xx!eKk%WGilNX1&)w_1IZ_CvWhXOlKrI|WtA@t>cm#2G*3jv7Mnaie^WQmm<* zxYE`$ei{BYQi3uCf!wo(j`%_orw>|lpHASj+<@2|Kk13Q6aBe%xdK;Z8Yo6$xkF#-RDh?z`9J`KWg04^HrER}(E1GRBFY zcs7y4(evIw!^eH0V8WmxmRLJOHyMXW@O+?WB=pCxp=g->Oe<%IXHEn*x42N@NRlQ` zEB0*2REPL!hOUoWkmX(U(gSDIV_x_~1T6{CdChu%!CTkpDnFz=#*+IkiGuUT@TZ9(nO4PLJghm*MVb zw2Psrg%-8O%sB$5zf!r8+~1=()8ILMFcG&^278$D=PPx7T&0|yGiq%zVs_+VN#R*V zM9t3Pw5~q$j+{aes?5X9XzwTiMk-_J@+F9NCq$)+EuVHeBJ#_KPmz$I(69M&8NJE% zl=Tzl$W8y=ilf0d*4Lihj<>cFF*~n%e^aQ*!kZH+;Zt;Yk)9>QQN=6vyG>)n<#mKV zYp-$1xIC?`C(7s3m#BC4OfXi>jkG%-C;N4~+Y4sPVsy=JJKNhfSnZ`J1bC*8#rH}( z>dA-|*U6up9z+RgYVK~U;znJ$weOjAKu%sjw!rj5qr;IQO}_PoieJrF^On$VCulFb z51squxw5F8<6D;NNZ5y9LITRyvad*PYaS#RC!}-0^hxRrR3v??3t}th!@1dY>*ck> z%dQOHkK20aZ!$h#idOKnmbxut7D)>iv3`V`{-`fW)wkHFuFW)w?zDJH@oLtfFKSBk zo<4*oKkk(Q^D{9Kq#}3TNLf5KLL-Ty)#hd=adqx5!;Z;3wgIQ#y`sg#1)67!E=?DO zZ$$Y^YO6o87Q~hox@)1!?X1f^h<5IU#mA#2A^bRtqH8rpyhltTGvgE^5S-A4PrS<- z?=G)8JR5tho9KRPr>Qit3a~Y*Q!C||dR>p=W1xH%@28Jg4N_Q{%=Gx{EZa2tPob#nl>G~&~{y-JR zrx-Xz1|(U3`^cfwld0eAhFt=Xj-rA_%jWorw>)Nh*M)fhVO|LDG8dnh-xb+#Gd7M8 zZ>&4^I3S)F6+s(!uU}tbq$hbid!sR27Ilc+{m8@OW8;JLkKLU z-5qap`~tH1mx-DF6yGc+M9;_4)EP@AsoYt}MxQ3jfLXyVvP+XPV+81QR9+G_59R9% zmksX-#H&Y%3dNhN-u5hfQXx(@@Jw9pY7Ax20Hp-${Vu9? z)93vPJ~U6G%wq|*`#4Z}=r4y^%wqG{;V3G-moi*Kp=~X3e1&3rNjyvuPLp>QB8KH_ zef*9q@1=aACsw64@oI8nM?xv3+0Q4`21fHYCD6)e@)1*%yy-C;0T~k}D!1SqNcG`> zEQqojN=~JUvW^|b;nO|w4rv+V5I6wIvjNUUhMwIYVYR!pc-|3Ys z>~pvN_iryN`wOKsy_i|4Ev*-wA9s*oRwcsKZIRnFFg#!hU04@gn<+Y1r;d5TDEo8N zy(aZr)>z{1)rI%@l!RUJ5z}3cke~=BuO}Y%RKv~?vqG6O-3LSd&(G}lmUbPUr(z0f;@B;wv$=WnAJ3l@7S?5zQ*b?m6G!Jc+J{`d>bHf8sH?ld|Ti$ z{>v|jD?b5W4L*MS^fpGEWZP2uj(XrVd_G`Kouv@@tZ-uf6Sno4v96}8kDa;KHT;9z zEV?{Tywr@x6H&_q2uQX@>t55N{=|THlGX&<_b}$5Jg(XdYd78HH#;&Wz~7zIbF1&ElZ3nc}&n(+8klKS}_l*h|GboowJu41l{!V0=0m!2(>o0)Sji-Ycne zcxg%jpWW5tOPdKi7xv0r05q?1_v?K+wiNtY`Mhbu4^(3cR?CiSS2H7;@%nQ&ma-`S zdgX7LfSlhgJZ-WN)Zgnj$ZS+)I#ZcnT*AK!8T@&5gE8;%KVEQf`0K(P0Eub7{pZ!r zLn*h#P606DP2`U?c?GnrJoG&V3>$p#1OI2E=w)1YpJAgM4RDHDc zi7CZQkO+UljVqF8yF+uJ#6wz^J@QRzTEaHPu~NO0-W&hSfQ}p(*SiLn|KkDv z`qlsZ^SdKhj9OHCC;vYd<*Rs?1Xp|rP`v>tW_dgeVFkHO6?u2}>gMaG( z`S-v7nW10295-?(0h(&0Bl(u z$Z7%5&YPe#Qe&gR;dd?2)K(lioS)%|STdSD*4=r(b8{c03@!i<6@r(b`RqAiZw|T# zdm$|#x@VjLeE3$gT*yMLm+x8r(-gkn!h3-%W+F*Cz$vJt4>Vu6avlP*vUh-WR`4f~ zetSF#!T?!kDt#c=)dIG6617txA?+26#$ns6=ru5>Qu62gK=Yo{aQ6F&k#=iLjh6~6h9ji=8AJ6{=;MLFP4WLNcLd4+k;d~@G zz|6IcrmMjarThQ=q^5R=mrAXIt=`$gC%^>8GqbnAOa; zsf2@XWfdtue83~YIJ_UNWydzN#;V4o6a&=RLq;H5+4X?Lo9gg%ev6@=Q}du%%2Mp= zFzAZw3XW|9-ZPF~-8XvxqOzJIKmcbV5BT?u47T^GD%gan2KG zqyR`}1+8760wtj;jMb^RDGjvfT)@0NE1$Gg65{dw#={c@e$wH3m;Rf51n7x%d^N+R zi!FimQUN$4%bXj!L}-WoKa~83SCH+%yMk)2TZv@eU)F#q=kvSIXmWPPZPSBTPJa-C z^TkQ&4G(%)YYs3ebCJ$GIPrb#uzoYqDjP|nLzB-yGdL?sna?mlpS;jwlHnxB6o|Qg zC+g|nJ={$nuo_Rzh~LIs;ujL8%8$FFmShSrY%M@Rx1aSD9@dK&$b7)*jdQ+xW%!J( z!@C~u=nNzGo24!VV(N;n=l2}BQ2*Vb$#MXU@#Z_jo9`rrxHY*|+%CBRN<+39yasa% z9t)AEZD6ut3468zMBvC`)y3@-L45vpD(o;?pGM&qHW18#3Ux-W0)5TI)3q$!a9e-} zyNXx-+FVm)_O>cBvxprWz3Vz%d-y?PeY>53|55zeO00%7NrH)|ffvY#Tad*K^!NdA z!Z2xYygDR0lyx-&O-N?E&LnG|{U1PXtVtK-ch)T&POGB0skJCR2m1XaTth&kD)Cd+ zX6xb8sojhGIlN8)|7LOs(ABAnjY$^+L6<~yE@y2s92R~*S7{Kh(AEM-@Ke+(agF6m zi2!4FBX~ZCVjf~*Xs_5WbzuAfM#oE)gLe+MM}_fPXNQ11nI12Ec$@A581Ou39@f?{ zNyvGgr4WQiHQL=)aN@_y(PpP%qr&6scJcJWF5sJ3agX0hAc(hTJ%-d;0DR7j8j^m- z;`i%u_3=6~cKnViEkA(Wf7Iwp0JP$Y8HXrnU(irWXemTp8#}X2!=85ng7~n-16WzM+^Cn4e z*bHKStMfgNnnNw**;r-3$zQE~}#}2eTuM2BNhjM$v@BhOhKexOi43h zUfoIZc`FL=v&$gczFuRIPj^J8<9YXKgL0<4KIL(yjn3beOLx!eH1LXwvj^%2NQwT0 z$D>a?w+|vYH92scq*FC(?*Yyl4S?L3ilVrN9V%kpGG*);A56Q~m;wF~!_uDRVB*n# z2q0m)5iIjP))|NM7xdJOkvzCiB-aqvk^O=2O=5efYe`uYgz+abCQe8-OJpMd)HOp; z&Fo|Q#kL8s9kYN1E-8IZa9$7>ts9}XN!cT)gpXZA>4 zOM3dxLepn??dqtvrOJn5C0Y@eEQ035{v)b-k#Xf+V0faJM8s>lWCZCjp5fw{%4~P1 z4p78PMpvtM=61;7k$OggMsn4P}|(Q7vb}bw-G7 zXW66eYSI_g7~_rIy2PJ9vw&70)LXg2p3bwNIAQdclgxu}t#`AUKXTq)ljlCn#)SsX zM~!R=he;2_)bSO8=qJmiM0W2MZ}vtrx5mJHEv+pDs{=|}xa2yDYojdZA~WnatvW31 zYvn6^QAwgB;mb$adJs>H0wMZ()>l+vS=L@!3gnBS={dJhp|I_i_wco`Xa$SRX7s{D z$!_>ad&`akY_b?WBX!SkeAHx?$_(BZs{0LX$D1xlnGU)yMVv=guWIKJ%@soT%$OX2 z<;V;s8Ed!e9 zj@PnMKSCw$1)g6S23*rF$1zB{nV)yL6@5$NLm5r{h6z9JZQ*4}gxH z7Qi>ai6}{a?+aT%XIT-ME2;P09V1CRzryqp>YVangpqZWlh(T2FVR`Q@@14Gp5qq3XwLN!e5*HEG_0HI`&p)2XZU!c$_0Ky09&pVGXAJv z=pS3n47kI=1)9R}y4XIoxz;Qmm8<3#Qnw zeD)Yr_Eu&;!4KF7eQp+|%3tD>D~zBGyHUojXY3u1^-OCmLXQ}7s~K5%c#Z=#$f1R@ zH$6tI=iE{T0=`wW-sUOed4WU*pOK7IewpcGQ$uWsZhFWZtFCp>jA!LN{&^*x1`rdu z|E>UADR;^Wm&PHt);bHA6YQ(&JlBS_j}|AsQWPGxvi(T5t{)j7M#+4>a?+h}+5IdI zeTU@inZ~PuEe{jPeaqXIp*eZ`CRPLd<}*guZMSZ98zm)<^}$-igbelSZ8@1q{M$`N z7Ud&0IcWc)@?a1ubDy}ScS~EP*g;BjG-LBBh`9m`2IHcRHh7#VbDkg7%c6V+z9nTY z;T84_Um}Yz(DWD5{E+UvmCTw+PWp=HcgxBuMaqGqdBx|VyCo|jo3-PQAEv)1=dpib zy}LSaPC5CvV;mH%A}+6Fv}GhIQ+L>83tDX(?6*2Lg+y^=ndGr0Wb4+>k>gSfLxw^_s~Y3*BZG)B&-R?MPY?F2c_*0j zVVa*ON)I;*A>i|Vr>aQ~=T_JG^;8g|B;Skc_YF-b(-UmE4~k!%A(we8H}0OTha9cP z`{w=}O!rt??wlwrZ23*=&(Pd#*90_v|F*16njrgN=GuAt+38-OAwTZ;N33)V*lG+p z{3svq-V?h|e)AI%DCujXb^{@^Jf{His!w+c5bA2t_h$qze%WmO7LBlot%`|7Ml19% z`~Lj6T>MeiADkEo3bwjyWx6m{xBGXG)M-TxR&40h=tOhf6bI9n!1#)K;epjxz5N6< zS^O&(mC32tU5>NA%$oYh4Z^&H9N#frG&7vDVso0KHxT9nDWiCf$MvTM54qH9tk$;N zfR1X;(I7guitL>%@5UNeg#T;x^PzH;q{N9n*u4~|fi1+rdpr@y{oe|gRGz7f#-USz zCSwiX5m?#Kp2QJ0<6o8;MPCI~mfjRDZtjo5kpyU>5qe(JlF^JXGe6S_h;-W@kZ9&T zge@kB*Y0wdwA~+7frd~`|E8@mEA=!KT43Fh-2Z3E>|a$LJ5f+(^1Oljepn~#$e$fK zQg%D`W_(qmFY!?~s_c;NCtlcYlUj`%K#RMF@O&r9ex{;jtf&aq^L#E5?+t~TCcBDG z#fnlWE6`vPwOSB4V4lw{i9G+-7HX`U$Zs8?{RFw*xs!W;%}xHx{SyeC0ievchUF~L zA^%8T9}Iz2IBr*DF&&A-qlfp8ei6Vcd5>MnPDR=A;zlx`98Pu-0baw#J)Mz?aq^pX zyAR}!N~M2)dkCYFQ1j552|o>|cqf}`JD#K$EcmrtRn>6?{V}1q&L0@*jG9~)%y`W% zK9pR+3UxGjD`Ak!60r~&ABZ9P-MXmY-6gSETwW)}5I6gqFWL3SP@K^4cJ?NDV##J3E3btUqF7%<%tNY3ynEqy| z7cP?m-%R&<4L#jUI(&S=$Pp~$uGa+~E(eqg*ore^T}Z>%I~(ED{!UC41vJcX|a{$n5nc6k!HY z-Qg8>1zaNbr097h6b<5*{@f#b`HcN3zZ!%Soxz`J5TFVBhn6XQI|WgWX)VCSyOmCZ zB(|&LvT%LvPryJwqtbt{GzMmR2hVz)4!tG@q7dPVm+ok)_#w*dT-w)-mJWJAeyII> zqyt2r1`FNYt^fpq^hS1qHgY*ZLVxY-J|B-z^+Lkk2iPh?vrWXL{AjR-gmdk>)YD7S z-70A^=XG9ajrbvP4hhPUzUoiv*R`2o6<(Wfy~#zo6J%yqF-|%GNa zf=r|8_a~&e(F)!LS5L7N{+w>jBpj;6zO%W)Kfau*+!mR`q!OUZ1OWL8tG(^C+?p>* ze8Ty)UyE@G|Ljow@5MfT3Q8t2!)c`~)xGk0Y2)oD!t8%Ws;CFYHYu?NMCiuF>^;Hou#qVUdVfoAa`OjPj#+ zql-sZ6J*wx;*I#=4>Ia{x(%gsCrb~Ho!b)1qVt%5U3v*o62MJsJ1y&nwN%&~m2t95 zRc)_6tL?E>T`kLuZ`{XI#VyNttjWlUB?3qH7{P;2sD0||K-~eJM;#V+$=`9KS48GC5)OB&NHSSitKE&nCh=7$m135_62Il#ZTE+-GZe_W7uoT^D zSUYQLdjc%9&3prtH!?P*d1lX!^%2s;$cqLtwemQ*HJizZd8mkqiW!Vt&d7UrPLKE5 zD9@=;O$f)wZHoU0%0)n7$>~z7Q)nhw`)=;p7N51a54zUdnaPFd6a%3p9}tlUGr_ZG$tOI*`^|R{}8zWGsjZBnzS)&X7!o3^6qD5zK^poP2H&lWO2G zh({~?73M1aI*rcDES!=O#S%w@tsB;*EI|!IrH6I&N+hkn*zirIPrE7-3tDy7s{R=H zNl)IY1yj>KdY*2TnR5kK5w1qMe11?}u47%_H*xD?v!BL+jREhVU&`TgIo$>_J^Yc} zC$2vn#(=I7Kgpz1pkY5NEMot3@Ina=Usx+Qm=pbv)q0FiVOBds*uQ#S9iDks*4;sd zXVc2#Z`~1{PM5!%QLi%#hG29bvW`#!=hir@O)E`}M#)`Fei+i_d7j zJ=aQ@Q9u-K!M$vPcgJ_i!N=4JjQVsu(?~$4U6wfW*1IEKkor$+L-Wkn3tKT$nsAJ4 zE+Sg^K{~uOXoVw15@R(^=AatHLcQE_v52gk8Ugdhi1C&bjj}A@aw}b{=)6;)#T(GNLwHHjx z@|n*DIr*gvrJ=C$SG#2QjR0U2<>9GTO9;(D-r~a8c1DJ7YP;p+%wlrmM6UkFYJFh` zt2HbvptM$Hlo4MHz0qZLM}L2=1jrI{dSBN)OtMKX;43tZr%5nP#1ndH(H~Q$=6Hjm z`98@8uZo7)+&k$G#}H#{Rq?fKW#b*35l|=<=*JlX_?$Oarbh7+$y! z_fe6#;40TB>+y@kDYOvPH(et~v=Go9^(*H~J3s%xmWd5oZ~PW+2sbw`AMwFK6}c24 z+jbx(kJHdTh@eHgZy7EFZ(DTL2ekWg-**%F4YPlvc|FKOm5+6LU&FH&5wGy=)c@&r z7fxxs3~)o{tv&PT=L6AYZBe8{vUMYJ=An>f%PCdQvB_Ir`3PfN;;h+&p5p^Yu&bZm z8p@PBK6~m)e!R=zDEiM_`+ja>=Dy$Q3+I7MjG)=MkAfAk75!3M2Xg!pyQVWJ9Gz>X zJI-Dsev%O%?N`gvX;#~-%X!Q!mrhppAJy%q3pYS~`JyS6s-7;{aPKinuuEK3`y7{3 z)yZGM<9YV!k7d-OTnefiH>nfk5OwmI{dm@?+yst!Z-Cc2cLT(rV?uoXe%pZ94du>o zH@zC4jLz2@XwRZPqezFTcz@or5C5I<_F6Z$Q<=t_yd3Tb>&Ex=!U&PCmv69k;Hxte zcs&t{yh$n!xbgNk(8F0f*A*?>YXrPBiwXsP2FFye8PFcWxQu&&VlJdDE08MRIx_K$ zGlNFgv1?sR_r1ZZ`Qy+WCK*uS!Bt?;L>E~-48%|om!af_`qiMWUBJiuC+qsdSFvdOX-1sR?;iubT5S{u4-^@uj+JdjocpUtTG$$Mc7wjWJ;OtY~2^8hGfF--82>CVF_}M2O8&D{bCF6rQ_~Kj6{k| zaFQbhJChByOWC{<54oRXBdEMHgZ9U-zPiUU+#TAgRNg-9?RMY-x?^m*gKj6Tc*QVQ z2ZPULi@t!r?D*4HBP5hkwmG*|&tFrcc@pd^gA^ys+MpL}ca{6|M}_BcdfV|CcQ&-J zjnyZ|WAITE_gH5=iJd*xjh#$uurSz!iD)ktpuOA`LT-JZTj7{9f8`Sg=^92rj|a+t zXW3GFQ#}8jSbs_~_&41B1nl78u5+cSmQKNAoZ8s>O*46bf-a7)&(-oU9sjk8n$ti)~`o1<0J?u(2cNkUx;q+x_SW_h` zx)Yiqzn6Pl3kua*Djw)rAZ}OQe>+BS9B&bJvLi(;&On4&xR-zmR)f_%-f=~p)TTXL zP7eUTeo5tRWjq}UUOf0iZXnY(yHO;Z$SAzeR^~taqYVfaMV}%gT713~m=K^{l$7>I z%+3kNoK=itjlwgR06B`mbWgd=sI$uDe)ZaYS5ud-gas1UB{Uim${V8LQKn5xvBNw) zJas7RJ@&6WTlci3du<4zsod8wq@rqVd~T2LUNn0Wu~Y>LflX9R#1c&F1rhqtCPn-4?Yn`7#=ZT8L0ChJ zG&A}KzYoZlOo|9}uCds9`Zk{J|5hG$6s5XBQ_VE0V3J85AmrZv!S{;HJys*n6R8eH zch*Z+t(B{|i?~#KcFa47e$!V7Aq)R1F^N7mJkT|JIAFcmlQ;jgN^( z5nb}cea)+Zh1M@Y>T3K&uR-6s#>l3?`sPx|(5nyMO>?a;A}ETK8Ifh3;YQl%`nVm? z=GF2-Oj&bACwua9KQKt?#)j_0K%`>04NR##4DOiL#9eidYJtJO=~>ZTt4FBl-CO)d zJ$E&9(~_S^e~8Ep;4VgRs2IV{OfACLsJ3&S9iu9<5c31FB*R=;h3y~=ZWq61aYtsl zO7~DK|6M5<-Y6@=t^0*Fm&uN1ypywEFlN`}mZ6HXCWp>JIH-CZ>|4LhimDoqK9W|C zFd`TMO=tV(D@6=pVV+tNMdT64ZcLJIFj1}0P4fUh)T!YHCayN+<2^-PWszHAFySJE zD$>fXr06S`cd0-mnBd*<4K#FJr;q8${@IjmeEkflXx>NFDtMPl+K%o#*s?9xPe}so zudscG7y;DTB{t0-$2jNmmZVGr*8h zn~YrGJvmXDI}O9ZfUJ~TE>K*~6;)8ZP_e-p#kuqDkbot#%_3B{Nv-Wm)AKsDof|=c zl!Q~c{Z%(IBZ4T;%s6BYCSb*sdG?cEDhso63`5@-Yb|r$4z^=s0CLgsx${xdkf#-$ zs`HvPS#d8y<6qw~ToIL{pZP5Ug}Kbr`#+DJqf7z9J@v+ZJ0UGS6A-~ z*X=b2!}ltdp?n6-pbdI6Q{ueD}s+dy$Rf+;IMSXpo4p#$MPZRw0Y zKXhR4Vs(&MfQoN_zJXby|JLQRWP-6>pD8+yC^C9N9sHD$r_e9p6~Ves)FrE~-_H+L zS0n0W26j&v(Hc^)-S^MOkv!0=nCOl1*8i-T{v*3In8$e$(5DpK{ekyxcaC$_x^MVz z1e!~~0d($zl0Jpj10L<*RXR};cTj8!S=Fc&kR%SK0L7O% z?a@!v1k4e0_(b-%qTA{-(2O@RaJ0fe2=HwxeIO~@ z3=|5J<%B`qBKYu5d+TV0pQAK5bHcE@K#DGfF=1;4-vnrl7OPAaS~<7^ekOB)QuxI{ zX4Z_a5P$y1v#$>UqjD@&do*kC;qysKndR}fY`IE*JL_ddK`gepJaKP}_xg9mpCTYR zU(9-LeI3vS8_oeqV*AOCrS8Fb{R4bgKMiv?kMgF|Wm@nyfBkBq$ZInNsFD^y$rbNM zDLCB)#sdFm74cJg_zA2#G>=7sgJ1LXESeo>M(~k>u@eg~VCYnOELV9-WWUeicLJbN zhEMsBsqJ}qAn=0+AVPQ;Bk2T~=N=PK;)C@-_1i9hiIe?p@sR36H9-kGK!$!Lndv|6 zF5?CmT6<}M`oQt;{`TKoFZi?NHK-X2@_^+e*ucP>9^z^UIK=wGT;k1la`gk$+7pR>E^-KSe^gEyBZwBi2k1jvD zqx^sMBY~#(1VAJevfa+a@m^-e%eRD$}^&)?tRPAX%$}TcZ9Lmt z{bfp>=a^*IO!DTOo$*zjz`mGeh#_xl;~~X=)Cd1}pm41GqOi1`boPa?j1YC}^r-wi$Pt(qlIZ)129-^Ic7(2&NNX71{g53A}S z@!x{Ke~qTScyZED`o(cP#QrGJlg{&%eRq6B=k?XUmE-kZil{l5MGg%$}# zQ3%OvBt!NHBU^^CFJ*~{31i=~O!nQ_#*F{j_gWs;@B9B; zH-Gnj_vQvO@AtW%$MJeSkI?I_;RlA9*fS@QPw#V9Zx?3qYD#=N3QxH(xB`F)m^-@U z;4?(KmH6E>N<#KW2W_WbG0(e%yYt^|zBs@1`LCw^uP6SGGn35u`mTrn?vSl4B+{S-J)&Koy|KsCx1bHmI{CkO2 zz9f@PIr|S*6Ce9&R;Xz}r#&K(#rzn%bR9dQn6Ha0wEyQWf2jZtsPfU6bb^pS3sj== znX}#Ry)bach>euF5H(OiT;7=9yTY5PBZ{r~u=tgtEPYzez<5yOUp zL+mrDj94xfMUH~kF{?Ke(Mkw7YforfOx9*9OoKj^d+Yez_}}EU|Jg)7H_nGh>@*Ls zydGeI-r&lxo$t_cQ?X0@S)B!L8IwtVhOaGQ5DKA|lN^p`RsAC7rwVNFp)3Q%#f$&g zL|iiDku_q+Iozf<3f$5K~K+knXtT>7}G^OzMz*zc>Ip`_K4c$DV%nWv53 zGo9>z8_-fIUnK@)HxT|a6fB{;PHFDxJnf%obuh&cPD?ic(V4#ZHj62u{xB`5=Lb-= z$IkwMaC-bx*MY`Uy$s!5ahTiiS6TRDbF2CixQ|pUjw;8iw?IE9u)kS$%>Fl_!GF)% zJ36_B8gg(j5*H#qIHc7qRB2qq>wvq|*?PnLPkPHcw+Y&zx3}e|Zw@PQ{aY~QKZg?A z`8`EhKcB+~piRDhiu~(cd4c`xh;BU%dfEp1PY^TTP5ZyLLe^K~0ot!6XSer0cGTNv z6a&ow(d6&zlQg+Y43jw*KK4;`OH%pAh3h;!>nO_P8X`{B11O?{t1O0|-qkJQ{+HwD z|F<_>TW0%v(bI^t$en#ggnSb`A*n$Rfh}s9F<<*(e(Q18QKD{FL&$GJ$ z)N%HuH!!4tDCN4Jw-C<+-%p8p!u-$ufCS^P>PgU^IEk;vh>Hm?+3Jl8jQ>1f%%6ZB zj^QndC}q>FJy*e~4VJezCTt1+{MQiBZVWN?F9F>#r#AzjR+1KWI1pq?yw=h3O1jI{ZqQl+w3-D5)H^!>3;jR7hlFq>uM}s|HmbORpVTkl*T9VPd zc(X+sx;=Nv>SV>?GRW#bZ=L`BX_I3c$Y)*ygTy`HgTYu0DA8~9KTdSHtngfc93E-kp-y` zE^_(RKJj*--FfHA;=4a!1>7V8aa}B@3oAvDAY{e%Qw;B_)y!cDY>rm@!CMiA(pl-_c^)%Ao{>jtcP*pRXvC;ru+&VpNJr-RlCh=(ZYExnvt^FS$% zs`h(1(828~yHry_=w8OG>#hDv0e{^ZzQ8ch;L-?eML@jieu4*fAIjP(sP{?ZcpOgL zSYA_ndY@9Kakq!BosnIIYmUyu@#FS1XR2#}HlPzb72HgAu@KS|p9-+C^80JtdJPO{ zlBd9Oa>b)%$Nphr<+6251dxk}-5%qXsf-}qK#T&Fl_0_m7~P7Z>T3FGCb`z~T$@4i za1N=_Wkx!LzOQHu+*Q%94qRGWD^is1AIf+~ZiR-XOtChotjU!WI8XM)ac@HLWwmXb zsTMTZLA%AQGr(`+mlg>B&<=D~^uQ;F$_=it{FgI|7`Sw7uH`1QGrjc&s0Jk@mp}}i zvZ7^IJ!kJ;+VfY7%%Fyw_iGT4FR5-3sXG9M)cvS@$Hw!OCo?A`@YPr zNj&LU0IST|)Eqq#-o601 z!+puz;InXQLKPa;x=@g6ab?ufKWjF{H33)))Ea^9slE;5@GT(w$3PI#UXW@=)3FKe zOIJY^DT80lE<2rcLT(fx4}ZP61M-u4bwFnSYP0BbDsY?KtDo7I0kzv$I5uQ6Vpn&F z_|4u;?edrp_SrnerYKTCRdX4TRXBW=XSe27L*5Wi*afbk$VvBR(Q(w&Zg1rAQqC+( z`Q*W&)pRn(QvVnTG)CKpjm)!N4~INCOm6DTIRmBa`1q^Vk-p!Ez@`&9Y8hPSZaF|5 z3J$8ZP=kvRqXeg&00DY|Rip7{6W>!%(XCl<88{f2XBb3zSI`K{q1C+8Y45FOwaKTA z19|vkWG_FXp`}gS*g=t?*5i%!hJXzMeip4f!Vacg9|MrYXa6n66#2K{SizFt;G8r?Z#;+Q0_Yn(^7e6hmm{G+2Yv zzx<)V-N`_N_KA+S6Nn+ZKkh~35Et)JqI3KjR>0A|Y2vBN*@{xhz;2{G z6Qduo^~~i)>E==TPN(`jLLh%8Ncykb3cWR~2EKc4PFN-8@6SgWc zFB_i_fM=1PDQL`UVtutBNulgfBujWJlv##@zuVnwA|+pG_CR&Q z-ic%L_h#c62NSI0x;y$zjMI6!-WxY;L-ytD&hhNXP0vJLm-9{SRFjc={j%cZ`(q1d zS9-i>ynu8d0yoc^3nzu)CqJ3dZT=1qWuc12SDW4G6sDwF6u6fi@c8H$6li36ir1C? zAxL8@KI535`z>)jZw)6DS}&-|?_%#{m}`i~oGTSzP{33H>PN`5Zz%bi_^n%mFXyvc zCxq9lhx$Wa>uNk(!{-^-f~E8V`z3cm zoFi>>(&)*N53P-DaKo?c4;>}vUemT8NXJU*pyyJIm~FnD^;<haKW)?^z+w9Pe9K zD$%R?m9&0@MOqp{u=qI-|EW3uo9<_`X9S7UR{7JrlAA-L@we^M9?0B`@TZ(w6aeBU z)!kD}r6QHA$SE+8RZtvEbJ9_R>K8BAT3YuugMGWw37+kgqme91cP&GPo0Nn<5n-d# zfsyaRdO$gWg6(mRM@Bf`#Uzyrls9~Ly_}eyj|e{vza1F!`d~pv;x2#d>6H*Fd~o1F z?nx$vN*Mkvd%Wh%U1S%*gUnecKcEq4+aGu!XH2X{Aojf4w%6i;WR+x*N|hw6ft1&Z zwd$7u39bcClrkCCqKEA!=TLFPXD0*~W%+6HkBOX|PVEWpLjxO8FIyHu{y-cefxxP1 zB~K(eKUzVc7v3j6DRO$)dZtx+m~2btl0d$4^M|)R>FIJf%n+CjWOpGWHw1D*4j|PvrXn&p z%rmFNIX2x%g6V}+)EJP3rW!v`hc<9fafEDtyY$!2M3rjc2f0DjlC$g7rQEn`z}7f% z1Ym|aZ@Cgwu6wRJozz@_R0=YdX>!g0-Ob=OlCk9s}bgs<)o3iS>(VSy-- zvca(W#x(li7$>)KE{q;ATw}{qtTeLuw|pr>>OtJCN)3sVG@EKjZ2*u&kAdaX$X^C; z1G?l29{V-~$g-W;nAQ0QACB85D^V;dwTsW^{t2}RmA!6iXGJUusDOC)p;q&7dEa#@ zFf`+wn=_tW8*0pU1-u%k9YLZdK`~_#=7c2|2CAOp$HYzlOA*hsMeF2vEywL-#7MpyJL`xc*04xWoDZFft$dE!<(o5Yv?!|Um2bAR%1cuh> zECySut6G8B)@UT^utoappq9g(lFLc=2i(=j)t>?x!fMRnUAzFh``fIA*{%W z(dOTRM)o-aV5yO(GBeLue_9tOKF;w|X6WZY89L@~dN-bceQ=Qm=$A|-b`klf#dlC; zE+(Y6fk`~Z=U62 zE8u1MX?ewk!W}CuLEBX#DqqQ{$X5T1)+^Ok0!#!!`k7no`P|bylW=Zt~ zMHw#X3Yj2(?`iOnfHiq1CO5tbUOO8oetiTw6*!rm&Exqrrqt0^YpA@F0wbin_OQ8{ zs&h~~EGY7he{8Idqs9Z9i%N=H zHFrS7syWyBHWdkqY|;*H!F&D4;6R?R5-qhRqh)CU7F}8mPOWfaS2*>}yRLYm{hGn% z#YI1bm=3b2E3hP&OMS$|&Vr5~p>n6HX?E}j<*%W2hP7I`@SCIT334M9%YYf?dq<#l z{oy0xDSb>im0RM7 zmvvO9hC3umAGul;_EE-ji~@tCTCZTiQRZi`)H4mRxoAPm?2E$queEx5Ge@Fvy>h!q)|xmgm2~)`PEhrfsdphZ_Ot1{UD-2t}SE@MhNNlm%&MXSk;nzcQzca&XQ zf9VQ18L6FAdMie)Frl8%6p0=(=i^~B0M^Lk>{WSW_;`0Ob;+{oX4uL5WSw|nHb0$c zR!?p|k;N1(Lr$7Llo=y|wRTATMwnE>(b)kw7SueV!=!%?9-ZA%7l0zIN6z|}8;461 zKg2y6`J@3bS%9X&o9VqNX@wg$)Oh9ixx8@Q5C8PfyyCNkzS$Q^d{NJIBss4_R za{Y1!b}T1o+AF3n9180Rf(XJ+FFhjc@A*+bIY#=vQXpgy4k& z7o5Iv1C#DRm!z9AK;! zz=oOzJeps3dq5W$f1EQFcB*D~-&a|_%l~`KQ`EWiHxCt8)=f84S*B0b58?h zKtQ6M&eZ)wpZl$=VL=&XwO8mnw?1|A8ly$~l%4Fy9k!a=2UHR&qgw#*z?*<9VaX-F zgg-pw@B1{l`Gsb1Sm@X9=m3uF$Y!Ho1L~3!%-+ise~sDG!EKo{6M5g5!XCp>5AQJmAyooPJut z>JFg{%{(J|4B@L^*Yc%LUj7R9T+QOQ-+$bqc?wu{54(30%}ay>j841b3j>>32JY=KFR&bl6QJAeO+>jz6hZu zzTq;_w7VRl$}rfkX&hC$VrNzSh>Tny zqmz1a>;~o=uzUY>YCv4nAs%%Jx1H{gT51TPY@fa_RVc&bW?RzXQ|gntffcR96AsEK zO*@u%Pjm4LvKBZQ;P{9bHnL=w6v8J!bXJHstIVEKhnKP%V1Wrar?>RJ4>qvB>ol*@ zRUKfNbs|7<)EbH#FhHq6F88F?O?;GV_ynQxy6p+^q0U=+Up@&y(l!0>40jd<2-gvv zY9!gv%vE-Cai!SqdCkH3V)d%X;?*&A=nHJ2^MZDN>;sn8YuJ@F_lC zYR$)Ak-d}wVTfX&8&#mdoIL+j?jjI4pOvGOdw+b*0PmV~whAZ5{J^4I~xN zUCY{8v&;}$Ii&03xbLUr(kSM8DnH<+G1E1Gr8e8FsJ6w+IZra&7(#+Do;Va%!g4r! z2D@$_yERT^PfbrM81F^S5N8ezwdZ?@`G+}OEG)u%sw{p7Ze}5uZ__&Rcq>_>U8WmPp>E%@Pm(?C3yIT%AFeY$NcEm!RVpvamu z%5$5|TP-z9ApnL`))`YtXF1`bBZu=5&=%5$x#SQ!;}thf7~Q$G@a+k5<(&yvhOJe2 zWYPVjK`VCfVkOI81)it)`X!egPMJe!j7y4vVP713G)KYG_;F3V;Y$4uf=XMSkboM4 ztk7ES)0@UvDr+CA?YZ*kCDfW<^*HWqcL+&X)&T*9rEuIMK= zJO5Nkqi3Qk2RgAN*tGcvEC>&^uCgBEkgw$Dpp-#=TMPXl9|A=_r@Pg(v2 za{(%24$tpADTL?}XC~)KUY8r#As_3a7CM3^7d}7NEQXGCrLyVtd%}f6YyvUYMek>M zr?ztgdQ~_&7!}D9SS?t-EGPLsx zcpEMwC{k06CX4Wq<_Vsw0YMhk7|lJK!#mPNqtTzd(nA=KEkDU;JB@g*^n_QGo0eL3j3->I=~-|n?bH1Ce` zW=BPIb_(*m7(BOmB*9S)0gcBBH1MkR$A#P33tw$FRvfa+AP~1uCfAZ;GdW_@264n?Kj*`rm8Lx*)xjvCsvj-O6;*|J zJ&Pde&FW_~%7vnJV6S zOi#W~IGT=tWu3LN5V!>*Pp&9ASp*InIMp2`bu_#PI$(&A=xo_c1N}3n-QJnNF%mK9 zjkYZ4LK2?f1o8sXnQE6pAhVCU_~l_`4rOSa;f=qfEj8$P@ROP2fp?Nx(hW!4nmQr8 zy{0~APw55w$utsDb}-Eo^S^|LcJqT1H%1BH(wuU#KQ?TZqTS~(4(Nlj;hf5a7PQrh zJ|rfr^RAfE(wML??59Ajd;>_R6zmv7mDVI&itlIT?T>-wizY;hg z)q)Oe=#Q(Mq2-q~?Rqr6SeMOLQ}F>cqj$6QB-QRP8!54%V34kY!|t_xX0gZq62?UC zpaU%{@x|Hi-^{eTTKa_m-%Zhy{N8%&THDG8n?QZ(o@|%a1qBBh z?X962^oYS0cEscQ;ZfWhxt%AqPn<0F%bj;7O*WK6?qiMIa(ng$`#0X;La61Q^5Lr< zGC}vFP=2Qns3Jk*&%y;unqeyg z*x{HB+NAoH21^=EG6$6{df1~`w@Yt>!?n5t(Mi3Iff3e1k{_0^SAl(NxZ0A&MWf8rEro9I z_GaYI@Pehuy;i|3>lyZL1-sn}ysYGV(oIBu#hQuFQqp_#(_tq*4VA7Yg)(}5-(8<( zgiSFtZHzbDc~4HR`3P}mHLaXanoj-=d?X>BuoiW1$i~n7`)$%6a%DHUU{Fp3_CLtI#|@b6y)Rz{QPiNPK-P^<(I!L@AM-)M3LMd3Kg{Re@h-fpO3R5lwtS(QCb8 zV2*E5Nul3VCP8IK5*yH0kUd6#1o2wL#hAh3wVYx&#~jLglwKQ4f7qD67+i#?O`)+s$Hq%t%!apd*CAq6)WAY7k(IjN2?6^vf8v zAb)<)p_I~H`2_oYh0>fW@0E+BY!=*cZ+Xg#(AwQ`Dk8bM}6*Qf)pKBfZFNy ztB>&-pN2KUvEH+U1HQP)C)a(!;xQ1THDYa$MMnM|miYKsS4Cxon+39F;ajK$HH7Vw z88*kJoy!Y*Bcn}2;CR~YC9+jFJE|RKa_0%HD=u$qsJLNTlgT0%ZkI`bbLLE#r-=MT z-6W0uka9hT@1mC*qnEImEYmx zacA{{vr8{bAg1={W2%Ty3)8q8ErJuF{=(2S6%|cg1kl%0cl=Mw+*`>p>Zb6!5IzPE z^G|-O0Px>v5khn`H5>jYL{lq3Rkn~ioV=zqT1>y*q-$X7wz5#ULA>&TOZilS>IuXw z4&X>oam#*pn`@m|dk4|woG+s*E&NVJpU;V;6)jkQKp`+OEtJ;WKX)bBs>wG8I905e zF@@{ILWdaoTVPGX!*@Z_Twc1XJecyF%Sia{Q#&q|&^3d=L~b|qqhLM#Ms$X(4S$M9 zqvcIV318{OEBY4+QI%O9E-prNT#X|NVHY>~p)(C2z@JxAP}1@yI~XbPQ={ZVNZDmf z5K;BXa8AdyX%9QKBIqjdW3Z2f1^7{KA4)jEu57xgprGS1rQt;EIh#+YY(}NnCdA#f z6eKWoh3) zRMa0#RLgN5oIt6o6@Xyhp$WY+ z{c1SEviN)%+d?TRwG_AAwbre78U4$L@(3;9k5`jG`RBCMfDlzltH+kB^&B4AK;3go z&CHhjz4+1A7S@ggH6t0fRlk%qTg0zKf{N{3&(a`ejI+0~yY1V%RjOeA9*Dn~=}&`7 z13-q<@Z^J3I&ZC=<`{Np) zq!@{FZg$r$Y2lVqV+)5e_3ZShb~0vi6qhnjh%d|| zAza>IaE}CKp}S|XDzmr#HJSX$j5UV8a{t|@)9#?3yVhCLvJ3l88^RP&-#;ZLa%pwE z=fBMlPf%bQ>^W5@tL3rn#ORLOEU6ZT0!^<~Ja@Z#Ynm0Z#P660$%#pDo#zq~1m}zk zM!s1gdhbxKGqPRt$#qVnPyL*0AL!q{WRfcu6O__ETIpd#{Gu12eBw8?cEB@aa!_jAS;vY5L+` z{$T&-moG|dh9GR^6i(h#wVQO0%VB6llOuvYp^0bxiU-;Vb=I^LI~{r>q5N5tM#BMa zlDJP|D%RHo=F2hWYj%Ny%k&zCI_c%c8fWjv<=PbU9fK9=v5?V0w5dxXhsW>H-QO2h zoA#>k$h>fSRmd$!vWAR)@UNE3cYoB+nX1*LYL8dIPWI>>< zU)FCp^_}{TEJD6occX>iqpO9u5Dxb-q;e97RuapG8x&!!Y z;+X9XrAayq!qv`?4s~GCZ2C4>@-Ro}Nt?Jqk8bgM9mAE^d))Sl1*k8;X6* zzLmYO_pI8jiWf6FEZfX&HVzB6;0_HuRN0zW#2#W3zgW=K-dTGB_Bmnpv~_PEu*1@t z4a-jeb2)9{s^aI+lC_x*-O3SH> zjuK1SkbP@=JPLjx%A$0C`cJ~he_#-3H7u-@hwO~MgMqHOHb|l)|T^k0-nBLqh=P|T&RtFO$BK=RL65V zqCYR4ykMvor$Di|p@wri<}4374YEYnFzR2*2d(xx#Fg__+8mmYvN5^2|_f*?VZwl#9aa7xbCV6} zH_gbur9@gpSL0YFBKq6S5J8tyhGVNpJ>@lwgDZo0amVv|w!xh2v-FSFZOxnC8j6mC zKNYN8aE=m{s$CaaV>iY*+R;(qB==)cN2qufRjoZXdR6PCgkU|zXFp>G#m_@l>~bz_ zY(H{q`O~cG9G=^tUFyLGH~b^>Z928DCQ?0jgf+gWKz=w*b~GgvXQ?j^S7|kD1U0Ww zcJeRm=k{G6QknEJ495qCO+bg&((GBrC1;lE`_vPEyLvjhjjTHNI(O07H$Ql}D{0*! z=# zi~}+5qNW;zoIG#T?CH-n6P$4II@4Oa6RSutwLzL6Ip(2>By3yvgu^-n?e2A$A%*#IrR4$=}nI;Oxbl)-#%wrHTkQEHuW8TIO9Zu z99eOQq~I|*_J0TY$ndn`r$m9k$5@0EiU zRwG8^OZM{VGnM6b*Qc6%L5hi7zb9PEFwoOECnw$1AlJQ+7C{y3nYdhcOlOKYwte3j zMYQ#-8C0LuXt$q!iKucMnh=pSgxAr;?n*f-+1+_dATIExA57+mq{p>WU{?2giV$1f zDG(_Lu}Q(4gM_CP!ew{q!v5oupp-<8Z;C_Lai-6R9I9&(YC_3Dp8K!zYv+Z}4>htS zsyc2cS(jl)8(p~fBAn(36EXL8Gu9I9YQYw?L@UHNb0!ux@j5W{XN_;G-f_>Atnt{o zNgk?SSdIo+WhGKDR%+H{mmX1-%Gjy5?`360n6Q}P{B=Z7n&hH;t7Lc$lrZA!_d`*l zyn{a`#iY5yeC25I1pA1~X06Sv*vG-#*_T|DbE2L@AE|q$(Vf7)_lO)^_;0_Ono6?Q&7!PVJsfqlM+-Y1%Pw{Pytqp6=WJ5ga1ibu zMRl$SsNYn^+kN`I$M)@4Tgh3G)J~V1>Eo&_As7A03KU38%Dv;R)FAj&-AbY0426x? zY!0l(@N6`Fkg!{_PY~tPbrH+IxKtKeS~Jm&QvI9f;~P_GI^q3p5B8wOKL(-BisN!I zyLa2U7}tA)Ek2h`RvGOe2;Du#o1ZZUKJf=@a!lYRxuCf=(idl22fscu}5Mbm7Xdj4I2#y*T>eDmNIms_S`mRUG}qWN7G^zg3L4N zNXb^6gKm9nhyiMH|6!w{`VEmV6Y*!V7{AGo!;W_*k5SC;P1d%sT!lT8?Zxsg^|-(>i|Ex?3Mhi2VlUJ zgxeW9Ds7V8Xyqs64>h>pOx`EwVK+ImJ3d&9>_4G0Vn80$#3yy$Eiu>fgm2ZzQ2anP zp@KB;aL}^vKOM+9I-!ju$2f=DXYulx4#(6vhO%ED1&Qf8fu2UnMce5M0TkTLm$N;; ze^8s?(iLC{*#XjJ>C@iC+JNff_byLdZG@d?lYS% zW07AqWfj7J5Mbe~@<-mJ?Ss7i!^j#T54UnZ%;sKvZ&7~8^2o$T%eC81bOQ}A zUs+QbFdu~M#AFSvTOx)hUJH}Y!a`^Kz}}D@%p1Ns{u<`y5K^;L;KE}0>}cKpDn}`w zg>3#_e;HB-ZAeQi;wH0|>30P)ek5vK945X{vb$_2%_z9#{})8{k@&J6p__p=X_yQ# zI$lpu*eG-K_2{Jycu(yin}gLez}#{So0uXQS7@T-wJ-B(Ud|!3s8}>R&*}m=NBBwA z$&f-8KSpakDJ3Mkd$BjyrSqiGnVqN;azE;)U-NMg4pf5TDWJY)%9NeOl6z1^gx!{Z z>o(VG|M~c~Fhu@4NR{$coc(^D;$h@?Zsy{uPsI+rmd-(V4V>M{U;mNQ@O6n5**5Z_ zl{&EzfB`##Eg#{0^mr4F^5V~q*ww1IOoMkyg zvJR?;baYPlK1jH&5f1QLT3O1n=Ps>=S(Bg&58wq>&o-(aC!I+Q0ZFnUL!?&89y?)N z#4aSSKM!Jebg8uT*&g(*-NLUe0HE>B<`?jYN{=%&{6km%86Ylk@VHSJo}LP;2sbbw zB1eSia$Ylsa168_nG$hr1ysn0JIkm;n=Ha}i{Wbg-yxq)vOJV@GgYd8{-d9{Sol|v z$Kq{H=<=W^$IwW`Hj=3|H?7rb-GsL~5a3Ghj&Hyt5)vjYxNu$$cuuw+sW$!>eXqPm zm(eCWDUf@nOo1*Q^+sH|YWoIK&KiL`?>B_Qf~J>KYq&GXE5`BKdPnQ9<4^j;{ZyQI zajMhCC~N#FtGZ7&@xxKki*$j!1!szJA7txBQ1VUP1LK2Q2-%t)e?|)|_$;5{*O&Xm zh>9$?_KBRHQhN8^irTCEUOUf)%G2Ylm#}4hOa4F~>g^+|zMQoEIaQj#)6`)S^7nneZkp#fxR&3F8sw`5XHR>9exf?tS2($q^^YA;^bWV#%OLLxkI2FkAPVU zit@3`7e1X*J#+4}6TZ)9yesb`26Bt1lZP!GJCr;rUn`Ua^vzpf`%ENid3A#=H^%Yr zme@7CZOVf`${QMBxM>m1mmwpyyDZbau$*>^*GM`;n4NLrow4fR`uHVCIUYHF0H(#f zb>J5inGNH1g|$HGQcUdmeW)1Mq-&$wLsl%F6!5&v(&2yio~cp=x3`*)QlvzS4;=DW)#8zP=UP zAS4@m^_44Yk?Wh}dg`Yv-xwc`3zw}=8D4OfS4eDr1BIOK39o5aff=y(vyrQc1O>|| zxjEfO$xVvCwe);X?XT8F<{maRS`_0(odTIi?}>h+t6jw>YKT&xpt=H@~feYQUPfZQ!yv5m_Z@h9D&$UvN)xgiSi#0 z!zOZyQn%MN&(U&m1RQ$jc$ET{a&HWr!>?0nJw;5uedG=%AONKuyyFG=GC2SHr+{ufUw|;&vYZ|uDr{_Cb*lHQvI}Xmz|BCwDv!g3tr8SveS(uWW1$*!`nxASqIRwN3 zGbGt6OS{>`g0=H!S1U|U0!dkj>`_4FNK%iZ#t4?l!?lJ+QzsM->Im=)RoDXl%m|N2 z5U*Vi7GWsGu+D3P&1+TZp{C*p;hZErQo3ymg%|(u1y5Z~bz?Pj< zlZN6O{c-Pg|C?bGvuDU~-bR?+)x7GTucqe@T+S+$d-Ly91PRqrOYxOmVmWchc?hm5 zX6~OYpKrbvNwgwRYc!^gT*kQ3{Cr!O|JT;0?^`V|oF%9`srXn9fzwUpT;wUrHkkz4 zdzyiujm3l%=PdY0FAoU{=+%J`Rc+s`k!D=U@{Pz( zHKLW{ET6ccMm~cq9HxMm;_TwA4ete(TSDujYx>$ukB569dUZh0=&Mt;CW_yk(jf6| zoO}Z%jmdzNYdlX9dbZJf<#vnPY3M;e$;@YKw}pk~85avuMkVzNH!5p2 z(@AypM&sJVH079Y#Uq~L+?O67OSo?4_$mhxrsa*3oq}(=B_XL1(!!{ok^B8eO*?;zL3yw|N4XABvAkhFahfUtA#hPZ(EYQ2v|(BN zmz~Vn8!AkSu0`rgtIHhGd8;ozNVxd1VPE7o5ERSXpdDs-O3zSHN9duRmVUay4o5LNy1ODE7Ip8qs+Ak#Qq(ui01Vz;y`Q zryIaNis#;xisF4zVSo2y=dRq_77-Z^9fTirzH_Y;SIaS-mlUP7PVgj6W>emV_0tBLZigX7ZHow|wKs zq(+;Fe}6VSTV_k@-$S`XOUx2_l@86yA=zB$?+y#9Gw_9tZxRG=@~m}HZ{>g7+`I&o zPR6d%)1R46X3pSNPuoM#1*Uo{rz5XJR9>$wY9!9lpCiA$nx^gdJqMTq7w4Kn_z3qO zZE$69Q_x6djt~yA5+d(~Kdev1kAAL-_X})vV|vsV$iZ%&gFR{a-BaRd%8AfOQ6Bo) zOMadc(Mx`WwA8^qKq9-_ci-)86Ck++l$x zj?c*iK;EP+&b`H{y&v)TeA|6@PvDDiVBLuZ@}cj=%jdBc>0iE5)so7J91bd)wz0&{ z9dU9Zvcjc%R12K`^iW9m%?C)y1oBkq<-ggWE#)+~@HDl=e+Wtv0|Tc{C+&^E<#x{n z*wQ-{saNR_2@ihuTGufjvm&y5A{lM2vBD%B{I=Zj?O9!`-{jG9R2g4crcFw@p)s5e zluK`WxJw>be0_Gk|NWfl4W%S!SQgWHU1l=h%*_TMvASL4ec9ePrQZ94`}8Hcm3%mL z7dDyl(Vf&t>CI&QYhs%L0U2v!+j|Q(gVSrQT&A_|w6W6i76Ccr*ByAGrc{n(TBjd+ z+!r8!B}vf2|gbuf?GKm;3Fr~!m{T=vMWn{J~Hd^S+wmOn=_D!;$9HR5EO%^ zuyOF#A%t0pyrEFR2%|&W$IiM-`edS8RPhpv_1EoWqdi|H+sqRLocSx&uV%6~WwMY( z((l~)*8bW7gO843ocW`!i+^){O1$kD-zvuP&sa*=Pm#0HyIzX?bC~v%gz(n zx56j%YWG{q)}PUNX<fxxmjHwB%e=t$QJPEoc++is@N^wJ6i<8D)Ks^b1TH zJ2Rgo6Wj_pi%pKtSlmwW`XdNpx4{>@wDvwN)Np`Zfu+)dTuP3$KnnhqQftSnbAAx#dpojFro+R)W%r!X;JOpLvt+b+2?vl*b)Tm1g=ir$!ip2^CuDL^cN zH%6*Hfk}>cfatXo;3TD;nVTdY>e)-llS<9O&m0nY`x+3&0S;G7}mggI@U6tgs9v8&5B~5 zGNyQRUNv|wd>`3eIbO2-a!7VKr;%Y?Fn4l?pY<%HRCu~Vlgzi=hCP=2(DuthK6-k# z-K1$wj>KwWtL+|=)X+Xz+@zIh9Rh5&|{BW&(VoH{}Zs}2Cy#rsG z_0E=jD4_}ZDt$@fu*xTtNOpcC<$W0419Tw2=d^cPKsTiX&D($vv7)P~6p!MFLN;&Z zH{*N+plX>NA(qyBjw7Ufj?3dEfgP z<2~d20q6Y0fWi3eeSNN4Yt6alG~Xf{`Ajy3yK6q%UBGsoWRKj}34ORvXMo7hc&2{2 zzdAPn@+|dgn$}`a6%4gFUP|b-cOf*w_ond^BPW6dnI@^POe9crO1cQ7Kl1mMuB*ohQt+{>X~eR)6$AIO=^Y-A(VRy%NEKm zS>%~m%yHDFCDjokgf3qiWFRZl_`8hdyX6lISpU6iUw?I>xV!?>-q~MZsFS){Ow{4T z+>RioU3?80a-rGQNuFq?-V`P#>UB_A`lG)~vbzg7niFJ6l8QdM# zwUd_bO84`wrwHvZs&Y_*eJP=2WWJh4%NiBs(jt%8BtU3JZ;v^ zVaTug$d&ij3=EKc0Y;g18lev}^&87U{h#q%TZqN~yrU&UPb5!kHvR* zpqXCoV88U0(KE2*LSa>Z%GSV|K6g!~$x7;EpIs%;t)aNC)3>gkfyi}9udZL~q^5Mh zqg|3*7R#vq@OiFZTxpY^yItd>{nl!)2OrL^6tnZ+5W+E|bSZs4v-k7*e__17vk$*1 zG4g&M>>zv}kkY9ezAZsPK{inR=mym-a z~3lD*UKVt~*peB6O3?NQGfXmlq1I){iz?9bF9FyB16zFbP}xZYr$i^%1%wJ_7iW5E%4<0$5lp9dA56vpW+d6A4g;ojO$}&|rM2h?~Or zUQUZN3^HNLWqzYUPG#id1Ccp`SIYd8_s#RAt*s+>obgRW`$vnZw`Qe_HeQqg&NrKk zH=f`d?=v&Vgr7S}kms5EtycF($c)GIBRmFu2rdT*a<$eNY-gbvCn*0l zpw_D|bk0IJh4Ot^rN$=V}wx%wio=|y>bY#YEPd#Um1 zEqwh~3aXd_^aB%~S9HOio)gf-V9GQ0x&_d(tEqsGp(xHDO0I z#Gj?I16H>PqDe(zn6b8t-e8unug?9?n);1saN3f%7gF{+o%bU{j?qm1(olTu?9Mpn!!tS!tz?%vM-W0}8haa~5qQPE&!@bQKA zpvy+6Ml+U>*gtNe@c^A}$(K)s?c;|$o}YY+RD=>3?r~luG26v@Yv4%4haxpqvYy|> zZ6e@UEBmJp*&SzMBKXo_0opMwvYOr?F8?cvH6n8(W7t^a=}Q8iPEA$;LGVQOi7l2wMe=Ln zfcu2w{&(F+#;r`Lk9)?xyx;lhlZm-n{!PI{?6u8a*;ZC}rnlYQSbo`T)*!%dzswz@ z%x4G{Ie4*bNviWDQ9`(*D|D7)f!#mo>r^cANQhhp)N^6DEU{YK+JAXsQR zPp4H7Ey?PrxcLW2c30Dr54Vq;Bt63zGNATG9j%Et(2C@%_D^AMfY&O)oPsCG{!p>vQKOH9{40t@nK7WuzwkNQK|uVkL1MBF|Oq%vtMFXz@C% zNsrgsl4;|^df%*|{+TFLUz~Tm)RmN$7%w-HI=#DGOa-Dci?^Wj%Ji1&tm`M#$6>s?8`w4n*}aqERb^-^wq_v89#o|F(b&LCUg6V}z+qpWlh zM#wps;kIX^8rl_(C0qL3v7d$Li}%1vmq^Oaq|0kAi#;p$?~y7Ryzx_ z=(h|qYuC*8qE*d%?aWxlAL}Kz?*V^ZU)bqT#rnX|&WFN51ukcf#(lMsUa8L}7Lt%D zr=b)s)4f0Jrb8)E`AXBFimwTFhbtL8E(gRn%+Zk_sMKU6g%_S-7mnFXROHAGoo$b= z^J|(yizjOeOiOW+-*bzW#5o_M!r1hhq_3Sa1QYR+^u6vTC*m$6Q&ccY08PBgKkV67 z&tdC>&0^}-5B`%DRsHS;jgSO$v~9G0D8EwymhUi%jG^(^FJZEZpS|<-jzdZ8Mr*o1 za8j5sOz!nqpS*)4(z?Ix9Lvzvt>-%+P^t0&b7apEsgf5Wh)IS zjxk%E){o?rO=RU1)flL5)tOlur{FewgREVx>NkB0i!}Rvb)+%`@wf1$z4pZTo_y+%~K(xrg zcX!LXZgyx;4<9s^15ZCS!p^u+p>?KiByqfZtJ7>Z9trPpG*y0z`X|h=+ZyUF{$-m zNVN995grK8`#kz>BRLOR!{%z}6ot#T9?~yG%F6ba5kAD5G82U!KIHBC+ocIrg&Iks zsQIiuZ9c~0>i38*eH?o>!N zx%aF3Hn`idRjM#iLgZIBhf>Xiua-PGy%yXnEzS#`M4k_R1-eMM*U}L5%*_j-;y`C%0wg1sA zN&TVXDFvCUv2H%C65>lZiMLqbhmV8A6Q*8Wm!FoNX|Fwm{#y&+9%e?Rf-RX)pJ?e( zWe5H>zYe90(XQ3wlKpXcPwi1M#K)gIby+7*F{>gv&?Gs^L(PRwaTQT_+$l86PnCTe z3@;Ujs|)iHs~2DQjxIEpa(ihX+Da1B#P^MH(d6HezMjguyWTAUE$&X-#oDzs1LV{A zFu%jro8ft2D{8v*3y$083kOe@c~X*w7sLO4*N?B zj7gL4xWC*Vt%thPKdMMmVq!v`Z$9rN8ez!d0VIzS>WXKm-}~}ou~4fwIPJ%L`F-;( zH;LDTeI;yIprG-;=l{Q!!3^bV=RJ+_Ce86|<4=F|Tus=h(9>gww;$hh{w&J8({%bq z?kiilC(Ap9ZmFp@Equ#K_xVI9gK0w3L7a)s&7=kr!4j8Vh$y#}tX zSi!;aa-n$0@u)@9dXC}Siw`*V3h)1Z#MPNZP)NN#bDexn#;s$z+R7uFz+8^*X~*a{ zo+Zn+Z*Di019_a}|I9U<1UV0)UBGPpI3a{KHE56sy$0wqeHky9#A>tutNhP9qd1zc z9GQ*BBS7bh!NvQeP;0xmkUnLNEB5g?Cdc$RvMU0?(fZnX&c?cC&U9C&l40`90-{@R zq?R-opIP!+SD7F8Co`hcc9ovvKa=p!BKzN;|DWG7%fJ@MUicgvK16$>KH6vgRUUPx zov6{iSlO2!JsF;_1kuUob2hiw|M>F%ev}Vm0C-6sessiVvL1P=`8NC#&`8aD+>8I& zlK=C^TOZ0y@JMH?e9d=CflnB!pzoCMwIVIt{?DuV_tXEGF(MRth%VQ)Ch89Sp&3m+ zT9aS3>;L`fkDv9D9v(dMQ%^uj4x$rEl<3V*M5piP`887i&qFBi`DX~w|9=So-<^fG zNMau^_GUIVQf=f4Ccg)gn)17B$9!&LB)tOOu!E|=(z)f~-mTKOFVb{-%w)p{nd}W+ znw{tef3dlue=Ya7%wYNTh^i{lfl^=oft*bk_C#OO+G+1A+a?1L?2KeHyUbbhjOQ!= z$X@;WxYnP&@?kgXPQqpKCwp>89~-v{VWamj&YHZMsY>ZSsgzL{*>`iM{_%)w~E8&~}rDs_UQs zFsW{RfJ06K=CX9sr)R2)NH^QgIwUGxsq97pFd*G9q(O0;|6rPWH?Y^_DDNn~OC>ju z5Sa3U`w#gChf}YIOE1%Qe^k@?Kjo(L)2oAF+noQzdUB+|$GR`qd4HB++_54*zt@}H zHH=W8doYD>;8F0%bXwPiQ;O6nj)r_1SZ@2f1Bn2h(=pHzMm(_ABSV*NTwq=O0n-UY zm^J%9BqKS%#l#uvsbTE-aOa}hs9>#HYoqH3lp(t>T%!6K($@zPl6e-~JLF)VA<4oX z4KQH3Xj*Wnp*ve%X#Te$-28VYgg5w}l>$DHbau@B7`C|)C8m{fkMJ~mXnntSk$WJ4 zwfcBxqS#2QnxE1-MThEb1dC4DFVpe6qRPQV;EmnOjEqkFu}6@u{Oe!9cC~JrEL2bR z^thqTHrR8pX3ymYrbPaZ$|4)X>6XGktS?*j0Z8J>ho@U6X;oVcoVQfMdPMG{U*=Jg zX;hkqyGmVuK3VHC?GD@CNYtN7X=t3_3V+4LO`<6Bw+KwWd7+5f0T0xZ|IbGGS`UpW za6#n`C*t8oCYflrYTS30*=7iJ%SJ=)ZLS9~^nux!^PjTsrlVP17hek1ish;;CSz9C zzJBZq!8QF;W&q*-JF;g=zym4}K&mlexg}oy(^OM^b0WL_9{imzy(@Za}S63q(uKSs|_p@#3Qh{3#O>fU4P>_g}zgdl_476#0nF7JLX1{TldHcqCi3lv=s}V2e z8G^Jk=f|ktQFA2YLK@m~HyBKp@d=Mr=hMza$$D46&Er-C^Wx%w8Ho#7}G6X5|k z*@EAeTy|%>+<_)n^d{fcf!krS^L~UJuj0%c8bgfrmBpY&<+PsLj4|eu)H};@|8m@6 z4Bz{v(_tQ-MF&}CO+{f)$?&iLuyPA@8JC%T7X|jKVlj_a2l2G6u!zUgV<@6tKwcQs z8l98u3HgmBeN3UnVaOqwtuZ%BBBv_SsAnY4=vdEi-eK4fB3$){o#H1I*Uoewj3jgR zOw3uUH+Ks6aa$3%X7mlG+BA&{-X4iL`?3(Da-1}~EON>N z6~X1W2jZp9@*Ywq92Hxd&SNj)nUZvxUwqsrr)>S5V_s6pm`0Ses=i+zXv6mrf9M~6 zzPbGC)yns9i#90v>YmHBuk#SpY^i!iUQFxT0)L+a@;PnW#vvV7lhP#@^ZnOqH3c;} zLm6iDBV+FkCJR280<8)K+^!7ExtjFvFAn%(SlgVY^(+sXFBiFIm)f8y8!TGcvW6KR z8-$JzcbCZ^#g*)K^1m@Zai9DrJNZv2^tJ_4$(LVWT5ZogF0yNTE zw8?1jdY8S=kLx$jUf*4xSLT&vtQooKmlNqz8I!6_YT)ZR^yO@nG(J$`-MW|23c|8+ ztaT#9T1dYv`AqG&o~+qgU&Br}=cw&*5YRds&iq&BQjb@A=DtMzx!IrYomgyc(cpOa z2z(v2ErV}|8xK>cBIT@lz?YNv6S}P09=i)X$VbDW^RO&dguN&SVr*Sg1rx1$&DT>a zu0V>EyV7ik8%(bGZ;_uUWWC7JDDeK=Nz=uRq47D8%g^op$D)FGM(m0;n7%{~V&t!U ziFUWg1)Qbn?amVQyRef`u^g|W6@9+~4T$&;NOQ?1hWkXcrk8QMOF#%9ocgVYFVVmV z%d~t%**ot(PJRC14^(0S=%F-?j^32EGW8i3=5@70kvAllY6rR?m#-$||153ST;bp+ zykJ#16w`k&x@vWLBFi?j+6gRsFQ!t`ZiZf!w%U{pZ;&44YTyIU)IxHPq)gM8k9&2c zL!@qdSe?f%j0ljwxlWdrkb`Lf3o2`_eo3d)#a$du?k!18o9;I=* z)C`=ZxWr6MzF+&}7;={vx?-cj9*onq>)V^7;gNvlcaug zCeH`Aw~_z=Hog(Z(64)R9HvFjHJZLeSLZuVi^Qskb#ZtA*I_4#ZMA=ewmxZ(i;M1x zQQnXypGjUlz9{RRQsVR4nA`$@p%rjvg$F->V$kOM?P(1EoZaB4)GKOu6xjsU(CYUW zryg71k%vAshp_x9!*;(+cR?tW$Hxc`K|!g`%}~IMfKH zlDc_!c8ky1>({|_#I`_aS1k28sy|R~(yuj&Q<K79SJGivx~ znk9-Qt3b!Ihtw!$d)Ky`PS;ErGQ{XzSkl1%iDUZsNwieGN{O=BPuJtF#3Z+SU8{XU z@uIf^m=hq2XZ3JN-(I*YLNv#wE#`OGd0Dje3u^&LjzN{&vi(zdEG1E7=r=de-Eh-dLWnGpppR|MFEU`unzSyjLXf1vOE&5LG1 zP4{bmLRFEAty!l@t8d*$%{_Eus3;rRLy8`(lL>tNqy!d>a+3?UeJ97;iC8}kBAYHj^nOLr{;Uj)>}c7AN{T^>xBcM$F8FAwrz3M zeLwr%!s&<*oov%cCDu5Whx>#P;ZTgRNakgjF#Xy-628tS4epG?qt(dJuGxz3nl0}2 z8c-WH#04JBUFR$YPv9;&TOh%L<1#Q^o}0$ulrniLKZ!motMj6sB8mYr^kq@=%_t$l zw2otOGRL}`p9Gg$pj=v<=_BE$l=J%HZzI$kLjubm@QV^LI+uNr_iUZ+HQ~x`^KfOZ zn^hpkth_WK!lJ3>OedV4f1x>SOnI^I;{Fts>CF z937h3eUj3LZXBjTp#s7hJMLUe6pOM)ndl;0q@n=i7erRSGdJp}^4S`;3{U%+*ydy! zU>u`6mOnVL`o*7(ph^{}srk-2m9h2VBp^82-&)I{SkOwZ1lg8JRRp;atsV&+yJr5s zzjh+wgjsah9w&lkz1=cA1!`@@l(|NJxjUCOvhF*jhi@)5i05FY&H2;q8-|vOYZuw2 zLXn)g;o3{vGTf48D$P>mxo0{DGgRf?n#Cg9gKsN(IykPVEdy$_rnH)NW~ut`ZzD() z(3s^`6QEK#r;!F+L9q(baKt2raQn!g2S(XO@RgsmY}qT~)%)-{ZfX$5kaYgULw_|F zl3U!mH(wgq`Vi0Ce0v)@QY^-k7G3>mp?zoD(173bmWO)>I1#3*puLj82Da1QpZU*z zcg&A)%!vMaPRP;uI|J$kn|YJy{1L0qSPT^9BX+bxJ5<`ED8#;HW*81*xxQ)-ORgM@ z5IFdBdH3Ln>6%J|+e18d^ zUhK6^llVsrbM&F*Qm^q4X95VY=D?KK=%eKATkwO#({y*Huq@9coOQToOEp3$Lo%IL zpXxf%Mt)IWN{3@EI8@R-(3c-7zLp^Mb!JN=L z>HVwQML{1s$ZME!t6OgJ)mU68|KFJ?9td~Sku>6Y3$Q2R>rOd-HegST(tkIa2W2O? zdMsSD;9$>{L5vqma(>toUKH^xkbPq=a`+Y~2bZO+3^iY`-|u=^{8NCa-F`@BzNne` z%H((2P_`$Dr3f0 zyDijjK6OA_&d2I!=epBJch})eHl&f}OzLD@UMa&&p-uc*Nk!1* zi7TGennO_$F6t;biu{uppMxfU+wwXMbILuCSLiK@C@pW4@RIvW^XnBfwjh0PL%~C@CAeMb z5mWjH*z_ui%L2olOT9pR+5S|qMg)?F?pay1NgwUJ%VP7!tYt~LOoqn=pJRZu=hb)q zguJZPAxE>TBdq(M{vLU7VJ&BMrJ;0A?!MOtZU^Ofn>-74e$5woy}T&eO}Ui$9=e~Y zImtiiHs6JKUk*^JzBFS$=rIuiNHXG9%gvjrlzD~O4o#^*)EzP77=N>9Ha>QTP83TI z4{*??f(%15@V)tVREo@OuL@8oT91YkG9_i>Opb(? zxy*)%Pq&xa5{eeYq@PF=rg2IjC0GjFS)_?WXpLX}ezIV2vu{-a60>&xdEcX7nk&80 zR7KyIjS(Bhy+DpwIkaH$oNC`k^=HgGw>nV|2RO)*D>Nt*QDCmz4L;`_*eTb$ldMu`L+*)>GE!a+8y85a?JR!mf=j1& z=>^Vf4S>dVB!n$`Js|8^_}o)A`-@{yD6D$vvZJN~c3n?Mhggu~0mKj4%OZu_5-$#y zHb0qn&UKT>v{kNwoCB22;8%u zSSsqFUhEd{V}`wy*lm$LoYh7#pP~~Rqw`;VJhVEo;eTO~2oFV^7egt+{-Uqel>O|U z6Op(cBk|3VoaI#2&#*qEsbmK1H@v9-Gs*hDFIU^%sF6V_GEd{;>nM7Zz{diXpGhB= z_)Gu!UE3zY2y9qmHsU$ZGBxDJm+jAgtyrY5S)hor`|i3E5gQ}wtuovR5_Z56n^Q!{ zK>3MXjD|;j#blK01nZ#9jd1HcCY3}~yF23SntO@JHnuL1Y zL#v4cKAj?vE%0)I0OOD7q)4Jgt5js=zJue6F{2Uuayu{eM+SaX>17~IOG^%ouDv?? z5y`A+L{)r)AxdDF|V$pG(Fu_FeT6N5jD(&N%lxrTIx?+9#VDc=kNC#yERs>`Gqw!f93{~x~?;#LOz`Z zQ%hIanBiG+3FzuvqZRJZ@4j!n12e-o6@$NPUX=fHmG15a`P?|K2*u*s1t{Ov;4Pl- zOmeQ$$vxkRMuohtwo!NC&;8t#5}* zMx~Zjkr#Yz4$3bN9KHK*hfDNME7R#up$Kx=!0G)W-#HtNlw)x&~{cxa!B zveb*NWM*GaM+|{LBjwwk!UG%v4zXtoCEgzm80VB`&M%8^pO-@h*mwYEIw(BA%R5B{ z`kq47_xk?kkaPO%z`C+On-zRSa@i-USSQ|WR)UF=XHdT@!<3=HO!!Mi<|ed-CCZMs&N>BWMMC@CmI z*Zdl#d#foa9zvZ#`m@v|ZT2$QU#xo_C73vS|981j_qORsGEVksPcZWw8#Y=uCB;v} z)0n>a>?%r4Rq7aW2}2V-!~=Vcx>YGs*SH}+VY{A+nP=wK*kceDxcVsL^GQ{+>vDj|25?hb5onm#?g zWgn|uv~06)T?qBkQK6CQi?){xzvt*BYq~w#Lo+8yLw-1Nz0^jTAz!$Kq4|Ch zEkNoq=@PS>&pE9H$8vi3K=m3~B5EdiWU6gF&GLNzhr-bNo8`cZ1{dC7Q%6x^kLr&P zs84s%ntrPrjro^bks?oZs;yOFV+cy78KI#z*F;Qv@bv_WAgVN1wMH@3!rj6PFW0M> z&Eo5BJjSq0Jc69q+8a)t=D3f8%^k#Pu#(-&%UUwmzm_FW)$oU~%VqnPWgj=)J~a{( zCLvO+ksLQYtM7%jL)+OP#D??cf?y;lQuzMQfujhWZFjY0sfH5WdXL9cdZJ8U_UYPa z$=_)12s!#35-Qu)Q=8vxhU>)1&_&Y=FP(}v`3NT8Mov??9m4Ay9N242QCXN(uoz9O79lN<>E9_^5w|y8TgrT#fxp&+ zj^66N9g3gfrPnVw-Tj>ufGxpWQJ1p6#Z7h6yzX6VA~bN&2$PJP)0Bd4f5E?$RVqRs z^&_FHAP}wc{~>X&SG9#~d5kaY`pXA71@NGHKVlK!m+gpMBi1ADV4`cN1KH+!XPquS zM2Tm}GQ`yKWfudIvFRuFYeC;E3gS_Q+oP{@DlN7dO*LiBisai4fJp@Uo9)BqLt(e#&K##6k8Pwh zf(qYNkZP3SwM%;$uM$MJ2#Q}PyJ254G3Q0chM*Nue*A_6M`CqWcIPc9Jy&B5&p3N*)U1nXK^Y#nXW z`{)AAUG-~1TfPq$g~>G76oRdFHi{y5&&N+I1~^V$ENLqZtXcbd!mwSZ%0-_L65?m2 z*)=%cUo1Yf^yql~b-MWd$6jAb>*D74$HhOz{yomFds0&OEecI6N4@uNgmV9#F)5(r zBRMG?eMsqir=*@z!l)?`pQ#Z3itLUoSg<{eaD2!eb|u~qrxISKL>yBtnCe{xVRUGd zjCptmsB|?IRRWCUhogGNk|^KaDgAH^Gc7>tRi1ZwxH~W_^8giL7MUS9VSgC8^Y=l_HH_9F4K8RPyk$H%Y;9ES{02w696=p`mUU6O8%$b;H+zMFbySNCQa*g)KU zlm7b9>@xJ4LJp6Wd8)+en0!H_0iA&iy~VMXRz4+ZfVEW=YP*Xl5I@N_$Tn}Y;g5pmic`@dPi<&trYx1}i6bowXC<1S3u~ilHq)U=P81(`+SSdUU%u^yR$12w8!t5%Pa&bOpxrnvU(!-=^?j=mF4@>ox zUa{S6PT_;fd7S*o>7C}xM4Po}qy48Sn=bkTi1=`371D{FSQBAzRm1gxR}mbb17#GF zh|4T9DH(z&gAK$Xo2~AiQcFA|0oeJhrdZoIrSIh-KngB@0>`Re3O>T*e8D>-VaPri#^HEL z<;a17v4rSrLad0@2gwWnK1lnZW+ms?$i?^#&Oq-=3ia&&Q5G6|`xbR)>}~bRI^ZdE z?Z!4uNu%z3;f1B4VHL&ct^ny-prHR( z(Q=>8fvC;476GR8qgx^2eWu73K7PaJ17kg}JExm*O}qw2tMagnvf*~3Vmax#*O2g4 z78FtV&Pe7P#R`S>G{xUKPLq=fm`h*YzlFkni)qgWN4{4pS2kabfSBrfOn%r{4h%)T zo;$4T&|&Sg&xITK4Qi@$f>*x~669!fbp*(_(Q!|_=IiVs7h7S#uyInmkM?-UmBXwxm@j%x&nuW1A^Y8&TD@}Ko!=fwfB*u-lU2G=yH-XdpRJPn zgt=0dsb~?hT8qo1ra^M|SWV7Hr>0#E$K+{KNkFWo+8brU<3rMByFW#>2s--_!9SZ} z6ps+gz?C0x&t@Lf~_2l z^8#F{E3aSfekp4E0beLo$7XQe&qaU2e9-_%^nD%M3zZH=A)jI#(@ozg`RR(;?+~F2 zQ{2ouj^tI_(0Q;Ta;*|?Rus{;ePOt_?tiy=X~pDY7>;z2A5#{NoaK} zC6Y5<4LfyA9RfU+SZ>&w*kz?PsQqElRITubZv{P@!TYrv||Xbmn?oogF|^s5AB9C5Sv zy+Iv*j?3vALn%bmV(o}r+3&{@Fv>sk*Oj-dsI14s`CcS!3ar4T&D zbI4gWrjj(?8r2g03mD=__pEbEFJ0N0P^vc)u|K0fPaT_XjUWdG^J|I@eXo74#xy~l zrw;g0-<@`V_#l_v(i4Po*)R7n{O3~(%F90@h2PMj$jAgynfw@wUoZFTG-u3aQ1~FB z&0F({r)GsYUr})R%PBZxXU~dWqTpBqPAU)u6qhz(==Vo6=ILY`UP#NSrjn#E*$ncV z%n$ba5h18T9E@J!T=AlTbCt{~LaR2vbeebtfmHo-K4&V-U^Vk%_H6z_Tj`o$3G z8I!Wk5vm2Va5DLEM9LFVSN7GFTv3~VlG8Y^4* z1*HegW~=m$&;YkN%XxWh6Tmf*nTg|qgyV>+g=fcH*lBPo&gz+~O-mAu&|aba2H>uEou`W;rb8Jx9nS3*1q0<05P#7cNG zz`H^^NOOM=sAR@3DV{jbmN!7C-o#h=w2C)oVNYPPV{#zcAJHWgbv0xzt5He$FiSLi zVbyiToM4uKG7zO}cz<^y#*Y$!Tp*&gL%lR#VHRj~0`JRj+=SQVTXx+@Qj`Ix7Dd~; zQ$MX^op$DDcH+9%;UF)RJ$|<#YpZZEl8TQ%=EaHz<$>#Z!hWR>sHQU-BlTa2?Zuh= z6c{OD1xo33cYX2aRtD}i_XNYo-PExH@+$}5R>1fiYP0mNCYg8b}eEmGT-;g z1vHlm>S>)nndwH|rL-uB*;E0%`T4M!=+9a25_#aNDCji(@<=0u7zRWI#|#u81ssSMKt7twB`BoQd_TR`GwusD#P$)oL{ONF@ z%5Y<@X3>TeIv!58OkKFRBP6TIzbbvAf-fA+u_kKZ`EFf+yGF9Mi9;~?usaa1MxQZP z`S*kyVu5-fUWzaOcSI+MlbM52T&6;Ir#?Kie++NHnAsl%kU{{n;72_4ZT}O?>i2NP zMsFffX(lr-xTsalU#-#~7U(rwX(nTOuS1jsM3F5yq&ZQx@_!d?`>5IY(mZgQ-dDfO zSU*N4Eo+r`xLPhA49sF7#Rt(x8qABqJna3&jE*hwfhVQljUpA_Re1_^R^f_m1ZL~(;^O-8p#zE%Y&Su zbU)i0el1rW)RsEBg94o*M*BLv{EW%x=p9C1uo|?_z;TBjN~9yL!2}RcRH!{~}rc7mXq3ku;g(W6?FBinAM%lOmo2rX2&GLznole{gKkMbYBZi*ouRir6QZKa>$O$5Blg zu0UtQkb=Pe%i;F>2&#O(?V=Zt5OJ$pne3^ zxjCEoYHq5{4s`evG#HKcHA+jEm}D@G%ELW0X|)rJgrYxWQL}p-KTL>D!T_h}2164! z50)B{8K5JePmI@~B*u(S=XKe9qiHb*3Yzn0O=l{pUTJ9&rH-$-gwx-{CCfqCIi20F zr_Whx7c9P>H!xP{GLN(Z-_+*~RlFWXNNodb&Bo^`gpKwwKwBA|e^+Bl@|&1=DB%mI zv!(hB9neV|AP(r)5%C;v1J>LaddQ%FjT9FM1-?a1qj)5FE`y!e{M)@3elRC}mNPrCSe5ET?JSHoG z#)jepIZ8+NOSK}*3f`whHIr(F_VusJ{GT)8%rap35{=cX4W$>KS5%_B_%Hz2TXbb1 z{#AZWr+$iX8{TM#lZANxjp;{7O3nq#!L0y`mAW`fIb zKSA|l<)C<`s9)gAyNzPucNb8aBDNEaI<)+C~ zw57Tuz&_P7b5DyL^V;COUhAzagJ0r}o`e|9fBTHcmC*6&Hj+S3=g@1>%{B(t9;7aK zqZ%Qldd>V(A=ecdLdC3{m%=FRfJspO!6XNvkTF*gYGW~3V1l|q9~g`|&nsyxifVlW zkb*xf$sb7ujBz}$rw`Hby>6O#e`z;Z{fyu24MgI?LFyq}T=*zKLaGfGB{)}_UAx&S znohE^FegAAgXQi^(B$y2I2fkB7U+&#B*&q7g!7sDZR$&s|9nh)9o=E9S#ZN0%=ip4 z)Jc8m(hgWO4CuCzH8;ukJ>n^;8hf-cT3cC`|K`YNz5$3+!yBdIFRqM$sc=nQ%BAAV zPdL1?zT&ix%&$=O8(#=O&VwTN#~2+wEQo)ANt2#I(NkbX zJX+rKZ+Ttgd4l$k=SpUHA3SqevU}ayN~o2v!3&H2wrfI?Wuz>r@UBhOm7`}Q+B=F z#oJw#j1F20L^4OP_x*CAX_hJ({t6j~oVhhnM>wyC@97J*Yn(pZlS>5N2^{$JzL!C- zvPmNZN}6Zn68tcT-}J^5Jj{PYur!x#0DE7RN6NoqvGI~?L#r*4o4rKiyWPMLk7Iwp z>)@?em7i&34QInExMR2;>OtfAWs5C08hn_{=cCAUVfQCYbBoHyeBFP9)|UK=sNP&3a_LMIE6KEs2B_B#$x)H|2 zdI{>IP$Ba39T+0aU-0Uxs3bjYJlN|NaeXp3?mIitVhf_S1#53N0}Cy`H2$rbOUWHd zNe0e|zcLztzsHbu?ILMJ!jXXL3kz)f;?*ZunsnXIru$ttGjMphhTgw>dUE%XFxFq# z<3>{|?LunME5`)Vyw9!u>V)>_0CN+OBUkIvWBDWz@+oLorwO{JQ43}LO^QM&g>6r4=852c_8cdOHN5p)Mvu9K!hihR3!W>p z2KqJ_Z=jhwGw_j@nW`sC#WD8fWZ6DjE@Lf@}mUf;F6v%3Z$iN9GA}X;wD(Sd7VtJ zJh2tlZTa$;nA&JwRH$biK=1*HF?3z~b~PgNA`&vDP3IMgr&;kg-I9(7=;I=aP5k*4 zk`Rmz@AS)lkydoxi)AVoQwFgN5v})o{u7xmO&TNu@RO011FVffCM)u}j(MDW%Mib( zsd&h^u{@rFwfcH^6LA<=k=>jL1BgdO`mHTAl=bN54$cdcpGacFSao2YtkN%yYL&r#vH|{E^lK;xa~j_!}9^IHTY@d zgdd(DM|`Mj#VGGh3K)D*x z@%%%0ddAZeavMj+NC_G8aKTTG8{l5*#au+lfheu|f8H1*oQk#uY;HN0@?Pj0^O$Bj zRYlt83tw;c5d#zK&!rS{J)8gTZ3Dz+BJJ-FDV_IjI;cBwM_V%gCk4odf8wp~Y< z(xi{agUGu^89lUYlKM&hRQzOzE{ZL?<~Sn67Slwbz#E4TkryI2pip1Ll{Gv2cvp70 z;HK^H6>v$9F{BQDbcG^7dQF+3y52=L3r*kJW?!If)|J^UizZub85YZU$WhprcXp!E zQakak`DJ!%5i@Orh*nGX(2np{@_PAV&ZZUzLwPe#A>Bf6cY34=^mq8gf954+LMg#V zJ5*H^V2Kf@7IvUHL^+24PDtCshhgvNrxB+LeGfOb{n#-F5Z(G}_`o9(AU<70b5dol zDu3gIx3tZC+#j2n>!D-$$d2!O7l>>GuZc=+0;oi+OFhMSn&m%_2bnEp5m z#bV7bNzTCw^q^$v_F)ZA-wg+3(hh;1kdKc9@4?eq)aH@sR)x-{eX3EvRFpB$P-hC@u1tTogN2uQB0zrqq!5M;$;YybA~;yY}O_ z{iR`mi(+j0MKtUSSXiCs=L@i6#B*%TnJOx!r2jCc*%}Y;3u!!t5c>!#+P&S@Q7J1| z)Y35nj~z@e4;-LPBCDHBIBtNBuIe@va|i;?&5+P}MhFRNC@E;r{7>_W52OD-jaZfc zX~g1pLN+pZ?t`kVtj(N7^z1nKoh^@(&AJz!rF0NWuS~DAG_7QC9ysN3eT*s zTrYRUOG3k3YNA99LB%M+4HQCT*MKf2YJ*(3c480Z9TllJ>ARs$LJ46eSmbXRT*@^B z*|2wQ;TyJX>(dpC8@*Pk*UcM(9)>T|O4unB|`3ZaYgK>qAdg8N)9AicANV3jm&=A zW>{{zV3!s_R&xa+G}Bp}!~Yy#KMXtlYJW(0C7&a8GuZMndVe-}wWrOQ=55|^x(UrM zALkrw92%PXyasot!hd5M6pxK}6c-i_sgHSjc4h?FyGnn5hASgJ!-k{Qj57ELZ@9p( z8SiVA&;1T7pAu!s4*TxfjvmpMe?B+nw)@%5AEO9`iUcokgBEu?$(&5Q`F9iEOGZ$E z#J3ost&v6D5f^-Rkcd5jG@Ua`E|ED#;r-1fPE3}_*TlK`uX8mA+Gd(tiR;$)KqlRr zs&?>{sGuj)w}2RkjnQAKRpCH|6P%mvzy6uLAJF7KKz2!VPY+vCtrBkQI(J&30Ex?W z4aI{oik|+{Df!>6jO35eB6$P5H5C{jn(}%C81MRlNO3cz5(>(a)!D1jvIFLn1waer z_>ZR?^E z6c9i=6kQ6#c_Z+`@?Sg|(4i!9iFhfuTo9@E6%(cPv^%IN-YANtQN z{R8>_pI!RLI{g1r@r>C~B_t%w4}OcBn$9;hf1RndVG!2^T?w9EuN(f!1;A!CM(b0e zRlRNwP&EqNx^WqmhMYU(X&j8{Jy4>XJSlxY5mn|2TGRf;uu5LD z0oh*`OBfYAnG8SPRR{r8>r~lm`>zk7=kVWsaSW*hoguT~shl?Er!zL?@t;ccnkQQh z4+l7hPelVMe0D2EEdEn}b`W8l9?{CmZIf6l+i$;eju;Dr z!nb1D4>2zrA4Ol(gb6mUr{$T+=Z%}&ZUW}^5)L;&_&~~KZOfbC@4d^R9D~ny`qgAG z5alYas7t_j4z@^3Q9g))D^QbnzI-$?L>*GYeueR%U{Jnr%njy|@pArZ#`7_iC4V!ycZ%aRtxDoJ(hj%C%sX9^cVceozp% zY|?8kxv!r(DLm%v?HkY650*YIMi1ceA7oigws>_oAyzr*Zl z$$W+N$XPgxjzhJ4N29I(+;c)>k43+vX~Q6#!ADx}E3Qt}I+fct@{;Z^-Q)lo)K5Hc zFoEj5+)A0)?~Tj=PLBnr5U0WD4hOH?JrLwD-D!9n$q~P!oO&IXbKNxDmMm;EOZ#H zUE9^<^=DaPvdL?`Wcmem<7tY`pdaFK+!&SLWhKvUMQ6}iWLA%86KIV7`DdaS_LV9? zm;BOv12mGcAcPKtJ1P(GO3)SIQ`Acbo6PO~XPxIa*YKM`fMvC5yEv3(bDz_+nfRP% z-s*iKm(vq5B+oUkYfOSpS3ua5CoU9>M`j+$^W8IhIq2pRLhgG&P1i3)`1sk6+LpXm z4h*`}#Tv0{0Zt`f5be(jxMnP$QAe$q>D#woxsNx>CWVvzs#m0PSx=sSxC|kHMvq5B zZz0BeS7!O??p0mP1KV2qLUuFksUrZnX)btU96xQAr1$XfgaL!QawU>4MF3%IXbmg0 zTMv7TU?JI&Yan>q06@*A*Vl;l*~RHgDaz(Ad5o*Z^=u>Tiu`{}Ir|vh<^T&4TXlDT zt5^u``X^$8BB5uEq+5F3b`w#xw6$*l_pf?HOhtK+!FeNe)1gXvK{7Fe1(TpN(Ls8lCs zw={Glr?BjGDe1-3v2V=t(#6bJi4qe09Jdwu5SmPr_vg`jC?@xZ3osv)^Ok&fyO$(G z;+}~E^|F5)){9=#`l@G=fO29fhDw&qvzW{39COX@2u406w`Xs^zP)~F&8 zt0T9l_Oga5jabz&V3-WSEUQOHYn!8-6o-tx6{ckS?Kgrh^6-UwHn#f{Z$nfQz{>3l z;E2o@O)MQgXdQNi`>S_Y(`1bDvo#W7;_;su=2fX`eBed=`Ns2?XZeqFb@~=IHvL<7 zArAx&3j#|0Yrq@iy<=iF2YS`))(Zt?l9+Yq6W>qZm_G0>DR2K{F8WEC0Lrus?%JGb zXL|g)>w=VVx8M#+i%UfM193L-;rJJeI`b32I>LP46n$L{m4UqJEl^S9nH~g4;#d`8 z1K-eTFt=4M=pIhV1kGeLOn-d#QmVwAYtB*Z=!9z}E{(irZ4VG)??wMArHLj(1-T6q zo`}0AcE)a3=e;9Cz!kP+?CS!f%jvN8X6iUV;-HW&1dy&K#^c3V8d((j^RQVAv-@yN zjb8%h0{S@Q*UZGLMStWFl<@p6c?E0XB)k^Z`R@KjJ#d>nm}kcM+gHfP6wY?dy+VtdyCsKU=!fcOAH*T)r0h3!xWDad>fRDkiFM=V{ zx8HRyvB6i65EPQX&m`(-R^8o$PK(k=-JKcLE+N4Z3x4qUgZG!8W2r1A>#v$WE?i?? zg{-aaH^aDUu=+lO-i~V#z+>I46>mk$(6-rm>@0Brgax8H>tNURK5WkZ@ zY1KEuqg-p(k)rSEOy`gHTpCL zbXJxH&~ZzC3dTWH679X)=zx4BH++FGEgVT}ba_Bj#@DM^q*GsJ#hB8`_xWhp(NH)1 z5rYc)_Vq9yT+_~Y+Xp~fQbDbM`eDE=|3ET}(T4=DO#uFXh_!Vnf$i}-@V)uP@s@cT zH?%X`4IFu^UHZ1G>xTwVauazrVggy>~9}7kxQ_uTOWSYOKo`J_Gh+g0E`dmFI#ey_0a_QIG z9>%ekPAG*8EMGwauMngwtwviu?TNh#fkZK%rdNyzB2!-1P0_Gon^s6hF|`HM;#1gW zFt%SFhIy452>I+C3>K~4T{I0-rYG)#$XeA?>z#m8H8@{^Ft=ccn*Ph`e8E~SX zY&?@n$zxp_7Wg2&-R6h*KZu$}AEP(nA)zLh2F&zKS>7%~Tdb8kjnjGOesE>2XnjfmG7_WHe;elX3$AC*{ zXdFn<_x{4Yc)#IJ|K28Djj^TKFe^|+Ym9~`BuGh=&`S|_5xbFTqrdqs!or|un3*sQ zoR_fzU3?rX&&dx@hU0dclZuJCmwzOAq)phU&u;KXzI*fg*MDKAllA_!=|K5f4K#G+YYXcW`ZK-|}zbihDsItp5jHC+L##GaGC)Di;~^J$B3 z8Zo%@nO^Ss5nje#vCnI{+=qV*M+OG`$9UQY0d#u4C#TFf^a+Uu=I4(Wm@g=D!H!7L zj4SozC7ss%iR3>l$eytAkBpF-0|X6^LU*NNqQfK@)yrhQfR?b4$9))jN@bnuZ`ZQD zjy5nL z$KZ2IpJa^)Z7mAfQIOXij+(EW?jf`Zkp4bX8&ejUIMV%!y&bs?Om_5ZL1F+w@kM-* zpOdNwF;qVntIB!aT&2r52T$R!A(Bt$Y<)}b{DC`-4;1sh_-i3;MD;;KyB2M(KfzkV z@lt8@l>|5e6y7GuQhk?Uq}4JNFr5&QTw}g8dPe}0X~5Y>Obd8FD%Gv!&1t!HqeTUm zT{&`GMf;~+Y5v5#yHxf3CB#Z%dV~Z}8e4yV6In z{?~LX{7*teOQve(idBrB5(aQ)aGSpJhF>9`!Hq!KjTYBJWj!vc^4-`@!l{#k`wB~3 z>87$&UC2f)rfap@%!W)i;dz(H_`o~1~ z#aIE%%WU?I|Cx~~FKm$?<5O0Y9K4@+x+LDKp(VSne$h!Pnro!JfSY_E&p>5=U2a>OVSMl=#x);8zp<4x7nQRqy-gefc^1V_x=P@|JOtsxTWj_pni+=MF1GsXR@FSe^mX^Fx&@8I^cr;6 zap0l}lr3ie12^#e{E1_WI*N+N47-T%>w-1;oai8JB`E|`WOappPg6o5N0-QJTvnjM z_}E#BU97G#wZUDn;)2=XzP+?&$G^nz?vWNdO}=l2G1qlP>SSbu-sQN<7beaAt&%2J zVW}cSQ>2>q+SB0$(jU2RQmX%}6wId}uUMy}NL*cMyYA8MJ9nyZCu2UO`m4+t8WdL* zq|HuTyigt<-HX*!+4d+DALF}Q>g43u9(GAqH!tRc3QQVIk@VGQ+`V1<>~HeIVm_b= zc5<1ZcwenpBN^oisWTusY_ZG|>q&>D$LqmbUS3U8-?W5Hq&e@fE#w9!IFRi*q}TU_ zL=m9U=h2@{Xy}lR^jxid4L*%x<_udZtr1Hc zQ53}$3-&d?rE-ZL$nC<#pS)T}hk_0FX=EH2Axo5Go>Bt*2o@!%jtkIjvWz z?6^JDlgF9~Wgs2EE7$oY{D%{J(oY^W?xR6tEgWJgOzR^MUaoo?*ZPaP~#y% zzYF$JmjzXI(Or9rj8TK+dmCL7?G9;A5%?ueSab^x)XMb*UKIO=N9dMmyzKgtytt;nk6KLM0O|c0Yei%er9uJVrVva^7H6Zo8NWg#w&W(K3m6iGF*mq&kyJDCIo>a z-|j)DS%M}9n@q{7mY>AaOy;h}mm~d-KV%vrS_}^SJDyn2H`VfMoK{UXqTPGILe^Jp zPk5fnFsxn)eQYe0_Nj#Ztg|NR!r6}S*LR^@Gui6alJEh$38mZ)cg$Jv9j$8qfuir=F3GkMIk#TK#Jg_iD}(zOh?WD^Po&JV1n!GmX}6Z zn!#mPAp(biS9lduRUMJYr|&&T$nPX2B(%O(y-~T%`)A#M29Qf?xkm}#nQhVM4qoI)fJ5fq)UE(41e%SU{xL8itY`-XFXMjzx#5sK6kAgKVo3r2qMt*8p! zmZeS#;ubx;>-5pH22zRtrK$ytushm4Csg33ek*oetX}@2>Guchu#eHWhmS?8-u6~! z1E!QIlk5%B+@Jl*nCL#bm>;um0dE__s~?wD*{4zg=V}D7hl%xV5;}E6&|?zB zow9eM`OF>43ahNIh(w=0?pxKIX%e4+=Or0n9ki@X>Qwi4Y7sg!NA=GNt?PWOGDfu# zzqw=sjR+bMfo!mvfZ@Fj6Wdki)+X<>S-_a4b=hEngsAM{QN3aPK|Wwi-T9$LGtXmx zjE)!ow!@BQwIu75}ytg9e0f22P3T!ASK8$L=<>vp$yQ z!KM4;5t9N`b0q1mTZ8>{+fl=DV~Y<(z~vvJC_v7a_1PkNVBD^<#~t1?EtsTB*(85S zufqQb?-u>XN`eL^o!Fi#=!8rJ1*1y-(CbasJyxT`Wk%TdRcH#+w)%cRGyUd6VnG&y zLq(Vtr7d~?-R|M%XH??^&_zF??uV&NREgb^6Q7byi6IOjS9wz{sv+aNThWeJPtkj$ z@FXgk7?-)mFnxckmg~=FnDpfjz%v4F_?{co6b7yA^Xp_z$w?_8sebxX3KEQ9!~`%I zAO%Gz5bp<_wL(13(5A~nkZ)<2sD|F=o^4dmkDQte5kw@vTEc~OGf+LHm_G+l|Bkx! z%HMGs`DxBy1aRN4Et@x;guY5Vwn$-uc~0X)@eN;5{2D&6e*6UVCGa5=py77YeaQja5_YHn!Yzvd*m+Cr(H@>Vhbq z^(V6m^tBziEa!)p;>*1!ZlK}sPjzEm_ZT$s=M&78y_t{)=(${8V!xYK?0sPK9vCO$ zV*?Z;ZegmSnv*jv)cNBPfBsTO%=%_p^b^p%^5l2#)nWu%1~yYbz~MsX*>cN{MsItA z;Cos+gC4^(%6lj~{U1Hu%r123@$}L_^Lrl-!-=?-zjnY4;G@Ahbc(A?W0nVv=4=Eb z)qUl%b8V?lOtNG8@(MiVo;Uck3dQ_hW_>5zDEC}k{`hI!ijcueLJ|4qDlfz#gOaJ5 z7H!7wbz05n4A7P^WmKv|xAYGTsnX$_-=3wY-}h^*ZYOQr6?`!Fsf4Su-9A`TurVqL zx!*2ydKaqo@gWzkP)Rt?2t@s>Fb|;V+vCBcwQzbg3=)}|+oG(^fQGE>rS)Q4>kw?> z@feN5tU9fXE#Q-Q`K>G(%hxp;BgM=A-1knSi{R*H3DNl-M4!eht2rsw^K`(BP3q(&GAQ~b6hMj4VTu>nhvCWGbH&n*RFbj-dvPLA~h(tWD zD1N5y?__r7H;k^L%O7dNgD1UrZF=t3f5ueKq}NO&l5vJ0-^alZoI}$Upr+IXlN?H| z4ZFq8+LjGAz-)rX0O6;fu!G%5Ufh3XMw^SOH{GrBiEtLOgs1mipr>Quzi!IyAH zZA_JARuodfjUMieE365}7F+)#IkT}uelPz>zzme@+5 zBsbHv($VMUN-u6>LB#Rw61+Lxb@HK*`B=3uO7LNdKi3+DDA!yG>YX( zYez;%aBZC*A))EFGvlCKsUFPrqR}>dm%6TYW&^pcok0lJo3#C#lh!=V=R~)$#;VH$ zZvEmPTg@*Q`6sdxxxz(pi$v1rns3STF8tF7Y_OhDvGm2P_JW)a%}f(~+Qr!=BAo5* zG4^N{?HO;r-1TnFc%*uOS}(&9$l!~A_aKGFFti4VK1ue0H;-%!dWY=ogFfa5q($*B zs-8#+_7i54`wYG@2joPOuYw0#&aqJ`G}&=%U`1BH!V>ZNpW^WLne>Fe5fx8iEZ==h zZeh`A2}rp0_SA~iNvI3Z=0^a2lA5<+ytFMFp9srp4zEVmidh8H`dOmTe*FCD5qp7z zV3)NOgSaLl2hd3j-S(QhrLUpUlny(nQWi$?;8-tzCL}MeC4U^SLCR5L;X`eTa}sf1 z0VBr6$ZoyhY%B7c*No&bC)Oc>jhmNBUL(BC2Zyxt<3AyyV>LCrF@GFp+yYm=xwAR=R>J?Daxwe7!op@bgsE?31SwgG2h1E ziV8O!>*v13637iXUVsZNVpZ?%ReOva&Fz7IN7FFI#^%>53)Ma&N0;vI>-~)7END@D z!&9jQJ*Sv>v7={Iq)GGlFy=k0e+K^|i!izXM1)_LI)i85a7Z;d$<%7Cyce{DWKSBS zQS_WDxxj6%GRuv0Ma%FFj6Lpd&S<@w)>;##fb+E^^WCp+$|yL3H*Lz> z&F!21NOA=i_TaWHCN4ozZI$Dt8u3Uy&eB|l-J30S9c$%fi6dgJ3HdULiG0w0Ooh^> z3P7Vo?1IGYB(d%p}Zl<0khFfhUuEPaYYv4G&R6? z8vHtT*e7k<)zsaKkFQGLTMcX5#pP8dD^x3-TgWzOL(|fmf)O5sE}P@;KTdrdT8Jr= zsHQ*fYelSPsUO&WmHzXz^_A}lTOf;`fQIEaB8A7o2npj z^!U|yem&XF)IH${9OWi4b_iswl_)aE!Qt@UN}A2?x*JSuc28yB_lePlpJwgiOM4-* zC+;rlXI13hn|HW+YFkBYcXNk-!rA^mqq<5HucX8HEdWtj3Fin1DZ?g0#}~fye&#;QJvTc)wz#G% z>Va4jlz{vfea#vX8Htn@^~71oe5rS`6A%REL|fkJJ3Q_rV{IULCFPmwUWx-|uC;T3WC_#bd7b@5JGH^)fTS zl$RH`cw}5?d*4T?n7F7XS;$q_0HxZtc9l-v+Q8lItcXlY2YRNfQMNT8K zB2V!nzwbcgBQHK7uo2%Qd~^j{9Ap>j>o97EM;u39H5Ou|dau|#k8FlF)|)babHv+r zjAA^YROclXrO`F_Ve2fdC%pf-6ejqxKFzl|!6yQji(vTK7NT_Puldw>*KStFM^d1p zNw4`^x=vttFB>x#+lk8YE_Vz>wA^qdj}BlJ-e!{ZTP`*}N|3y7a6G=zWX6z;k_s*# z#rmt)ms2;0c8Ae7OYFW;+7XDNh4)K#c?(ENsPl{3s2&-_T9rsz_Ejt|S5c$> zNz!O^RaQLwMA z+uzDF)1OI2zSJ7AY&@RM&(HLFy_H^W5^D*g9s4|)A4>_nI44tp;3c{5)xz%XsHwy4 z7$6TOLqf>I$in9GZO}$U6n8coF8wd9PHaz+kk$)^-^<=g$c4?e@Yh~y<>w8)vDzB} z3O3w1iQh@C1*+-X4v-%+?_k}uj7=@&9pW0qMN9@YakTrK8@05k$?DrdqGRpz__Y+v zm4{Kl>-}UVnqXPN$}bAFYSiPbx^}-+uWuM` zCS=AeDD;>?*(3(&l5}kq1h;6pb`S>y&mt(QU6zJpZv619$sTZ=zPsq1O!S+xf-EM3 zPTsCP+YoXm0mlxh$R}^+3SbRHeB_@hS0tJdpq5@g?UC6Uab+?zC8Rmm^k=0fc`Z?A zvQ>kb@?<@fNoq=K3S)YD$`4)%=p>T&=bM`5cfStxT#r%-bot>TPOZu?YSXiNhoUKy ze%&R$oJhO28xiEAudVz!*)ac7f5S&1UxLw<<`8hX)fV}rc2+;lf6hHPUisCvL zk0BbgCsLjyccYwf$g^DE#s3{1Wa!#KCFit0Dkzo0W2Wz9y$(g(B#7Uh>*QkIr(9s( zhb)Ve^Y;c``Bw22$<#6>G=$3kYopPxry7)e^!9x=+KN;K#EC?F_sS|!j1huEH}nc= zmKRLp5VOW1&UV(Di#m@cbx<8wOf{IzFmfMMMw)iVnbY}POD3V+oJrMZPPX5)$mq#*-B)T4=U~clhPxBg1w;^CL!Ek=Iub`1N5tZS`0Z|kF4aP`fwG?&-JoZKd9s5 zLQNgU37Ab`RCiNX-eYOY;ta)*1-Dz=uo4w7E=fzgO+|Bh>L@Snx z`{F?l?F>gKdxu$3E=Fxz>Iuaj@eOSZjuM%VSYK&|fKT1lq}vi97pL%EM$zcK8@>=9 zhjKfzryfYi70je?AFz^>ltG$XM+tTh15PdaZdrDB4+MH}?-G_owViJ%a=y7O;Q@4_%M6T+i6-`^dLLYD~8lT6N?zgZ~H=a4lXE_uPxnQKltq)8DI594?~6u(!=L z9fxyici3ewqMaZO=d$xBkB?IlCAUT9Qx;o0HcB(N$)0$9U>TO!ab=o0x0SIo7eK{) z8YnCZ9ybL{)}225?<4hr?c-f~P4N9Ot8g73y{3RQdakjrL;mf~{%w#(ANK$p9MnvCsRKRv&{=CyE@gGAyPu*?hm5qx9sWyz- zu_Hp)##_nF8&e~JA37*G_{!xA;gF&CsQFypITx+n6QYVDg#E|d_P z%KzBu*LSTw5x<^fi+g4@BC|g_o6j`J9^jrfuT9R%>~A2-CyE0e((n?L^emsi6m9ee z(l_$9vnpr&D1G47idtbIR9>`CZZsED^LjooB_vHED`WN?@hao|5_l&OS(8%};7DWU zH%Qtvt*zzd(spU>Ntj*WcQKo6C~}(3*;(*Hw1RWT=_VFZP+wASX@zHfG90Q6p_NMe%^JGwE!9k<~arAA6-uq z$>%^V^vFne+G}t6uLL)Jlx#{il+Pt$J1-swP)N4NWg`Q1$Y{7$^eOB zVuOXmVR@x3IDf+R{zSclfkuyv|ANHO+2#DAo~GeXo*z8XT|B>6w9g|K-tl=W%`PS$ zw)_fevf2SNj7`?L7EkBijlAO{Q5{d;C5<>KrYzRpO)Bz9WBb4{S-+H!M%yh6ALbl55VoSGiL+NLiLI3MsbH!pxWbIqa^ z>FS)J1LgBe4D($kI#E(noN#Vs0^fcjsLs4^cz#MVwYD3JBotSs0+pZF!WS}p_IcKK z9ehR;n~6FEO6>xhx>ura3;5<>a-kzhaKNyy#)s|2t!C+!bpyAF1g6S{Ob@5V%g)of z$*(&Cdrt&!d>Bp0V?StPOJcf)xNKu)>k=>IBnDM=AC3ExAp!m4We@ z#n!qRXIUiQuFKHrFNd-@Td6xJ==g8-11X_>spfAaP@!733FrgjflV*gD~vjApPFzW zo-};Ox*se_eAiRGju3M=xtfJVk4d=H#7{|s(0Q+J$Nnc3%&EOMK*bjh{Nv?jD zef%UTv0TagjS6?Xo{G)j%u{idDywxyfn%^T}04UVQ4hCZ388U{WB zEsdM4cu$cD7bb559&yxvM1#7QsO3n@(4zjnzBC^=urDPKzE z80|ZZ#Z(HpIh%;aBqgP`|3mo7TBlJcwzhT5eWG$Sj|0UTXCvE4uO{Bc1xL*pI4wLQ5Ul-f6MpScs?SCCY?pu*ctAgC* zlM}2@hZ#@K_lXoHhyyXidqTn7c23 zuPAg?b(lKS_aT4B!kp90J{r`UTz4_Y>Et*r$ol4>;_iiRn2Xq!WRf$?#?`=YVHHA_ z3dWAKn>pZ$N2wSpp@_=MS!Q~NQW$sV7n|4+WKHI}HhC4neP)jqrv7}%>6TlqMm)}lF_@}2VLVO%Nq zj{`G;pN!q--82jy@O_+`SpS+stnd~Q-6}%G#V&j19geMJ)0-rK(DX#}{gp))o(_NZ zww=!5xcZM9-{4ytVx(%=6~%VNROd@9CB|=5wg-N&^DHn%WS>4L*xq_5`*+=pc>AJN zmF^WKe*IY=TJ7t7gtmNiN#=@nN4sLvPKjP9!S;K1PtC4hX(m z4n91uJ8O9wcn1{|sug(0EuHLX>F$jjam;=&bLjJb!yWLpf@8G-hh#{~RA@ zDoJNzaNQ(_s8g_z-dP{F^sv9_U+v|AA`vGX=Rs}`pv1usY#4u2H*-6QKdg(3#Ar}Z^yadDF!%Jnz~nKDRiku%wY94bxfrJ?7ut{f^VF%z?zWv-l{T#4uTe8S~3O>i$c#K%Mmm9Pr=@zAc zN#qeuxfi7ahgq?T3e^OSL6rpkbz}`vQ)%Bt{kG}NaNd$n70js^jq-m4Wwvi1)Z@G6 zlUqzbWK1$Iv?JY?>SQly3*i18sGh$Ra`x-bEthHB%8A|%gTw@)X`6^i_8%FL2L9_- zKi=Ntg29(L1_t{lV*^asGq3E&Y7V0B92RxsQ@zZjDw9~ObT4~fWd<7|7HUy%upjaY z4j~$=pjk4JZH4)t(mRO6^(4$NG_^H4$0I3Et>|Kc6$jdbL-?u{ed0?;6uIW1>BJKc z{(SS@8`}7N>3tQ!mAYDZ4KcfPfC$1<2CN;{XjvuXa{qoYGYc09URy?iTQ3` z)VgRiu)Er^b0rt~6I%@nr3KKzui(0+B+FvwQ*VyY6mi-obQeh7Uo=Hg9f}JT@3lOX zuWJVk2qKhC>)<%)6HGx@n>|*HE08?;1)pw8yb{!+SneEVcz7vT1rVz2g;F*8P8p+q zXM?})rJ>!v`qFMgMEE8}t;z^NB02UMb~1C%GPC6D5$BnN7Rtkjfnp)Y$FAq&Tlvj) zb;Jf0iZ1@72IDu&r9z&^*I7Y$_NPg+)~L`W{=L;DKNQ3iM6uQvD_x^$^K!H#v z0kJ6=PIsSqQ4m+2dd-3eFtmO(TM>r$`}rnS2A#guGz1woW)1B4CFh)DXI5H21efAr zxZAwVR-Osk$E8D6(%uIc1!|FExFkwn0ndMNF{;}AaGPBjJLEjvU&9oC*Z{smku^!x z+SGUeK=nkb?goN<)D}N+>y-{xLYSI&t3VEB2IIvnaK0*93&MKtP4d|KSl{DPG)C1f7XYQhX9e~(d z?KCs;4|p2(K7M9mPI%#+L)T(Zh*-K)yZ3(6_Uh~Ief>Qnh@(2sNjWs4l6E-4x(wFP z^a&E7_5-Hya$`nh@$M2l=%BKweD4Il{Suo`+DJr%?8;Y_r36gz{B$tVqkXp^Av1GU z_`S@zWYBI3!xESR!B}urBcO}d3iGJ9e>C0488$3*_xZ_Dm%_~EcHxmCO!@e%VZ?tQ z<;pj7ma?8H)Lot?!gAVGV0vMESeWax>-_eN`hn6-hsbm;D%6@SU85Y8ZbJHlOg`-f~h z1cywJe@Y7G-{A88Fce#f5pNMobVK>fTRBkYDD#XATjp6YinZ4!pM)7yXsGd_ozHw$ zEBqScejTE%SOXe2(jDLcraNrh*$`IV2#m5><93yrD7k~OotAm;T2x^>j9PK4z~k!& z^K0VKgJRUE3kidrN8z?*3m2VQ0pcO!zo>kMC^X~)y?_5$3A(%|bm>^_^@*XNaXrOm z{`$W4c^@>x|3XN9>=#wByY5~`D`K7seFbVFEDj^lNy%>|MY43TsMG*Y3OP+n)Dd45l6m^R{Jjbp;I;{gape(S-VU=T0j##2RZWCM*`rSz=UF#m(rJ?Wl znj0fNzpRnUp-LK`T;qrAMme+MYcwb?EXQ2XfJeMuVjz2GPRQ@u%JFAU3{iu5a&uCx#J zx!AMK)P*M&E#J+G*VnIB<0&!zF8lqZKO4?^H=;x6*(3f#F7)gzdMA5TmsZJvoRKOl z#P=xDMc476O8qADR_Wuf*H_49GHQRnM#_s@*ut+KCp%(|^#fk{=uL*#D*jF9g>aTD z-O<|Zfh<_Vo!WMk;=TK#JG^RH6NowlBq$5n4q>-=%Oct*1;85^BU+m@1{kf zhtfQU*XhMhIecu)!>~ca8yEo%SlWKnY@#a%&osKOeU1p*Wrt z90xdFoZMHH^5K;j|C3pabDQ?@j^3;2#FYr(-r*mmYF*No6dc*K;Rv98aj>#8KL)dO zkmP%phU{!ry(5akb3z-QsFN9YUy1QG4)*U64Fh5x>+~6wPUW+c(JaRr+XN7bW8D~S z9Wf$EJ)TKy6%gC8_vX1COO>R1a!j&mXNJ4=w|YkE6W$}cY|-L4h*dA zUY?7NNQmP zZ6dAzva6Onmlo&66puVro(j$B=b=J*)xqVGBQ{dn@YZtlrNgeKu?RaDB`FgwKBF}y0VoD+8^vFP6x%b7( zGfLb@_Y4*0`3)Xlcnh@B32C9_RdF z8+HDQE1H&K-DW6Hrheg_TK@p33ZK7FYrm2}i<=7dr5*)wmcp_Jr9r*5KjP486Dcdu z-g)u|zGe)OWcJqnMFp|BT-0g!-2oC2N_)472p+t}+Vkx<(%Dyb&qlE0XzN|w3blO@i!h|G3~`4&l`vx zuJl3d7p`TxN}kqZ+@^#`sZ_G0hcQ(^s>&KOqHV@C(D+`gmWsMR% z)s*l$lYZDqco;z`(64_~J|oSO^k#9<5RD7PR+g~*bgsAKgtW}&*kVPVYr*o~1MaRp zW3*2aLR_5?x^sO(`t7tEF#CGmW9q*9Lr8*#R-;6m(Qt;qEJZ$NI=4}_)^|9od0v7# zXB{G^5@nb+OpCMhuk2_)5$jsS#eyfmGVRe8s)W;<)(ITzOwjXkEqd?Bv)RqK9>rx| z<}POr@k$*ZZGpyq_x5s2WiurEr&09Sh`LRFm>Vmg_(HN3mTMV(dOY7)wrG%|vwE=4 z2mgvEc=n^DdcUb>SY?_10T}AXH*}4BohCPSuOOl|RD-qf-6*+i2dh@D9)()uKwoGvWEEJ(%ql zmJ*k&s&hz0KuydQ9a66v{16%6mTceEVTFju?^eXjxbOA(#y(yZNLh4&F>0JWf|MyC z+qFet+Qqgy-H&0+r_o=2fU23v>9h}X671Q{b$w;48Dl>eld#@9QM=Ww6%1T~^#!b#bWD`Li z5fd70Dz@c*e7m8Qom7vg1{u)td((kaGRN`au_#zOQUwq^c5-M*+@%-RBhXnP2Z<0@ zoznV!Uh@exBpKg%Sfz3E~E!AA7madm>|Wcw@-z8$r+Q&|dxg zdhq10oNT8s3Y8gM&ru1dR8oHml|nfQ-3hqL2ZDzB9qN0 za!2CIgsh=H4sWgM8oj_}xr@VEYJ}T8Vi z`?GQjIdT~0-zoW(Sa*I}TED=GSoFyB`jbaI1am)}b6V+{?%VL5%8alfoo^5T+^h0Y zlmavKxV4g5IQJibL@c?-?whi8JfTAeK5F>3oznZ4x0j9yRRNnUa56rSddJOs(ycG_ zj+@?8-=kX{y?uQCxMU}m5M{fmBJRciyi9Nb!U^D}iqUPOJAnmxE2gF`hYC&TcOw5gQGvTa z6I6s+Tdafn*Y3%qT8FIGYleE2y7A|EgCa^m{q14x$>_I|4-5F z7s7!}85dh?@`1bpJ58(Lab(&x{qk>1iuqJ258TvC6tY!ER4C4vQUX!j9k)DZ@{qq1 zRRp_w0##&oK!t8;!RQ!Jp>9S1i1zOn@ct#ZDGjWtry;Dj=1Zpe_wC12y}c78>q_*3>P1PlgkKm1jnT!%tA>APzT)qGw#j>-pT7&f7fZ0zwlR7< zmY(YGBx!*pU19Qk4W^Psz1_nXB*e}%;j|zA#?VGr-Ek_7|G5(nJRjbl`3bLyowdhS zgZ@r37f8}_RHqW5Z12{|)6lJmDtwF)|96Xwg04*Tv@C(uGrj7WupYx%P1TyHf^3TK z-$}+k0+PAr?&CDV>GO5cxu&|kp)9eOf45Zqs9m+n_sUh=!Ksa&sa~hsYb70r_ji)9 zKr$9OXs-f8y_Y^(xNa8ju%2-?P+J~d^&l-zmt@{4;q%@F}wl?Q_ zjS8K%OBI*t`ILtFEcCy-H~+Yp+*iW7jAjSCW>SGo3I|qZ1E10o+0Xw@lJ*6Vlpfms zE)mGvY!~;ouOXVyh?d~*RPR4Z`X43zkCOh!lK#h%{y(#%q*tOD96phw?b9ynDUC<# z$>&EKsdusOhfdL^_hyGN858N)zNz+XcKqsBq^!GkhpUz|7IB09=^gjKiT>~% zQ6rwfvbVIEK@@aij^if&Ot1H7gPA4nyBvqg_aV#YD~UvPJF)3Fdq5#wTN#Y9HQHLdHP)!2EFFvc z@5gzx?0d;jo3)2R-7*AO3IxrRS{xmp`2Ckx=T1|YCf2v*=Uocz^Ej(1|NShqJVK4Y zhgly*#NPp7$zMM|$-Mezg+7IZ&B83X!rW}928`OthbeQ&W`6wlF!;SBQ7>507`tj! zchGcW9YGpTH$dzx`(a$xb=UB?+yrb$bN6g=H<2E<|Iy`L?7^1Cqrnm$mmx5LYQCNH zV1i%z1C)b-9_`NE`H-OP48WwMM6sO^S&by6%llzgj5M3u9Ry zPPG6S$AxIIPb_m%VJTnJ|HXIt$G&AnV3~51P4uLETc4m4)^l0DFpuuW)*_^dOl9FA z`X03RqEs54&)t%$xwSC?%(-~8vS%7rZ8x$lsqKBT+0zvo0X2-TmB$Ky@}?u4oM+6o zW>nIyXdyyVYo>@mCxZ2_Y|KAg0wwML#okwjMY-<%Dhen_7=VI+2}r7>AOom?fOI#A zbaxCxDIg-DNT(njL-&A$AT1q3N)HS@)G%=FS$pZ)`+e8`dd_v7YkeEN#>Z#w{KqeD z1l#BLr5nqngQ%4)(lUIu*yUzVa{bo}jKV|g8VY8&Myix0`)f=e8a)i77ij|y4JA?x znz}_xslhSx(aY9gDbG+cNkwj#BW<|-pD3?5EZde1ssV|7$h?ab3<=O3<^WQL-a?O+ z!}sHAvYa>r7COJuV-D1 zbfpPEc@GXs;xn$;tqv|*J^--2u~=I%m}^^Wv}hG$9<@Bt;c447=;zUjIG9e8?~1W) zsgk9$DJ+29GH_Z&Iz~_jRLI6S8l4A1%|E%w;_=$zGf2BwB&N2aW0Yy;7^Di&wfzfs4k6 zGrRnj1w-&b^G`wseRKCr-g2b1SA8Ximk*(EU0RlT7N9Gjw06Jz_ht$@|B9m^Qsdk6 ztmmM3bW!pc@(TTglebiIQBG!L+G+0@T}rRtK-pE4k)n`^tL2#iP?O9%813^D#xN$OpEOErQQb`x5!y=;Xa zv@XB~y6(9kTTKAN?vmN4Sp)g4h0lQuBqZT`<$@<4ExUr@wdQJChL0Qv#Z3t@p-{)A zqRe=BV3<=pxsV;>b}omEcV_)wL+iq)5>6+q-p1nP*VB7ql8GpSOep%0uB5da*=pQR zxza7LuCzTQbmC|%{Bs)CHB>*&t~_7&vs$}zR$jz*NE<5aIC<@iwr)9;(Q{zj6AN3b zOt!5qy5=_Ln=h9(aC-0YhOJ{qB1Q8t!zL14{?L2ebyz8|`1fh>{KXAR`}}5Bi6`P< z(FO}_?cJ22DQ*d3fS}@;zS9mFjY1G{dGas6eSa`ZYf%|CkL8^BXkSGj0ZHPh26GrJyJxd0tik*u!D?4{zcR&`Z{pQc$G!)FXOq)xZE9BZ7rL5YhSR79B2Kwf=!T(9ooK!dLyOWHJ9BV_m&G;lew%g6VoqyDLC&(%)sr|(6GF&wN{(m z2dfMdv#-e`KM7t>(eqeN?*e_`DXWJxx=tT70q{I-f~$*uNh~qL1^IoYh0d0T_`02_ zf+pEX@n#DhaWamM488gNc32EBR=~?hzBV*`{321WgD`7*Qq8FTn(eXONRZrdvk^Jp zNrlu=%u-L?Mo!fRGNr&}XoI0*%1)~7#?MXf!{7t6?~4nqbg-!em!lc64wIXrxb_v> zct@_X5_Bd{j)YcDoFksY4F{CfV z7Y_zh+9?Tr>b~ikj%&nCz6iB~qn&Md=L6>C+0etmC=vcMSuT=XPdAmUr>}t^uJ^Y&0;q?rUhC*g(qYAziQqSyQ>IMpL z_2P;*+>5?ZbF*eXcPLHahtmTPpgm@tLb$<`+s1DcS}_$j z;X1~-d@G#c*Og6q?$x~lsw?mKgGeb;4@-Qw1PVHVtnO~vr!XT$MqTl?b>T#thCF$)vGGjcHw$;fZXJQj?g3yn37dJu0@oxMDiA3v49R7Sn{^wQ95ONb--ZV%uD z{c&@eUD1K8u`Aw?mN5PpFj(RlfrRJUc9_>r+Sh471EFYnJVbUU zF*rTSqf91y%M4aJF<2)v^7*<+SKNHd(DAzW$x3G(kfnbbcYOLe4i4MF}nZMre@Xy({xeJJwr;amx4P`~`+#@!UXafH5eBvpsp(bD$7O0!f% zm%4tKU2ePVlPres`egJrkdrM-p-nCVyh4|$aidqAr{awLIQA5@y=1lahh^Z7 zf$hhEQ~Irl^%5ufl00jXdO%AUYL0vg!8U#uXtabO9+F0e44#0F7-3{mF6+~R{9X8YZv6dR<_Vu#x%Spj=u1b^(t)4JTsOJ zUfaj6QTUa4Sx>cFABR$30QA-eB%j2i&3v@PT7Z^6GQoLBQ`~&{;@VU4N6k8R4TNGh znlcCbPGRbgFwCFdr999&S?BPYa!fDztQVZuM>+t7Mc{!VKu3w8sJmoh#3%Apw(*N671ou z+kfe}KNDCJFF|5p`N4VLd^Cq00~aJN9Pf z>sSsa*R5WEX1?yMKrw z>+bQ6BUijkL3NQ7#Os@!kku?|RV47tz+#eD0=?-G^>!yId?dbpDp8vj3LT!pjjdL7 zkRKOLtDfG3Q7|k)lD&t{o6ytkP;f~N_hiDpKPcxvdE0B#CnXDM`&|Asj~Iu!)PLY*AeGM}3%LHQR27U;-UM$n`73$GxX8;IuaC z7MOkiQOX)za0|VXj2v+aY_wU*J~(2LeKAE^LA;nY3yB~V+CYRQ+_PVnKNg@HxT~{A zdq{q;g=^X<$~zGr&JtiUlRR>^xm;`gkPqJzU7JO54Fj3%R;CKzG7tlVVzO9%Fp_Pl zdO%p3Ebc8928$mo;-E94&6V!KoieV`{5^y5sGpbs+!=C@HHaq+DKm1dqBIDmWH_LxhNaW zzf6{AA3!B~4B`jJh=~KI9n_hDnqwR7VM{H96IJ2h8~3S^SLX zK5nAxMRIp*vX`OUW8Be=ja);?BQHkpt*Y3^#yQZwnNPDsBM%DsHv(h5g^%7GtV0=T zF&n$Vq1#3ZmKx_V)HZEOoT9=VkOqgtN6|49fu0K=`$&_OTq(;+-cpg@ZVD4oww)k**L92k z>NwHy?`HU=OW&n+*gm7eU)(#5JoE8xD}lbJaB+$^MlT?Qb_Lw>Y3kTO7mII7dNZ{p zM|x^f9J^sZ{SdnoB0@yYxe+*kT6jGh8A?W8)dOTE*hVI^36cHf22d9&G#*>S-zK@@ z`A8*$qhh=mcz4lI7gR0KMoUyC(AiWPM$Gbqq;c9!=&@MCt_u6e3^fVgzJ>rGG?2RN zhZxlKEW*8UmWqPqi;lezK2hD$3AvBzg~9=^VNtp+qm5$3^eR8>Ji>0D!*A(385?EhCu0=HNov?kUv0p(pZ-?4ET}VpuX$gb~pM8+6a2ChOZFO zP3rPIIMv!B+3X+{qpm$hca@Ot3)d=8cPA9e6IY~VO+%ygR06(q2U_H#U%B~%|2jRZ z)&l;T0y2UtX=1-(O`41a*j0@gdGAAIF)Y?m94^RQrgu^Y#Me_Mf$Au*@Vc3nvP^ zosjw-W&2nKp|PY98>H>t7J{;s-xq~6$!|I&XKVRb%hk5ndCIZD7)$5 z&@P=qVUvzyOU@hF2JZ>nX1;|g(w}`<3iGE@J7>!|vKc~362qF3hi+x`_Uv_mDcC6h z#shX#@0~anjtHL$LK(>{gkT1;mv2ds> zq%g9ZkuV>ZI(-cG)QSP)pmXD!^Ij#;vZtD7k&#jFXQLd%dh$wTbgFRGW;MA5fH|pu zWU^-gJ*1xS>4muLN2bE8Y%#aEgg(9KbTMj zq=DFh+4OHa3>rvP>uS9mc^XG05H3-bR455zryQLXl}2-Dpa9xsda8?X@hLk|OA?MxXW zfCMP7cs{SM1GSBn75(k;5{H{uhd26`dI!&mz`1w~QQCPY67V_>qM@{g$w~`lZD*qm zR|#vYygP>F8-uF1vX}|H`X26=s8S?#35dRu_(52w9D86iI=$V!r<{4h*DjYf*<4A# zOui*?#u;!j=m}DnD)9yr%$hs2oTiK2iNPLKROqV*2CZK>q)$dolS5V&3+1nLIyAth zAb^5tTi62%M_OPx4BZ-`_PR{IlZ$Q=_D#cx?2Z^U1y=7xFv+r_4$NDrxW<@+wr`$a zu?usb&?t;BrjAr*Tz%s%-q1{E%f4nE_smC-4c+%;>oZla%dj%>j6vPhAo-$_Q>eeK z+>!@5u?bpZv1qZ5pl@b90a#SlFyu;o`CQCIl~OQQ!*1c;c%Ip)ed4(FUV{N>C* zvgfWbVU3PQ%9+_Wib@-3C$B&1!70fUm$h4)W~$QI_KWt zm9zfi^V8Qm9fC}YeR9}bdHz-MGlCn`SU5g?kBbrFA>z_h~^nHI;-W~5y zrJhNV68vy#os7<}~_KmBVH=l2AxsST7~hq?-K2 z{cmzaSM!Et~8xUHflTuhC$#nm>{#s5`7N*nK@MHZf<=`k5R>m-+>)gKI`Q$v5u+=VTXy~f=+bDNa}1f|3nJL z6ry5@19mY~k?VOS-6S;i-_|1lG$dWOT~%;wO&)Uas%@glDAw|YdHpk6QS+<8O2LUb z+-8g+RO>y-cls2PqzJRv9=TQkDe@E>lw!e*#ZPKsvY9}hzOqkXV%!fu(;d5vy7H5H zo>CT0YwEDV?!2S8RgXh!d?yh&+{_d?67bq5V@wGpC%Yu4z3w`>cb}&60tMTpNy$Z@ zEgY7^mFC!~`;yUy1>Xcb9yI8+v3)FR8n zZPLxk`ZR1!SGIyPF?eVY)dcFsU7&t!5$Tz_?4p&Lw%l)-{j9H4jA`PHgE_w2&_bTs zo8yFz={4!%9lj7+blSq`by9=r$wD^}so}f2Dng5VJvNfmxK@(*tkVkcM_V9$XbAHB z%J?F_EXIk(dmVuyJ#))$?S;^a(-zzDQ%6kuR#38dd`br^N2rA)hIeJz^nN3n>a1QV zpvx;a5}`v{B4Onb=i)$J<<5u+P`lY>bxk%lYRx4t$89H{T$qf88nsUHMARbKIERwc>SoKQmpDc%f(HYYJAU;JD%RZpiym zxW3i8q*36Z9b<$5V@_H5?CW^OEM_mB3;gtT-jzCTkExC^L&dqFoGOyJgsOa7dKi};9tXiqtUkl z=9iTQ>PS+g709m}7B}KI%EpR}B#mro??we&LLn>QMVH@K^Q29ggQz{oahNC$Zwo)W zHRSE0V{LS10StD_WbOUKq^;o4nw5f@qt<77ts%(ryrx4--b&j@$etba`x9xNiXzmpS&udb&7Z2X)^__heO{-&eNa8v4<4I z^v*fg9$CB}wH%&`5q6oJgxhRYcX$ONU6PDL1>E#YFkJkk<=%$}>MfyA>xIrlOF@@a z1Fy3Ap3X7L0vk0w`$r{C@FWxPkXskURs##c! zx3MB(a5pGSPSojJg>E#?c8jc>E$Py>rLrO6tlYApH*aSg#h(Uz(wcOe4f)Fb*zn6P9H^W1eV4AuVo#4Ut4Vg% zJ9^_5*R1l?!A%>Q#{9gG$oMs8OwZ=}iXDY%2x2W7+$dTzJ7DGEb5I32*zlX^J9Qm9 z&;0g!SJJ{DwB5JdY;7~B(CWbq1MM%2WOLP5n!<3cvI&`cna2mIDc5KC`R*_84pNe# zMxh&uq+z(d%RO&g**x^EfojT-TI_%fHr{?VxNnzn0IF$ZWLfV41UHO>>MX8)BIQJM zN6OAa7ja>!HJ@+^kqiUrB%^VMWCuIJek~7AJodjUwH5vDA7;h+gv|`FpSjfi=G0Tq zSE<)5)Zc=uo!hi4l#CLYq*|7HRB?}uV*STCc(JqvI4HG@^sy=3putV2&5IP`9+AZI z(SRtByV@+TYvXFQ^kSsC-g%c`e9AQj%Dy!7cnc=tR{tqaAa>|)Sx}W>0M)J$#jcKW zSmrKm5aEMz=9NjypRF5roPnm;t3vr5H`#!zx++ni2+W)n=od2E>P>TnRsFvw zZF>fR^zsZW~qKQxa#;DdE7q}WG?DDInRJB-)^1vo?fnh?<8} zO}TYF(s#`*q-i|v?)8*VI+t&m&iD*`dHCf8i+RP|!-K8u-_5lFt*@>27Ks$g!|I^9 z2E$n1bW;L~R4+LX3tOt9@ zXD?a}Z@N^zF{o*&FMFzc774t26ct2;tg?0*WvUJX_i~+m1kbN{AI&m~JF9->8Gow9 zf2k1>KWHf|_&Jej>jISQy1@NT%33a(ly2#ov;HCOm#tj~HHW`=q*}(BwsH>1o)OxS z`_L-Gg;4o4c8p!uFP$JKRCYS9KRLz{V%GLDNX#sC-K1`Xco1b78wc*3M`cx8^eG9Q zePOu2F|!s&E`Mp6BNZ@wGX}BR@|I>gD;IA|youF1nk3(wCWwzarD!C`rlD&?P}5OR zHHt3js0*wa7GdyG8m-L%s#t?5+PV-^eLG_-2+2Y+bVk)CSxGqSWN(JK!A0oRb1T8F ze0Hjo@}@6m#oRDY!n9kwxFO$95GSzf6*6tk)#f=5@>DCZj2^XfUS%W-%s{Ds*YrKT z%{Q+wuRW|-8%fdWU%;Q|8erZp$wkdQWD@leG$Q-xWMAxbGb~x)E}w#qIXo*$M-p{E7 zrP9i9(EBs*{c#oo2hELP^(Mr>@?jSRxS4mJ9@S%|Fe^eY-Uo(GwgGgy0i!y^zd56fNY*Lr^>r5-WoiChvLt^ZH=(oZP8%g|C)il#7*RJV;t%Y;}&T)2^)(`|oGju#-^1}s8Y6EsR4p&d^p+RmA zXEGn)7R@IawVx!76YU%3T~ig#iq^8oHb^$}84D$4u)4PeELb13)%%?cRyqQV<~_(m2Jy)-78Vp|g;dKa>xu~>NGGduC+a+({BJ_!bH{j4 zU}*?5xX*oHl85bAuP_C9Jlk9DXSRDslm&FWiVfmJNh$n)CTbm`0(%w0_kOaS=qV=Y~c(C?g8eN|>cuC&oW@ZFM~idh$AI z&xDgE<#?`yi?n9V`&sxgzVvE0@|ByUeiWBtFk$0@jX&Y=qD@KAc0!>bV{Mk_e zbg#6CvLdpkO!Y62v8xcbd?v48SpO4TcZ2LSV~5mjuC1(O{N#*gesmn-oKtGDet(Vs zfjvd~^2*dXc-hspFFKUN#44$9sl61nCW~|LfYMxrl>8L$kVe`@^JV!fK*(3=N})M^ zkMG= za)*3h&U9I~^2wFgB6@HXg5mi1EnC=-YJ>zeNVs0N3=AEVwK6~jWG2oj8cb3Mseqqk zgmd*Nz=AB|iIiIDIPB!M*v7^vO?^#~5^Ir>{G(ws{H9o{uzOl7e&>16wmda5&J8T4 z_<>Tr%xvK&F=2*RjB(;A-_`Se%=CPAl6aOmYoM+-9gGat3xly6jz@;^qC2u5CfQG> z`}Z2<)C3(*?LkG{V(TYCmZyzAK{hmyMPKdg^sNq$~xI>3(Vp*cj4?N%51O!F= zd_T;r6zWhsfI2x43$Hr_MsRfJ_;J`he!lR8=VQ{(mVtT4z=&Qz%dRvppXf+Vsdacy zr2M?f1bWW3B@~Oy;VCY5EE^JpgZh|>)%2j#+W6>*-du~^rO_OeZ0y5t^tNYGGSuOE z`GS14jzeSL$e9gS-Fn3?qC>73L8WSXc1_+M05FFsXlAs8=8xxWOD^UYPzdc73%R0Y z35;GBi$OTtBc9Q6v@xS$PLTEi^5CDv<-)iSwDHuJtAeJO#6fCmT#k7l=KgJT&&hlg z+9*mlLtb2DeKqEXNgYNv!xi3Kw}Lp?S?2CsDw>LEQ_hH;KiqwQh+c~|V^GeNW}ZNP7V@DvtnnhcUK>o9DTWGvYSvJ!%dm{@HraGRORrs?G+=)5P&q@6E8fKI zgdL%-3*{W-kP%M>MbYrfpbFZ?JJ%d^S+?E__ntnr>25X9EQkepZIkCZbjmS#aWwfU z7h>mQ(bJR|0F2@Kz8}IrdEaIAXxj0v?Hc1zW!2^ol=aakBg*IE(_5t7_i<`Abn<7v z5J)rqS#$-UC0+np3g-_x2S7`29@GTAI(SlU^ei4Agd@Lcry3EbdD8>5tV?hOcQ8z- z*^gl}k>52b))*??lfa9_vBfJ$@c$}cypIZf2^ipMc>Gg2q5LDjosOT zsVHwjme(sZ zH)p~9a?ue44usjd&V#BZ0HI3?+0J-)T9(rtqziGNt=}tqC0mM*S8-WzC2#f^4YC~* zuu|ac_Mv!&{x6WSuV~7}pITyu?#e~r_q|)Do&73N70zq_^Q=(Sj31$Yi%)*xCt!;F zcG-~G_tleTlGBeafPeixwf=ykSAWjQdyFR{mw36|*8A?b*u|}! z*~Qau(#eC09Qq#YF~Biue!kzh?QZ8!^cb&$DvQuBjN4z7-|!sK+bv~EgzZu$;BETC z({p;4Xtwf39p4{!C220i-R0j}>7$-`y=0QGY}2DIh3i_C4TB!jy$ra#+l2 zvW-?!%Xk6O_hN;$ZkI&pHB*zGSj#B%M8DJ056EI!y2t-M%uf-xQ^p8GL$5t@sa^iz zWnW^ItmmF}$(iLQxZKaa&{G2itI-#Ukfxob$w8-;zDHbxsSJPjm`Btxcv#+j^LKzs z6|p>+rX6Z2J&0FFyB@=5lyP8kbf@G`km_7*`QM%IqBkfA(&}RkOuFN&qt-?z*hkHS z9;*Ziexd|`R{|!kTpD(kn9sK*YEbM`uI6|~ntL`a<~NSz*NOlK-uKU6$KAI(Hx#ET z=LiX#B{Oe(6ZoZqBnd9&E zo7}IJY^r$G!3xI1SdI)aoB$|RZ+l7C1s`a>e9C{<{||BGzy2ZqlLN;zv!u%1Xl)bo zelL58GvA$GBijMR8cOP|Ekec$Z@l^=vI}b&kUeNrvpZ(WMe1G?KWHX|3=Nh*xb~iYF z{&1&Vx`;*cUxEMvGHsSwVTwkrfaOO``K4Q_N#S=C|JVDZgplq}?*RUv#o_K++Ybio zB~K8v1<-1%CIYtLHEx?!QYFjEu%unZAkcNGctDsF{8xzZ`%^gK>5xalljO3whQe18 z*7_~)^?%S%rH*4NdkA9G5J919*~}RJ%S=@>5S5$)8JCB;=t@X%h0%|L)zV9M|2_Qr zb9lDc0MPd__qXn7KI5?q>QZDYMNVOBI|<#k5z%?qPNP2Z9866!%kA*${ws7w(>xIp zdWw3vTR`=TO7fq9*&s=0#nbNYl0+uc(WE|5R(Cn^jC=8R>F(G9+i6t!=$csmV7!)V zZibw`TLtUL*Z)X1evh~X%a8Q!#>_(`GV~+6HNNbNw8o~!acL;r=QinjSYp!kz;U6Q z7leAQvnn*`X5!y5>c1~NR>~jyeZdvlo#Zn`mCGYVh~kK&8JeKw`&4O6pJDiCHT<B*Hy?E|Hacb?C^QmFxW)d&W@4a+Odv?3)Nhj&sn-bD`4{Fm*SScs(u(4$(XxQ$f1V@3A9@nJBN>dZKX30W{$vW|rCRX?EGD}?0?+f*>0s#IKPaHUq zB~}y*{@anx5(K{R(dkOpe>;$AWx<0bh{mQ{?$?x2qWsxPC*1(sce#QwaYi3YWka{#gzL|15_;R@^_! z;a^+vpXKn+a`?AH`Jd(R|7bagww(otJhBRd27(H!(T5c;zmW{5%g_vG$}dOn%fIPbPPILS#V@y#d=>*P^vH(2Rl`Jxa0Hiv_*Lc(|*|mqwiS7%rHa}9tdLOQW zmQpBN%Cy~Zfi8k56sZ5oCPOBW!)kO0=$;F_c1t?_5HRqo0j5KxT=TCWMq?Y?*TbHS zKM4Ny27-}ab5wK3V;&fd1Kk2t-5Nl@wI%|D?;6nLb_AAfY7?zx5)A-c^FtWelIy7g z_Nd0qr3EU3GeD3K+}z{m{)#PR@d1nU+r2+SqLjh20G2Q73aFpe{-iYJS=~UmxC(Tp zvcy}{pHWK})m0&v zym&rqt(ij5mK?#On(?MDjsTUH1O-~!6X=SmHPFz^f1(*u3-G&5q*$Z{F(`U`OrPw& z0UpM^^Kkgr)6V53flzXAd)DmF3CU8Pu3AiTJVSJ0V@sAzH&Dqn0Z_dCKV565g90FV z6+jZU2sO2e9NX^!QS}P#914N~1`)b*JTf4lEU9F9|0}q1!V4%T79*?veDaw7^v_@} zm#M>{irUNGm|T75XkC}s3a>UrDNSiUIbT){VoaliMGroBN(v0D}zWB z15Y+xGA{VVilEdG29M5NZ0-GXcg$lMKMNGS| z^E)jm*y>jnIm}DDexp*a#I6Ioshx5r)9V6uDR=>(ey3YyOoBS4W*=&H`egc90bK5) z8k$^i>BcZnH*z{5hHUssYogr%ZlM3e)WK`=M{|^!+p5|Cthfe1)*^1U`k;wf0GweW zVXnZ0wdQE6gAJ+G`+d6(hRrZnET~x%+{+Zfwc&sUg^O+NrUdQRlbuWv^bTOc!SyEX zyGFyO09xzvdiWV~fv@zAoew7K>~7n}ATp0;4fRddaeMVA&h>|b@bU2~$NpoF&2KdQ zkEZ|y)sdF>BoglV%^E<3G&ghLw9atIcWTVRa%OUpHMJhlh7hUFR?hUm$_rx#cqU$y za}Q-otKZf~@Ef;(DxK&NIjPkK{rCysbFR)NS;byZe|)&p@P2IqG=3YL*C!`nz+*?Q z=inQcSFbey#A|M&JYdV|(c`M>x{;HN-Y3|p#PUcj$+~KCj46;&Lglcr?d&3Lgy|C(3gT?Jcw~EO54UB zPf9(^3{suHH)UNu+5+qX#xUzs^##=`&zD2isume4UbS7?1IjO7;3r@j`g(j&1A7^D z%0s|guzF=+69orKMclae9Qt*S^X0Q6UwJHj4it1R`kla_Il~M8`oj&oar@T0yA<^6 zJ%07hi3f?UlTusWe8tr$d+HG>c9!_sb=dlLH&qhS?_m(3Pbx+SSQzq#bqyQ)TENLW zl63`kfrQdd`x`nSPjK(Lk(e|*hA@xRnB6T>!-uEH$9@Kp7qXIHq2~aI#2(JPrn8t~ zefc3>S6#T*C~sNwA=0m>x5*3qdS>dY+ua|^M4)A&IxkOGH526a3Kl0)H}9fG0Wh?r zA{Ac0|Bb75OK{2>$kRuLV6xYAp_Jix1i$}myhWP2d!Zr4nU5iSV_6EO3*iW@AHvy~ zN8fY0AQV6?1Zz2D?u(f#?U$1gF&!-`(?hG11rc`U4w*NMG%Ia>!5CY2>v3pk=c1lX zV$l`)gViM-bmdI=1g@uw=}@fL_G$&QnEt_)2}I*c2A|6z;g7BZK{_um{yce!&;sM7lwG~PjUZ6 zZiA9m?m})Z{>kt5?Y?K%D^5d2z)3>j?>jQsTl68LjalTNtEroV7FWzSb}uLIKPy407>r0{^%9(&1G}-H75`~qSCoZ1(>Ju_x zpQ;R2pJ3qLcRfxi<%Vt`^2^6qi+YDtS8C@z%6!aVV47ReF->%~Aj;Nu&_@HXds{t_ zbIGxuBl~r$rj&u6NJTjd=1;*dQI)SskY{He0o1qj&LoPH))3JzCnVnUS#%V*bt&;~ zID(0TW+wAms-+t3L{kvW50~swHMeuo;$pcnG3B&kc$txP9ol6pbFo_3LHSa(R`ECh z>iY}w-YOY;nJqywZ~d_I$)>H>cD%oX1w36=ialR4HN~Y4H(I@04|G2K4@=V!fSxar z4~&iSiO-E<{Nc2^oDp{Q^HMBlAD-lw84$8sSI0&Wl+UEe` z5@db;(^pl`E5yQqeW-t(H{8^M6djhT^?JOncKLgWegzP7FJXce11WQmSIkew1 z_aF>;VYTJ}Zebc!`FM3(qdzIz>Bk`?rH_mJQzB(6HJtC{%y)ARU;$2B)mjfqlvQ$L z3}{p&b|wi6(POf{ewp8uyYjYUvPX|M=OFpy$aJt=9s2ZkVv|9Jgr=HyOBkcRz}^{( z$J12mbWH|nekOP?8&+KU8Fpe9+L+FQo6xfBt$MIg2`FJ!i3>}l|C)A(aRQKixp4r{ z^sy}Y5{^+o36h3grQYw5WY_Xp^|6Z0SD({_NDZxkpv%nE?cn4z@!z@YVRlhQ-Y_Cs zg6pOyOR5XXts^bTD}YCOa?68x3b*E(3!yCb{OMoq3@a*SkRCQV_{=uXTdiH+qR<|l zN3rA4d{I)ReNMgc;=t$w6n}bMo7Z`RM?JYjjvS1zx^}0Dtq|skYUk~-l=b@<#ob&= z-3a!V^$vvz6aIpc#dj=|^)Q9Ys9g9igyN7L#r+X1!jf*mT!mzU$r;nmEvwAi1tsgJ zG0~8C61ByZ0n=UweHzp&;$I2F4{8wQA)iDF{uzngU`jn68lc zuu_&-jTW2f9wbUTQihHXEGf>*hjQ?JFeq*yqH{yPC3JJLk_6^jT#i&De`Rub^ z{Qd*|JG%7;3-J*^=xTd;FIM9Iiu^s-molp~gbyib2)jxE=~#B)Ds{FM@>%Tik}0lF zl!C1L(PBb7bo8CwYYz!!skvrCYntiz)N@UH85ta`r+e7<~mfLBJXO6Z?4-e(_) zXx4q|P@hg>iLDjZOvO)e7YfHx6DkjkO6#1K`z*fo;|x8{hfKcbpnoKquR>Es@P&4e zwwlEjP)rH=o2p+n*buffIRL8mmRz=|sX(!^m}t6rcDdQs*TP8+(Hd}G#Jwre@~Io+ zZQf}gt4L0bB=y&(}#e+tCkZcdn8~pUfGTPV5^qx9DA`Vs1zC$?tA-ABR~N&8v|21Ibn@k`}jCsY^* za>Dk0l_-5Zz{xwzCjRKpqu5Lpc>U@4qU;_bJbmue7l`)b!+tZmo$X^!O~Q&eEf8;c ztY0OB8p%kK10IdKrJ~)v1UuP-_u9oQ=Q0(`+!t?$JuX%l{B%#b_901KKm$VK9RWJG zY^g!ws$Fo1l{FlA)wNoNh>JDVW)E>yPW#2Fu0)@vJ)LmUL41j~nlG|wyc(BqcAYuOdf14nxAqs_?&(l@Vg7M;R?oT%~TWI2;u zSB3bBx~_Aidd4JK`uKT~%Q;*wuy$_xB=xkkb#V3M+-}P)dulG#Se*o9NANQqSNq^G z(=MBTT;#^@s_G8{-!iB7xTkLjf3-I>ZWB=NJK;m+cp=w6TMH-fkt`R}2AFL{$bbu9PI+;ULv?0yeLJ~!Hbzt7QHSj+JF(+& z_zt8F2*R*p+4*bxO@(yg4lm$i31hqubZ52PzJg^+%dASJ92RgrgIHXuOWLZCCamB+`{BA9*Tfn*E|!_OD~4{Gyqd zLj2R;JBIJF0xLy&#@lqFLT|FW)IKj7rLOQE#7}BZh|Iquiw=G4H%5?c=tzpxKkSPp z;l#{gI8|N=eKO+bDJLe4OqF&_Ihr|mSag1Y{l;pf;=z1Jv^pxg{2@TcG}_1UaMqU& zpR<52g^O4R4;xW)pp)}1&OG1qJwt3_s|r&U480!)jX?@_e$eURqWUy>>xJQ^(3H@0 z|F)^8m;$!-@`Bs-Z*FICY$SUNRoA&~{%nM~{0w52=&*1qDPT^xUzE+)Dxt7)*05mD z0yFZu^jW<@VIZ{E1)stBTV|=L=i{hj!iIX}eurkfgwHp7k3+XnigUZl3FN3V znAcl8tq$7^4&QI;J;H>Aq*@nCNixEmW-1GhiwU!gs7X)--Iu%=tmdqB2dzOIodjo^ z?%oQ+ia+!a2aY_h!kweniLzGO8fA_*RjSdR>gs;RF1~OwV_XvQs|Zk9ed-=$ zRp0nmy#B+U5X74g_sZa~F3S|cfN_we>W$(hwFElgTBAelK*jL3ZA}tcJWKbzkY`@z zVOJOdk0Gxk^YM>^6{$^o02CIC|H3&n-gw9WU7exk)LBBSxBG&`XbP#m-U3P&E2C_Q zZQMPNBN%Mb$|gWfhgJ0+uaDB%H^GG1@quh*#6(oYxTfd;lE!8g2-kH>RH(VIee(@T zDX_9kuet|e&svjse|2V1QT|<6Mqjxb)zHXWO_na%80s_$D*p<|VQ*N*GE*_X2L?5t zUiE!)gYEr z+g%n?o=QAOzdIEqgf5LhTEY=qgN46t?{lSfqPc;!*_6MI$nLJ*^6cG zF91)trI5#^U{}WFanx(9y@bE-^C=zbqrIIaFEH~auB+%q_^_958etZ~i2bTAi(~t} zOgH0~bkqqup~|d&gPJ@uhB3urm-TWGp!B!bogTzu)B&_y(2@NZHMV$>Nk7!2eUTTr zq=L53eSL95oY2%ksCwqur3|@VUQ6#|c$t!CGrN}HO??-8Jg;n6txWs!^q>|yi=IFW zgO^)ibKe>d??I|pWVma;hk&0}T3*w|mYFI<0FTk_>tgweIO?T*%_g87r*7sb5VQz% z2GNnDK$7@Uhpz7P2OkqzUYu64JnQW8;#f7?>XYB|+i^`7w;m2UoBtp7-ZQMJcIy@v z1QiicK#*=hkgiDYs3YJt|v)w)ELf5*8_=PxiIq7(xEboKj3Yl{LFgb^ff={+g|V z3E`ahZR@L&g$~6$ica(w^veufK2JG4cJ8yr`wVm2ZI^2opLcF1=(}V+ThLdZbnOwW z_qOq97T0NBD!xQPdmx!u{*ildr<+%}5`s3W-5C4y98{#FMeutQNC(~Sm&Q@#Io+KZ zM>MSB0$s~P}PtpY1bOD+f}dL-zpgFy9#~jAcDl-YUmbOUN{fsA990}@}FfE?$}7KnFo4n{wFW}?j!cMHsL zWKWHc=kBQZXqMr&FWi*LH2B-mk=BCM7m6?cgS(#{ced$hcQQ=%v*=k|V4FGYzLEsQ zp7E5iXxr`9DKPvPCIV_&{T3C=BOsfg{?Lm5mc2rN<_n2R#U}!aM+} z0)pzJ8k>5wif!4*XKc$!hEUsR0gGCDy%s|ovsRrm4;S&7G@M&gKuMKyGE>fvo1_s{ zP=44AnWOl+%eoAR9og0wR^)f zIDj8s?M=DU>{-+l81{zKqij2L&#<=ZtX`pfp5^{6#jTN#`jF?|CY(_WVY z>Gq*3^USvC+C>IV)#;rHJJc+-&ig*i4qxhNYavT}+cw#ItSx?-YmNV4Vg;EZZ@P@X zU1BYamfGrxWw7+FmJU7)DwNM=9ZI}?>qrnWcs%a zMyH?+w=6etaw*?6fS%1^XSYywML~k>;iQH{^EI%SwsJWCZQ{JdItnyo8ho~wd~9lR zBG*KztQ!nZ$P>=(IhbrP{_-GUU(!?=yX|X&itD0EkLnCJW_FHy>j*5+)TAKP`_-z7 z@Y~SkF5#_7&``=KNLS(Mi?5Fs8DMfvEz$xgL__ltX%poncp&-r9_}KzrDf+LuBR77 zJROkRORsjn+8=oFO>;(zvHarB@d^%=Rd2z{rvUUf+X4w`+{`0f&jDH;UTqJTYZ{;{0Xr{zWR``vfM{LvvQQ{cP-r?wu}pXorr0dkx%E+ zrgy+s7bx2}eGc&DoVdqt>+_S^T)K6m800vmIw(1lzcW>@=>YSArAL~S*loh zqMfuHkWvdS|{q!OAq9h2K)dbfYsA9{2g)e`qqf|YIhzRBJT^Q3z+^*jEC2s2|m)Zb5Qp(d|HP05qoPQ z7lknly^gvUK34Z&9%n52PTbS9L9>|EYQJLAkD|6*dBr)^A?I+S_L;hc_qQ+)sRgqg z?yMMz%{WMgOoXgPJ_wi4 zv)v7>-MK~211)Vl@Ao5dXLELzpED*~KQDnh|NUO@MDc-P>)A*_!K3~Wt~VpkzI66~ zlK=B8KJuVY`B^FL%l3!w+{ajPF}Mo|4L3i6FrF*fEjba7As>rq=N>3jbWT2rHf}!q zgZB$7Lhg*FRh~9ID}=?V8bi0hQ`8d^06=>>h?U{`)C7uwyC+H5#WmPi%J$NU-onX< z49yiy#~R1c8hsxCK};3LymsT~IdltM5>nN-)YV zVwUECt)sa6U=4S0q&D&p*&rlMzHw&Ku<)*W^%cF%(l+tNxeYx8!Gx7^>?xmKx z0l)*kjR#xAD=-G1F=Xu%$N-}0sJ$ETcTL^j9;aF!iTld+Ib@hCE+`QDBOoW3N3HXQ zhP%|nq~OQRhQY>#l@`>Z{3>MwF_;%v<9P1&2f=>J1NApd4O-t$lS0HR1KX&Ee?dbE~T?OA)H zvoG%Z7*+f3l$@x2hUs8j^w29eS;X{l<|$@ByJ1VVHx@DL`#{S!E*CCR%kDXLRa;9i zh=cOBSc$BRW@$9C+6Bl-%43$%<*x`bln%i2|JE2X# z8TMRi+J!|qjS%qgtQPVJZOaf!`*7;XQAs%YS?7+eie;2St8=k1rfbiA)`qZPA!w$Y zN-f`OnU1<{inFtoJEt@A!{5x z4uapjf{EZZu5}Nw)j?=K2^2iA;(dX6202;=kS27JE^t?OfF$$LMQ!F1Y`p9Tx{CCR zX7x2UC{6b9OzhnUWvZ7}*%wPKG>e)ZJP1E3aGGXKtSkEQ6j8jo9Pr0vv&AUBC^`MU zX8q6Z_H!|w?8C-bg=6p3-&pcHP${c~LL(`ggt!TEIYH<2Ee-z8%B`y?)AyKhyHBFa z70=en`*Tgpx(^&amWfJKMr)NBWlZGwx1!}274?rT7MYy;>3Wo$$n5LE@(&1m`gY=V94iam!4AVx$w{+kFz6 zsC)Y%CRK*n(q-xdqYFZ1ntO&1Egt9iJqWUIEC^KD=HRDwQx|mSCdKNs^bAGV7bpIGxFVYa zw4@0)wf`|{3o0tZPvq>NSy4=! z)D(4BSbmy%&3wmnAX6@Hv-;opjYTASXzICxzp>%-Tos6uSTH=V$)ngCx3fNpBjJh8 zhrfP8dF2iN{p&6PC2;5R%Zq=1SnSG=ong&JoI+Pba2_)@IH)onB@$T3^Zu+mEoIzr<@~qei{ri{vJI-DBPNH$j7{?C&R~ly= zpptHIvG>{hH$p5siBkJ;_2R^Tqtv>Sc$^vedGG%#8-TS$<6j2x97^KU z#<`0o{WoT?JBdunUiQ%LzmZ7?NrYCfcQH#Me=hF74*%Dy=P{%^mq$3W{x438Y2n{m$5C3Dqj)2UWcL ztTgY2-sn}a(1qzlyuQ}OcTI$zH~;Pp?VM}Z@7%e2mEUjsa9|Vb;gz{Pv+6T@kg~bw zFTZ&pI}ng{@OpC`7m%^4F|^hH?aB$VGm0n3F9e^U_&;CDao?gO$8*s0NdNcuTsT8< zK?`>A|NQXZhs+iR@7SZ1d3*Q2od>*?+#dg*zQLb^>;O0q-|~n@=YRPkii!~S|M)Zh zaggUN7Zeqznbz)~{a=3ZnWEy8f6n?$$)MBPDo>v0w5or_yySu*9`GMoVC+Tl( zfc}0TMtnKl4IR!II0g|L(H$3Sd41}6;LbqmHjt$eB>Q@nzx2YAe4f&_!uy8JmV+rk z;o}G_ZQAN~j*(irT(CxCX5PKj00edONii^;xH#=KJ5AEZxR<0rC+kC{f$+i82K~BM z4?c`mW-`P66@1?+Gp-naOd>FwMa2h`9KyM?&l#OD7aIT>%LG|gXWWDPIMvEqm|jKr zNE=u|0J{zLLi?CneuN3IgC^yyFCEWY4G!`Wm_AMq_p)6MFmsI1;L@#Hs*10$Jta4P zbO}E~PAzcjDX$#9D9;$Caa&n`vuxVAe%kY7641RpNBWIC8SXmzokE~7`9wrSF~@(^ zWVU;2uW|OsIao(rDo#hdQ!mT*Xi9WgW0=IZ;^yIcCKpe^-6Km_OtNtHxlvwPwgG^8 zGeK09d>-;5y(Dl;&&jR?pQ_DbhH`rWZWNld`$)-Jx_?igx_2%!khtosN>9`@+SO6>EbI~yc?Ic(1vY=)uv*s?6QNu`k%^WsP9)$9!ND8V|z zGrgL`DG6XYPslf(-2};RX&T_2-V-oaTqo^K@{)QG;_@mOpCTIAd|`~;eNYKPIjJIv zEUkLgxRmN}cOoA?E+~;HzeVHX{lf3Z$J5gQs9dd^_B5#n?Z5^AY7GJLSyN{~;oH>L zp{kFiAPy;HfzFANgWmWqx&2ly%N5r+tuW{@CmN-|w;#$t>WOG^4pkS!=sT+wD^rD{B00k-}8hWw1Gbod~ zICv&lfP+LMQ7zIHFwWI5Yyw;7YEJ3EWzFOu!1N0ltOb53ED_pYgY%Am-#qR5JWtUg^qB!B8NTs6V-o(Hy-9dM{z8 z>OfF?fgYCM0xR7Hh`P~A4P8pvoJVfLVns4ery=puELez^qtNRrsSVK17$vS~22B7m zO|vnnzwP#R_ewsZ^L=1V0>>k~F9X;|5Fqa9do}3#&k@1NE>X>9AWmok$e%$y{82UL z01SU1$wa9$YRe!8^E89+KFj~H7ngOI-@B?c!%8@$vB`O3cSa*PIPF8Vtn__~ri{kK z`g@m8@dSO>T?I4Le2^nt%WkdXEfec#F|{M;&XeJjKkpC2mVLM}9ye)TW(A&6O#QO| zIQ5srM~63UMU4%s4^vO;DF%SuleX3|IP%rgEOTooNe>AK+FFBglHHc+^P{}wh)$`c z5s#u+!i!*EfjG-njCu@`0wb9RJ;MS0gJJ4DZnxV-z zgm_V-jf~BQHUi7gw;jtH>f)O-2Qz#62(3EizVdOP=d{LXY?p(v4FrBfdi*(>)SpsV zYZt8U6>$dTt{31DKUs0hn3zBVHx@Fj(mo&N?Oa@tc-FOxamRfaV!&eHzYP|+J*%n= z0PRuA#vm8}dDe`zYP@Eh_4X90Pqli6+ih0_v zXFLrAdvi5!9}j08GdQDwd29%}_^6lTKtHiJ!>wPcpYzoUhxb=9iOr_%QzpHf#KG_> zK;la}cx|TpKCP@)(|?ZM8IYl>O|0dShsS`&`1JTIC(psFsvw~~q{UG;iB{khs5JNZ zw`rkuEG{xdt zYg4y^NJE1TXv?k1jEP-Xz^+NyG@x`}##gTyfJQpBbCW*K)sv?n`VsmcI#WGn?d9h z@)a;0K<1f0U5Ym#+^M1}c}fbB6bPT^J}?z%&@=pSZ+pPK-u4ZHfRbaPV9Lidf*`;o zOB%Pj`A-VF>K(*KFM&Wk)x6<>;-}Gp7dgBzKE~oA!n&0;Mo=!`;u^g#eCvUED8KdP z`Udcl)Jonocr7o&y;6lA&uJekk=D3EcZ;{vC$J<|!7=#0GA`xaf*_bU0}iq$e)(}L zx_7Y_M{3%P`58=VHOm5LUoA3#?-h+`N=mgVs+MS-0d|pAsT-pWsNpn1c2Z)?#R)gTr ziC>&h@}H{T!0s%&ycE*XB4hItiExvHy5Zev>Skl}BGb#Z(-Q6Gzb>y?AA|*&{9??q zn5qc`RB^@*`q^KAXNTLO&YgP7kZDmD-+KgdR`33rJ4{6~>vjOU;T*xVJ18aiZb` z-euZD2lXV4f!8=6rF%WX=O@~#pS|%M01B%Z{QY~VE_5j|?-!)!3&ti(tsY~su+y}E zsak~RU@P$UyZ!p*H5g%3_-hBnH_A}Kk< z`)Ky}A_5NDy1ki%xTZvlng!za-P%N^IwOX#ESq(s-CZxRt*>`9(EJLVJ%I+78@P0x zb6=&0I---}`ebNF<9C>;v3V-$%K?+D^*cOMi(pWLnWa=8p#GJS9IJI^lZM1 zPo^ZdoLZigwQaz7Qp--k?c)S<;a?6Zf`dS@vV~CY)y$8}VtQJ8*dt9HIF+S#fCDC( z7}S-*8e7oS`kDXr^}b2(2}Ks~;UhPeK%xo3oM5qjrR*ND%rkEnX7B=SuzscgA-zq? zM0Vo3ZklbrY15CQs*IZfkbL!T-b(k?mp$`WDrQBLyuh}-9*5$z?}lb9-u-=5w;#ZT zQ}6Hb9v6$`=D5sdoZ_p=S_L6AM`?J(=MOJ-0BHDV5+k$e{91TWbd3mUGfYb zWX!PS-J`pFx*dqc*1MM6+}I&{FWvGX;HX`whnEsEFm`T1d$|Ff>pJ^IEWfRP!)0Rb zS1PgxW)@odT2FaV zwQ*%fZO_#Tn~;diCR!6}g)as$ks;;dS-5-$KLoz>?L&@~f=&nd1YaDZ3Vr&%#D?`D z{)0NIGBb>))qK18MowKf*OSHBmineAgydW9Inb1`7kYv7k!Xqs`ub{7IB~d7p9*zJ z-T;_Jxk9aOS)$RjgzPt#)Ar@MqD5Rwb=8vJG96j? zlBvpcpr54|WUUlE(L+k&V{NiX%E29-4i>h!?Uv7;A$uS-6Bl;%Z69akHGh%2D0cs@ zT#f81Y+aWyKs-x@YkCRUojmkie`ET*LYV`nAeSeNLT8*^<@zA(OU8iHZbe>m;IUe& z6*3{#?0nybWf9|*vjV!Es|aM37LAAj>5wFW55EH=c|NM8;qKDHFB%XQ?I-EnJ6wtE zB7&%oai=Z?nwUpXVChcrJ5p<&Ui5X^9R(>TCsCzYrP>dSJS`_nO0QfeU_SpcOx}g# z2*oEEtP3eKiRZVGNdi_m+jJPFSn~t4)+0_Fd-D`l(#Eo+Ma58`D_eg4^&OE`78$Pi znD?qT1;6cp4a97R#k3dvP)7013_7NPh4(I0ecoSPXf&tuDeDmsJPQjrCasDvzfi1D zAsZQOer8b$$wXvxVU76Ygbs@N)PGP;EcbQs87Z6yn+V6hOo*Ns@M=An?#-Go$XvCN zsrZ$~*JG$ycJh}l=jVIdtRo72UOHs2h^yCdy67fPGrK%j=6!Zr!B&%NI}Wb1b6%MY zHws5S8=77A?vIY_WxixOHIN@t<~=1qpZwV}V)kaVTgGc<*Po(d=RaE}1{hda3V+u- zMJ)fRy3U*FqN2jSSEy_W&DUst`D|mX*mb%C%1iD(*KsFYb#)Vr%B2&^SX{8P_#1{( zOQa$tksE2SF0*7|dl-9ExIQLQ1FF=zMZN8S+k=O*qc_Z7pa~>F%k9FaFs9BMmd!-f z+gQ_w9_nX}e)>XJi`<(_Zj}jrJ|s++uWkc|mwF!RaNX-tZQn;MCtR+a5V~}iF>69) zJXNy4Fmt8GqT1ikAKbCw!vaFBK%QP;T4q{OL73l#WJiGYXuhLM8hu3}H|nGAT|m`; zKfNXwl8sb?wRIZ8j3=6ZT1FXjEyCA3PU_BNqrwUqlM{DIO(#2SGstPK?qhVfCo@BC zDFxPCAWS}RtM&wpr^nxZIpqtwu;fC1-H6t4d3kMnzTRQ^<#2wPY;#y$do?#un2Hjg ze^VI1zYc9gRp@-|2QtD#2xi`^YMDsBxL+xJt>W6a`^xlukjtXX@!V;qrD3e$CcD!v z#RFTsS4#~I0|wnnYy*+jKj^8e;zwn1(P+mIgM#bjduoLkR_fStT$JBXUfU^4R!h_|ITJZ`P78$bKlB8};l`OO00YA4M~RV%y?xV>QscSmn5U_#`T}>VBR4EMb7<6hyO2^1 zKlfbHWiSbWkV7d$-VTRgDVBUqGMwF#9`)B4h!vTG#{PRHxRUV4cXJGRvf>#U`EJ)$ zg*rl7b$>AUiG2&_{wPv^LB?fPbUr^amtxij+NMMA&KpbjCBM8x!|JzQAmm3*Lw+=0 z&dU9C?uRbE!)aAb93cA)`v}i<^mv%1=8(Diz)au&RqGet=|u5G9>&m>l#;Hu=Y>Y@ zs#q3fGD3b`(ig~2P!#qQX}3HIp+G7_*E@TktEek@xcVj_Q2vYj#YsP8Mr9LPo0tT* zZqhuM&r8xNj{Azm2%fJ*III~Q1=k9PCGi->tQJieYP0K^REqkrK6e#$nr*z1tv@x> z;ak3c^~Q%uvfi5D8(+ItH3d;V;G9NY&vTM)>YoCYdw;U0 zHGHT?YB*xl)?9&O&kTPj3jZbyzQ)jMZeFsU4`u0QL>&gKS#zp4ht8H*Bc@A_y=9?y zFTz{YuB!*xtQh!4n+WLEd(V^1**!0)PLwgAB$L%GpoD!vDmuVkp+hOlha4YR^Mboa zgi(t>cH(7*ZKBHS9i3rs6+`w`jgcenVVkzCrk_yPuKhbYZIah5qn6x@9qdb?pZX4_ zvFW!rY%%gu91`0U+;KL4TX9pBCJHWFoz-iTn6aCsOq1rDUhE&t-=pwd*xLEFLyC7{)ihwHGBA{Z(Fg<_a;! zs9rDcRgG|IyITn}hT+Q4rQX9yXW&zap~9N|llBwN29OvlviiC!Nm6i%ROU1AGlh50 zjN8?rZ!{u(pe(nR9;QwfM-B5U)p7TO|Bo=n^s?rM?EhkhI4>HICt}+tcVK-#u_(+F za)A_66*JR^BaBh$7<-mLksPgs(tfcrCBbscSz))ILex(6kc>q!O+}|bn}J)JzwGx2 z#Z~-#tkat{v8B}?2IthNRonS##M-r&+-E{YYGtFh8a6RjCEd(2VJoyDo|R6aTEed+9PF`K56MEGdW zX;W^uX7{XAC~9^?Ow9K6L5h0}Yit^@=q{1|NT2E3c`L3TxlWcGL z^OS5%+UAAiHBw@MVaX!CqvG!WsAXQ@h7^+5)xF`G-r{AsbB9+tSeIwi1t>^VoYnF#n9AuZ0pXug z9r$npq$`Msc%c+`m5lQiBXaO)?8OaU$d<5RIM#@LBd6>V(D z>wuCk?%dEkbS$mR!s+*-&cCiY)TO$(p7JxWWB0es{2h-(i2~bePT4ERQV`o2ml3xD zQbpO?-7b8gn*yu%%{`A@x4rm4&xV=0NCHIr?kgTAl14rW){W(2g5HLgxEG@;yzy+A z2_3@=h8Zt2_9ltG1wPl@I;x~}WSy6&igC>E@^N(lHTruiy zc_M{(t_y55u~+)m^&gf9#Qe(CP&V?{k&c2qY(MU9k(fS(UqY3%Mh}|;7ojC_TOxLT zNrr-326Q{)noik0FZif?mzTa|>_gr_?)qd^GyFK;CjTRPZ4;2=p-UEVJ!8OkNq_G- zjA+k`d)qTND91ka=om(S^2yA--6n249-1!`xeQ?J$BDZpF3ldjc~AEAQY(sIHr9EX zv}`jQ&Z|L`n|K)g)R!ul z#UT9K%k7^%CcGEId5hd=94oFa+nlI;Gb-Htq2i>`tMfCF!$_x0n|=!HM2^-{FBY0f zMM3|D@3-Dj$i`%y8Wj_)>^w40^?k@am0N^`f6wG#~H8&6%l+XzMS|`D74Buwq7}M2-SW z+Q2tl8nf?&K!~2!Fhfmx88vDQBW7)m=Wi?M{pzCT7iapb>?t^j>oF}IGOc-0^q1A_ zWU?QZy6T<|wTHNl=owr}y{ww`C-$)xR(HEJA-Y!^=PTCy#;2wZe^8N~dGsPx`ptzm z+y#!tsi!heWi^#)N(T=xdS?XMPd;7)>Di^19iB_l(LAGU7^SG)CXI9r>_~=+7hNpW zzD^X;<}nVd_48q2t6cJa8~H|5kj~UFdBtR}N<{Tj@s>kKER@0u&h~Q?v^vG|Wi)>= z9#n6N*jnxD{xhVlO466#w5a4yV_Ru|w+IKi{jr?KEi{zQYAj<{@b+uK4EezrDcKNS9}Jd!=1hHP(~}2$2hU_1gh6mz4zg1qsTms z%a`6qBGeJgb7<>DZp+#ZORC}8zSb{dQu<8ombm%bPjZ3l2t+tey&is4D!tE!aD`5- z_9N3cPM7vZ$=9;>H>_S6knUgdV7X(3b5G%0Q@W^yyNF4kD)Jj|X)h}^!w2HK4;`lT z*x!DwjfqMq2Ix}voZ8XuJ+QOK0zu>AbT6x94=-F0k8pdoWhybD*h-0o^!9BVy3&xx zC7fWv#?>zHZefdks9=6$!S425gY`(SL98>wOFGL-HLQY& z=3u~8i-)HEd;Lf=dg9s7=NxJdcmY}Kp)Ok^vwoR)!Dy4#^=LHaVq;a9gK1W+Wbu5y zoV`yRLJjXOS=gNXPCRH0Y(T61QCfqHI&TSXHd|tgrmiCU^6VD2%hvuyeVjB4wc)GK z*lA35fAvvD)rd=T@GXuN%VIsBgqO+C?E2+-&6J+OZMqA|U(reAcyHMv{=sOAXNb12 zk`{g&llK0@JsriePmI=X3a&oIa_W;N;SB9E?r7fZy5pMS7I@2l|PJO5Gw1;3ER2Dan|_Ue85Cqp?B?wqjmMIR}rPLyxVL zn32T9+<^vjh&#--gN;9&m84Nu$8l@|8Cv;lYw2_w8=Y3Qm3oz|lZTKqJ0qUyICgeA(N#|k|c zzkJR;Y%gbZ%AO_1b1yC3zTR^0Q5C(SqTINHqU!N{*b!;2TRf{Sc}Ow;UgKk{+zku+ z9+cyiMD9u&Pp}T&nQeg~P z2Je3J)t;zLn9S^vIaez9?)Py7?YKH6qm9kGmzNxpKKJ%nnB~Omqlh)=!Yz&3d)t}O z^_Ghe3c)7C>a(|BuS4@NE(D#G2($4vvGM_*aMO-&V|!!$Md#bQ-RM{%KAF1pC8T`R zN->^RTYubX8DAi=TewMoNvmh6#&!5^MO>g#V8ZB_ht9(T-t2y4tE>E4Bm7#VHt}wb z0IF)zMVME2sp?~iV4m~|l}Y{ilY)H&W_k&5>gp#e@@A&~9aE zM1cGu_Ej)CY29S1d!k^Yu)Mc*TvvZKpUGDbs`f~ngMSK}(4IhCPYRZXhBFkp|H!HN zZbR3#g%}{M#Mx!(e_gpd^!d>2xfk#eZVv=FeHu@ej3zpz9B;-}z4yrsDpz_`MF)(; zNWJAj%e<0i8-A>v8Y>$;Gv+d~SM}U5il6n0&hQnzZ-_moLG13bu3a3ljA#Zd;}X@aCWa}7JPO8@VVN`*jL8qz;-0?>6E3?wd3|p|2h~J5an#at)%Yr8) zR&pwLQ)JreXUc`vFR1d)(-O?XV?p)!s=2afq;ykUHE+3_u^jC}FuGeTEySp`@}W=G z3vA7`UAg_SkAx7K@k?JdwbUz+h;hj!w+|BoJ=mA-q&8vH3l7{Khy$h;zGX^gUdVk= zCL4c22%x~^zq9`6ic%`Cp-fl{@Cd&ayiziX=QZ94Ib~w&e8r5nkq~v#gS6S8;51jCSEyt zT)(s>ky2jb{>4Au@sWvfegIQr!)6A!^XKcoH%3>|XWU67+|dK~oOxOIl*jT2B=)58 zq6==`X9yIHc1hFO2|-<}$TSU}fdJLPySlq~V zwsJO4WZVEZ9MGKPsMKWTT@7B`eXDgt`68#5_n^}0+Ub~D7uZ3&6Nkg$P1XqOvH|p@ zS5z)`Wk-B0o@!#JNtCj{sj!u_lThOghzQmkrLIaWm1>1`uXx!(w^aR?+NH);v%Hu1k80nvT*AbBEhc7NP zE}`ABJ70F;y);<(pPxQa;up^OZ}#e4`~2*t7_I0!jcSwi0OGh zDXSf|Z!F}ru^zZQaD4Y-Bi02NOy%^iszBov(%8@)&uIoNiD`vG$L&CusxEG$nG)jN zTF%Kp6gvKF(ZR_1Q~?sy&cvh#J$=czQ7xf!zQRSIpz|(!W8rDL{;rq>J zD~=?*{-`qRW+#?CR!$Re>M9q9Gd#ODe@7?TL{YB)LyBp(j)3zbr@+Adx9dS+lP0AA=U?dKjwJvT+8c4 zQSEq)b&VKUWK^oJ$9H~P_0#jU{tY=(WZk%0a$p19ANhtNHI$1ci)Yax59JIVDmqQH zW3HqWMb%#{IeaDhm?1XQ<){8|Q&PCHPr_&vRS`0@wNl&}IF0fgd~DPK05EN9<+pJuylK{5sPhgnX0VlaeIsBXRF>^)$;q}? z=}R`Fv|Z&6YpHC=`KM7W693a$&Pg-hNo70zs#~GOd1(OqU~B2^(jG_9<=PR8eZ7Ac zqYln_4Ldx;P)GyXExCl4hA3Ej^Z6fUgfMCCIgEO-wud|?Dxr$&b@i5R80}Wi@*xxp zluHT(psr`fEIS&{LO;U|Koe$Taso_xca~PqKb=2`x9ODggw#KWZWY$nG&n%=U3mxK z9FN?t?U#W%f8hS|lF!Ol77A{DQlXl^aN~;p=@JF_Sfbz>i3M=$M{*GSx|ND-p8(d^ns?%p;7MqExPK)D<)u#=$-S*yY8f~qQP%S z-^Y{beN7lW3WgxFeqtYu#>4zQRmQ<4>6C&!TZIE7I0K8Fla)Z3lIwt*$asz*a*ivA z?k-sKc2R&P)p1eqso2M4AQo1&!`ozjrYK>Q*8l5Cqb3q7E%oq+N$RHOiJXzerpRnr zuRI}sXnR)SbChI)vwG529J(Yj$T%xXwK`&p01J4d+js+E*$Lpu9#qRA#V}N~X zAZhV>+0RF~JCz0LX351geA^TBEWCf#zB1#NNgsiJrS&%+p(kLKIjoybOl4Sb&nnT z>z4UTMGm5W)=9(D9JGrhhLy?JrzkF&z7Bh&7A|@_%KXG|LmlGJddxK-TUKv`iTVqgLws)- zj(9Xbdh=sS)N#(gsC@CgGuDP4bCX>y7E`dpn<1`hKum~jN)qzmKDMvd&mvSQ`6Qf5 zAF&mjn@bWA;e;XN1jXs>+5>_yMS?qeP8j?3NMBq72xh1O@6`;RfV{Mn=SP5l4R2tWRrT__JqV|kus+Fnzc0ES&nw`2Ty#?E2*bF|z zaDh2s>qsldcTuVztX`WQRdC*LC=CeBC%D@P--`sNdSo^UrXs4JY{?KN_p2sq&%cy(YU8)pqNt3g= zLw2Keno$cGEjF&u=@`|5Y~gny!eq4kw9GD0!!MOMBd3ex!P6z4GAm2w@sHeY;H2Z> zaF0%(OU)bHp~g1H`thq2Gaz_r{X;xKD2%@K*68J%CT+fz6SIleV00y?5rcXAFj*9=p&0p!f7jxnqTuhJ6Z%KVYmXc>zGLC%D&@8J z4}i8O$Ec)^)ezenn9+BFeR!LGWmEBhds2~SKW-}(-iUl1FW>Bsb%yuRIF>UEoGbx( zM{l2u;OWDAkKzG|lw%PC+2Z~f$1NltSwh5ys++L&q*J`B^n9Y7oGQ9fW|N7$bD<|R z!l{S%)u(dx;P^s8TUQ4RBQ12-l*nuH+F19J6jhpzQfAv1lOK#>+U{m;*^+X`4I>_y ze0827SHoSish%yKZ<9cd7MFP5Pd`gKS#6RT*^MgKDs(>X%@UQGPoi_3SZn0|&*P7uWA9>8iy9l)<=Wv;L?)>ShK{ibs}yD zw$9@W^O^T(olt_2>I@r{LDXvey+af7xZD=)-ZZtOj{7p+w_+5I%3F+I(JPlnR-$jN zHLd=m(D3N&)8<@$?FR@>u=(J2vt^hy%rRB4ywQ01yK;>wD0%}^Z^FW^Go}5i7KJyl zppY`*#U^0xUYth=#B2-H1hB7~osKMzLv@uSpb~py^0~c@WtQN(Zx0rz?Wrh}%Qzg!PXQaAa8~mpECVU+0$}*KN#qIzz2^S`NPGMdA zK3Z}LeX{aYAk~ApPd5ZO;7Ka;C>4iWF`BcrTJN4{ODnF_pVDoIb#^_;tUH<3b*|uH zTwJ8I6J-?7M-1KO=c7^15T0+(%$ZT|mr~1i?l0z6h$%YEA(Jk+8nQZ8C?RN!^#VP@ zq?O?}8_QKQXS~x!6Gl$MH&u&-V}5d7ce!>seAeAe|4{8=DWpi0ulX+;-<B)9#H)ve=0_Wc!viUz}6iAG0<`P=_i^kT=lRJV9s6sSTirs+0udCZo6MaOVrJU4Kt;{-ovfSMbGB?5n^Wa@q=zU0U7 z0euRo(9L+AmM7ca-n1IS?2CwWy%N*d?-jjH_c8!XBv7wEd~!a&veYN}y)?P~euiC& zu|E+@jsDeiwaj*>%BiWmpA8X5M7m=y0!tJoS)wkB4lXh%r5oFH00>*UW9>YPx0(fT z9`6Is6kS4j8VUgo7biDLxNL0a%8eS)@ZqF3V}7B^&vcfBZW*=r;+(SM4plE|I2cXR z6x~*NWuUY5ZcATpI%fG|YE(Dmv9o-p$XDhwulb(y#^0X3=^FPYSR(e@;avN^U`0Re zwSKSOewW2(GhENNPeMEI`-g8FX0INSfA)#CT@Fj_r|wK=;_zbAA31p(?HKV8zBiee z4z%x@o|fY)Z|^lDYPVllpHcS-0)$xnp?K--;}Rk7^_>qoaIMVFPr}ikICbbSOO&_z zsm~2h)&h#RevXFjD4#_EWS=c|d$K;gZJYklGUfAms$7Qw@4iRNw1e*5h4_&A4A~r! z%PwZSF4GzHdmLNEb=hd%WhU*b0roEDFRtYeOlDK>r5-L*YWEAjyBn}eeqy;^Hx?=H z>sQd9h8d#PSf(`XPwTT2Nin1DanQ9{9~bUVpXm2q^^1$t<;;`UCwy$}#ox43i1eKK ztnJ;Q8Imzeo*}mh;gxKqnb~K$0zC=~Qca$An2S>Q(eJ}bfO@FThgi7B%8WVhyiL69 zBHy_`&DQTi>v{Z|a+z|aoOQitjuopp66C`7v3Lr5nwV6_j;nWGC|fyx51P~BSf&z9 zQ`h!OJXmqi;zjEvvLrPnmTU`Wr!!p(^-*HaTq-Pf=VdEUc9TLyE;kK+-cQ3gPH6INdAfN*@xymwRkzyJ3?VKDW1>_8g!qKjI`rXwql%+pb z^45?~p26{%ZQ(N3ntrUbudKu8zd|OAeR!gmzdDp)G)?eRSYDzpKS2RTjd+5CeLqk~ zEI^>-f$C-3;i93v2PbFJgWMFPl+GEI1A@=JL>e!!eOa>gl026Qxf)7J+R^B8%1$CA z2vX7#Do994OG~G8iPEVc4bt5u0)o;F(v5U?cXtR# zOLxEP#=XyTo^!T)jQ7hs#yiIUn{I#mUNzTTYt4CG*JS(wmuezM-mqUS>y;#_vd0BG z0|EDcRFXPKV}`u)8z;`c-TP-nb{tn7PhAsA%|P6*8qz6s4k0} zy>xe{;J6+Tu>*M_cvCY&^Runary<3I{Y_MenWZ!Wk1~h2!zjGxuX)bl*&ANyVsSV4 z2o2p*9JPNU*(*GhiOC--8Hu9JyCGebhU0Kc`cP2|o?x8j)R`SLatm_KNd< z`lrgXpL9-^b1vZ7P~9JePb??SkBvJ?JUk{~N)i^z^U{q`wlLt$!#hvzc{UUxXU<$13)8JoEx#)a1l;HB+gJwgy6?G z6YoTTKs8GXS46HqV^@cZibYp)_%gLX3M{drD`4a^6$~MUHNbT1R;uZRznK9~Jm!}| zPY)U*J;)dXVT}kseDjk2)%vkPLTzp0T`=LtyJPo?lANNbC>nXZrC;9`3wTFAzAWWSUmL)9>Xw^mPJaL`vlgM zrk_D&_hz2M0Um0%C5ygf?K%CpnSJu=^EUJGYWxob%q9O9};$M0^ zfCE{*XE^`A@WYcn0U#B%;EdltF{=NvoqUL@j*|=bUsQE*?n%|ZwE+I1i*EozMhSC~ z_aFZ0@7`KN4ElU+a=Cw5luWP#sy<v#=I6%&Yx~B#0{wrIhyU&i zpqgty)NvYRq<^E1|GzP#S>g{s3#A$q5@Cd^-LBfK%1V#Pemsal@uw*ncnX%v2`>|Q zcvI=YymERrD*fSifj|~wC8Hr?}c;GHS~D0q4nXf$pw_z~Fxa&?Ish<7#56Ik`gKW>GJne+h#y%SLX zV)p7{{>B!CzCs&uQ;6t1B-Wzsp|Ri7U_b>gt_Dep8NiC(N{_RYDDR@qsQ^LaS%_{( z5(i)gfbye;xRcR9M{QjYu!L) zD7FC^jVN>stY8EEo}x32b0VM`&O$_*t`9#| zVE4gz<}?5p_FdDU4@k#$L-b*@Skp3#j6_$*-KQQ0Qp~+!n>Qev^Z{f^-eJhBrkMhw zupJO}ErIHESS7BK{;{`@A&Y5tAb#rrQYtfGvRqH5=dal$`$1md*W76vJ13G&8vGSt zqWL(*npI_Sfrz7(PXqg$eabXY#f|qXAT>}JVg{seaY_=2!0}ij(Ll7M zO2G2stj2ZwVtY_Mca*;ymoLd*2a*R>VEM*pfvn;-ICW9yfUL6}RA=Kgawg!))Zc3? zPGF_fsbr}RH|tK^hAOm}fixMjx$__QC=Ug&;P!@#hqHjw^w_&qqFHVJT+t2?p6-P{ ziJ*v{m;eE}8Gu>GrWZGM07&Pu=>-MVaqxPIs|K0ECi63>;U|D5y$2#As8gdWtHxRv zF&F!h^(N)TvWDyhrDLkwAPk5;uIso2tPr)y>;Rx9t~#I1GKnzFJ0HLcRBbOC%GIAP z2HX->nYKvEo6)%7dVh^7s?j0V>3RMH6kue-&_YeY13pks#0)z2ug?(vyPLJ*o%ylKXr8K&EyZq6MPR7B)m3ilsPA>P6Z>LUn2e$v#X@11s{d#z?8l;6x*| z>m-k?c$Oa3WTv0UKJ&p#&1UpXywoQtAnbZu`-CYEvzqAg2Z9;U9z%=7Rnf(?0}z~Q z75#YDW30M)5L_b31r=RLsv{|rB3>TCAP`_&ieio5GTj6w^pu zAmnSe`^PN~2A8A)tSol8Wgo=>jMaG2de%2T=jG0X{N&7CCV!st(Mu*9T?Q5l)Qn9WJX} z^A?~Ii4UsC4bE@w_`UZ?VUwJ~Dlm7uCF(W?hXAyr?A>}eb;t!%I z>C+&juE22l*Io91yU8jkaF9pBpbPGD63DS-ESF8ZML7X<)DP;N=YV&+#d}iO@1rjZ z!c^MxmDI$B%(2qO(IX+1=r0WE3QC3~7OH%%sb_BT%3p+ zOk)bT@U|*)GRK)pnhwi9R%x`(B;G$tJtQ&v<6a8_*nwH9zQ+5sW4PCC>~&wFXV+Lt z0kbla3rNW|y#pUg8(#2wL(dzv2e!8j7E|{X*hkh-%;nS-u=J{d-{o;;xS$NuUlyUq zk!vse-rdwuT|W6fwvy;-P1K>h;@+Qjh4mM(E9jdD!;>Y?E)kolzeewQN(W{Dv4a+ znks}3Qdw^~sJ=5b+&D%7^@v&EEL6w2uK(etc`Lo*;S27GW{5wD5uj2me$ANSZ6`IW zJkimCGQ-Z7d+pVLGW49=c0^uO?>Mu&NyR8Dt!d$-f-FyIDC!1~@L;kZ7YG7}r}b$a zcv)0}(jlvQjTMSHIB4o40>PHRV8JN!FMx|9+$IFc{mGLL9&Z2Fg#5SLUIRY_CkbgC zGWkX}6Yq9?HtU7Xi_a28WdFlMN-hpB6s}X2dr!E66;fjXk|`w4!9HC8?)B!q*;9u5 z8p8tKKq@5I>1b35Qmj}`?KG7cPnEs`ZWdmF1cEuZfkb1-nP?{NBSp{GhOQ=9z z1x20-p)&{2j43-CL??8v0MuUJO>j)OSAzkyA$r_^4G5<;IFufNgwa|$Wt8Kizvu?t z5iWpMz+0OjvK%M@PaDQ2W7X3Jp6vBU~2!_3R!^Cr42KIA4OP!%a(CkI!o9WpyI$A zH8=4#fX?!OobDG87~+iT=s4P)4?q@;8A<;Vzj^{xd@Uek#DHsGb%8OmDD0jjeI*&< zfK8ql|J96DzfZ~4PfETo<*z8Q$>zcM+6-)I+`y9|(Fp*jnh%D`>Od7G$>zmBKNwzs z^DdtG@j0a~*ZJf5)0c%Lg!(U4yC7j2uG1f0&HBy^SM+r6CW9l6i_xe8XMrjVHcMn0 zDqZZT&5Sr@{7*DcBf<`dDC^GYt*Y9l;RFwr0<{cqi#sYDqOc-jLbco~9e=;D9)R}N z864vT`xSd_kIQER+z4z&V=|4qQ1FvfYL*vQRn?q}Bw%j_w`cGmQ^sfwdc-0p-;m4zYj~_C2maaCvabXe>F4 zjK-LZfsP=^y*}E17W9jA8!Uw_xYx%ksQ%gaAAmO^dw&?lzr7=&uof%v0{ow@7r<@D zfY4x-L%KKOpDYE~4=WUEfI(vT(`Ev0ci{IcgIxFz_6AvDrT~~YR55#x|K_Iu#~(db zz_v6?ct-NalODsJ9~HPHWBw+TKlv>1Vq=j7O&v%fVgAd=jlla~<1UuwpN=!=p6CGG z6ZIuN{>#YafSBUOqmW(Lf0@8ufPbCkRuBYa#6Pv>@d&KvxVtyrzf7P(0%&R_8tad* zCou96Vz8d~$ZGz1+u#0I{{NWHAD7`jrt=@u`A6gUkJtH+*ZHS-;s0+Bte2ybIirt8 zbH6Y^Ck`QY)Z0(bI9=aAc%n^<@AHZb{r8dQ;Rr{u>74O|&{+T)J%2rv3cx$#Z8L8A z2p-j=wY!Uw+pUqBw&&L%3Uu`RjW8;7ZkEGAF-&$4o2y(;k8hLan=M(We#NMQYZeG! zn`hqg*IRlG!K0IRejUMT@%Ci&=!4#~agzhQm?%#ZT#sLzfS@0$sixSiUSc|u6sW9h z77_iPz(IiZoxm`w-|kKH5Tfl`BQ#+fOtw zO$`Rn<1=P?DuM=E3`mk$ZLjMmqMwjOCFrd@#FQxivM9=jSjf1IV6!NNRCB&zylpry z8k6L>68#?0CG|4sQ%KBrVmcdFkdz^9;E)12s-GkweRl8n4&tM)V&u$TuW*HCuyjI$ z^%w+kZ^x1@D=9N6VoYP1ezu&FyZZP`kti5z2r#&9S4lE)B5(<#^r0CENadp9p)uc+ zGFvLqU=SJ6fM_h^86x+^%zEnqQEi~_X7|ZqScQo-OL}?6P0V7lGSEoSbKYaV6A;4j(k5p728Zt_TB6;F z3rCF@IOUu{T0L_cPWn3)Z9v)?DktbB%Y7E;w9pzE*W=j3JKckg^i`i^fCF?p=qY)_ zJ;coUu*%@|j99kASS%UzVt3GY4+#Mb419Umz~-l_g}Nx z-NEY<{`&rr6+`W1k<+ie3_-brK4wa`3`*E={c1sX9}AF#T7yICc)3*n#DUwJX*{mD z$}l6E!kLJTg!Nq`91U!+kTw>EHbDZMj}$J69KSZ0aQMk3rd#8>4~lq?2)$O0Cwn7^ zbj7oTE;2$iH5@1YV?$%EQh0pSC?*FyJ`>jY0Ua2^=*b_`Aip>XP{jNK8)wEm`A$1 z7~qP~RiAh`HLOtmVl|4DdG9%`Dlp48O}-Pvl`z^MSg@EWa-ULS5poj2Du}*cd=~`=`kSK0-uVzNhE)5Cz^XOljk#ow^8%1A$fk8&^h-j{ob_jzG9SMmK2>T|_N zfPQGhxra{Nj&%Ui!tMLy@Az9ni?7@_$|(O-5?D5p_c}8ea-N1^?xX!W>V?m7SyXWl z@54ToY&d_>w(y1SEz>;@3D`08`%BIlOjh>4182$L((Xw0DXUnRG;A#pukJ#!fue;r z@Ino(B|-M@9_@FB_bta-Z*Oti#=K z@_UumVrmk%y-{Ggd;$ln$meI#*rv>g$oi3mUwaoxnXjFL`&3T^nPh!SB z$Ps!en>(D4v3Xk=je)NMJJ$akE!YGz z^f}^dtltY39^HKR_l^T4H%ElzrQ*r4l7;nac4xJI&-1(`@v-yYJqpoER|g5|soNgS z^!aFEL`lKr65+R<_32Vm?n7DL-+0l+ArY#*R=7+ksZ4~p#E>NY5Vo?-eIr_3(fLeLK(GB?kofmWx=j zWN$z)b_-Wo8^#XkzyW_0$6VbW`5kP&$KDnk(zC#iJZxJAA;WpP+QT8UPtVfDYOOCX zKw8b(kI*)1S~paB=6m~->Ai!{bq}bDt;|6@K#jEXfB>sbUmYkFUInRHO0&;ehf`&b z!Nd&b%xhT>ibyt}j~2KtKLII^9~q&QsswAGjU5ni@&90$62xW+#a5i1hTO_;H-2c{ z?j0zLtNj}B6rR?s1sw8I#&it#4IE&MHWSf#v98a=enGFPx#s}u)N z?doHwiu#2*Uu{*z(U_XP;a)&$M51!}94H@sLVf-vFk{~45D0(iDW*d@QKoGm8fTuHHWy8@&g^7^jlkr^D{dUMHn*7fVF?DKIQ3o!AgctI*$G>@@s8j?zZn05JO zK(9`tdQ4x1+n(o_SM@W$;u>P-4%6id&^Ug$m-*G+p~*3)jQb!s&EpzKu6;E#!Bty{ zRUTS&-MFJ@ObCKk*b*Z&1vNu4AW~m^ZUI7IQdBkaE)(^ahIt_8@-U-BeFemy#z0zj z!Vw6MN??v?Ae`b!<$=Zv7;~YFpkz1i#V>`mf;C^f!t%@R&$NM1UAd0U)LOHv2F5-+ z3e)5-7SL_+>C1*7W!H|+l#F76NU>2eKo2~xyk?os)D6mPv&oONj2pi#p|4u|_FQkm z6y^xTJ16(2`tzW4z`MoI4EDWWBF0~#8qR^7o*J0n`R1+cP6vW}^X*uLNPE!8zS0M7 zA~S=M2I`$10{16gxJfzHyAIKUdniv?KK#`DZi8n&&R!i!ldV}M>lgO z3QCKgF7QCo`zb&WCxV*hIx-8a2WnVSsNbC0x#lo8w5Zj0L{;+=H$`VYF`H4&nW(DW z6t-YV0=#A*d@9gZzVZHg-YM(KSJ$!R}5Ej(?j8T}0KTzO*vPc%0cJAb(n z@qp#mHRopTup`KCpgar9yL;Hw*ff~Ybq4CScc9YX${F8Zx8AND*K{gv^#MxA?>7;A zE$W!r*wt^NU>-VT!1Lov=8^USr%~vi1$W1x&wSkYY7wvAV3O3z_u+ekG}R$M7;uAf zW1(XJ5x~RXKUoUeW}p0d48_E4;~B7@YGW_@`!HQ+EctxL6&uP0ERAaFyTbe${sv^+ z%2xz!@YBRW@Za54Rc{>nVkL~u@=o$Za8<}QjZZ*EgS#L|{Q`{lYwH2HaI;{&erddiF48RDB13J020y46D_o*czpEsqv|Tczx_`8|6oT_0~RPxv;_ zy{6C`L7YmS^*QS$lw<1#U{h>S^Zs#qzkZ-w(B5<(N$o=~Mj?^~bF$47i5kW-pMa9= z64Z(wk|g>RX3mq_bI3HL%@aU?b6ByIPY>=j*%M3in9EL>v7SFXSx3x#EHYi(0Av_= zBwIM13i4m^ec0nrr{Dn4`JQsIJrbO_YX;%EAV2qVyxD!*eWCdapfH-Vyj2}}?;yzB z`6>3P>rswY?~$4v;VzUv>UHRC9=XW?Sw<*(n-$qK&v&_iUTi(ZU67lAbB|?_-PfUx zc~L~@7<%4FJ%T0px~5N^vf{io8i24$xxKw0dSitzR*zP<7bDOotKAIa>58KLYy*nq zo6WnN*v#d}L-{?XdQM#lzoia`Eu#~+n-jOm+S7o2XOKXutOrr+K9tf~0FYQ#1R~1i zpp0zWT+xo^<93H+?}JApG6=n$4qOwHS9Sn?DC2i<33NMcA?^Nyru!#AiNGB?FNym1O-!CfeNIw4%@)V3T2FaMEO)pF)Cp&ixnVAQ$oiD55$%9_ceyUv=or z&$@3j5WpmYQCiht+2-H&$=1YmYSz z)LgsW)}}w9iEftc)PodPTwC}zUKfC<_y97lCs99b9tFdGyuf3yw*%}RHICC00P3^j zW6aGRmU8;6Ys)ikwtIb9Ss+2b*I9S+5B7ZeU21o2pAqdS(3_nlV?;QQ77 zDBNo34r>Kzy@l8F%Ohwk2uzWE0k7#}4%EQ`q7yg+AmUz1JQ)t((E1N;BewRQCu*Yb zmEfF3YMIY{8*tOC9Z2?!3C-el@-W&~-vgSnO8E1mPev17UyHbC#PJ86yiI$N?v}h= zGs&IdV60gikVtcpzuGE+fJfaQBdYX*urJrEXY>is2X_m6VNexn#CT@FkJp)IDs@CmunoBr%3g4T=MtG51wZZB>qf)N!4 zcj<}3{ub`i+xZ8YI4#p2X37c5nN)M5EOD{gn@1yE1!d=F{w~Kg<~@^kraWPaVjHif z?e>_@^XbwoUB8F;gr5)YKulQFDx03??IqUkQX6jRAgUmKP$tHuRCaP0NN8UUa-C&_ z8>Dnktm0Dy{6w<*-qeC?EL~NC^LguA$s>yzvv2)&SOuf9ESX%%Y-8q>k4BCU!6i59DES&b zSfh`(eHw_s2Tk*zYwWdw$|O{Q6>eYNSD-x!KsP9^C^c?Iaa}TKcRp$AAG`P1Bqa72 z9#=WZW+htxvjasPadpo+e$uJU)~42t<1d>YyDiJFS1N`jYB5_1Q=c_ExK^TN=)-&p zo=>1GSb7y(FtYCHyvrI=``NWf+a2m-x^xItr-*Rd8)y?@8{s>M?ho{zs!ugJ(7(T> zaOKDscVu<-QO%-lD^;TSjTLjTc>L#NMIsh6O|UOa-xIzL?r~YfPDETLzUXx5Ly1+> zRE||sWI~8knjdx~IS|$~n8x)jS*hjc6wcx_RXtR^K0jVp7x`e)1?Od8uM{wInXD1L<26Nw3~kJ*@VX>KMN_ zFKz^xP!1sVgF2(uPP7LrI!(T;gknM{u~d4l3i&UW?UY2A60)&M|nr*YC{!TK?|<$d8AhKHgF@59#@+R0-q@m7D(1~ z%uCHR>Gqa@z#7G?;ZF*#hKI`3)S`@@y8f+P8!is8ya(-9G`OBw(o`FTbX$D zW#(BvN*OZ!%9@ME1BM(nS89J>QI;^}HboLjaq8dcNPP(^-x-%|E#jTsi7^Z?1_l~Z z;r0UHHJD&R(9T{x$}LcgKb|UX>@!pQd2>YqQ|q0ecybhXZh4ipwOQpY4A`xjb4zsf z-K0*63>4&R$5W}Mutm_8s_Z`}6rLP&YF%O#Z$8-L_~xotqt8rrc?w_5VFKv0bV2&> z&G;=g2tJNP^A{<=90~6~2p;A;ZA6Dvs&!VZr!Kzxz0eU{H_RoAyhGXS3X4WEG!$MO zHLLKA2UpeetDUWp zZ=-Sj8aQu2;2jux@vJHz59ty1TfA|USOnnngDzqumF*oL+641eC@fVr4eLZ_b6H$O zy!Bbx%No}4-h)|kY}=tWfnaQtadLa9NA#$aJLPC;qs1Gd*1S@bGFESSVkvibbO|x) z!$!K}CZgRP0o2gUa4zRG_43=@p6(fN>SA3Qp`}N{I?A}cIm)H&sXB?;86o%K`<;qx za06kOCyg=SuJ12Hkxl_Out=W}1^BRO^6ycU>E72m1eRfi%T3`vB0B33o!XuZ29g(J z-<7gOBIuYNm~mSuR>pm3LYn-^A^WZumxIk??Cof*USVpP%aov$Ck&zP(;yqt`XCmXc2W<4aQCTL1SFHAuRlP= zz5WT5U4TIxE`l%W5@pbTmC-De_e3m;jE>mKQ8VTpvRV_x84ZX_1)!B;r#0K&qoPHU z1Ty?5KC5XOE&!&a_CVtzOm1>NtzX7_nuYO{NJuB1u%lC<;l_JCq6?ui#( z3dix?_}fmwaE2^Pg7PkfPM9VewbW(+xru^WWRl3)NMAxl5Ox1hO&KAd(P~j=o(AR$ znaOAX4Nn1HN!GBvHbV*v+C;a~nF1%or}fpxvE}}}R<}{BSwwAulv?ZHQ%1;-wW2Z= zR?cC%a8_1)imaN#)_14s*xZFyceO=Qi=VcWa^( zLVRmnX>sK?-6dnEjr7I746Ao);u{8G?r3Lb>x<~vTE?HrP?qeX{7#|ovN?G$I>ME> z4-3BuD0F4u+>nt<1Qn5zNOJv4adW=YV9OalPQ^u1)qP;-OaO!%beeKnUnUp>3ayW) zVY9fhrf%Ciu=&x}2Vo^V2PP(AMF~EYPLLO{}~*&4*~!?npuFVp1Ad}6P*Ku4#35C`|P z48Iq2!@|rn3&eNm7(No;54DYM`a+zIM?XgWs>a59Cutq`erp^oS0vu!* z^z#_R+V7fHkMkUnJIL6mEd`axE5MX)4TRtteMx%5P?oxo%dxLnv(jof{tG^)jTmX; z0Em~yE=$AynwaF6@OO9o=J2WAFgl>qiu$hMn*i}IcTi!DZaP}Q;rhX#Nv}5U&1_Ko zC_?T1s&?aNcrQ?%;>hLnm*Abm5G_}N7d`PWF|k#6i`s$h4DO86-1wC(jsg57(`p1h zfK-!J!-!Gnii>9{x;n!%J^AHlA0^I6cz?owI3GT33t-&kD1+ha%R>1Nf~@IP>9M}X34iWq*+)irKO*QA!Tkph@dmWvCTDo+s_7&Xtvq=Nj_y|n7A(t-%R87 zzUE@r{PA;AJ*c_FN11wnoe%4rhUYvqsD~TRnDj`{iH!l3;!aQXc!048IO`5ef|M@F zCieWuOUW~Ui{5H*lt~wSYuZqD=MvqJNcCZ>+QA!KTMfYy(hL@A)BRY=r0bCkUYzZ; zfL)dvfMjGn9q#_DiKNY?QgS58K_{cg*ZK&?M%8NL=1GD3`G62QstvO&a{={nc3u5v z_bO_%S%v`0Z7r535igJuMk3l%8Z*xgZMCmR>P!dmg$ys!r&p%AS1tzvG}4~o+{w`F z%`dmrwO;Ir`&z=@9jAHzOlwaD>#W>@Q93aw?a_$>`yjaFFTNsstrRzAzC8JD%mr@b z+b$7ac_=ANDW5Rogc7dZm7%j_{HR}cWS$-n_yB0hF7>i{9pPyeXKq`JLt45lihDCnj|oC{_2r3rf!Uy?NjkH6T685y`^6cJ)XBN~tssiT$|?wcbRP^I8B^T(in4^}=U?qOK#*{A274nU$Dwi8!_z{~$|BJ{Px(ka0lh~T`o7X7MkMZ2b zIY^lC+r)E0A+()VP1T~TJVqPYYBpVz>R+wVJhTF#rCdl0-EoAxiu#wuA0Qwj?PaJe z?byA04vkp~aEs=cU_%KYEXWk|gvuxP=otl31&)YF#{ zR5n!@BU4i&Fco;xJ}wPYIyo4Is~%o#+FQi+h)eAU)z+In+_&pZGYJ9kBOr2pvSm39 z_%|EP(LKU}8}c=JWm5d6WthR-`yFg^4typj?k18k#pm*(#w=w-#{JV7Qpn0z<5?#n zZWMBnT84s0L*aB&=X7zn2p|kN;=6~O2~j`f{7Pd<`lVBMc7*wP=Iq}#s%2lru85}J z&8LS^9BPZ1?0tDE84!;%4m!yP3v8`1PUfJ74Ij zh(%yvFvBSj5I??p00-Yn^hQqZH3qz}+yj`arymXhF8#xZvHFhb%|Y}#LAF>EhlF2d zY!?aRn+{*4DHP^HnGQPH=fxc((&aN!OIm3OYGk#fSVw>zkEaqHpZDl z{EiGK5pS>Iy6OuLRR-tFvs|XNxCn!M{W|rYH9bA`%$1s5*iy|Wls-mqMwQ5~=4E}K z>|bqbrTRsWQp-smj_<`Bd>i|rmEC<}dq|UO1aCAO`gL1`S~iY<>&me^{^UAPA(5p)Tt&<@O}&VKWW<*mBX|T`Cjul%= zkw+|FWUzFr*okiba=YM_oQb5@Op372a}__8#cnckg;~ytgte58e6R>s)@9GCz9Xsu zVb-|TfXFQ8J<13*(G}sm1TB;*1X27nP`q0*y5ur~7I{QoazT|i5<8Ot#O$?qiD~4d zT~lSh*aYIa5`h}n#4#{=7k$+;A^F*PJ2vs&%qPx`pZHZ)(#s(if*dQ1q zmPj<-oRPrF#Fc4Vc~x06JcCDAk~MQJdl7?!kvU8^llORTx z?RZqiHr8Ecv`zFWRCjjc;G|phi33??0fqIJn3y9P1&`!#royYK!TqOlqW)wzXj+uw z{R=-+_+~?`d7U4W)WMlqkJxX(;~|ow%+Z-gc7T<9&#) z#yNZRAoI#y6q{HP`J7gPaAP;ak25_6=Cf?|5dVFTsZi?rTw84d++Z@*aO_N%=~I7) zu5kXu(hc>H@F?_0)<&_{i+w6YvXbV81e9_G-`gJ12Yo&byT3Y^c~l{w#@uQ+`q+ar zer)F>zsry~W#xfV;*o3=V{#_3;mk!2W+qpx?CG^7sEUX;N^&mbYGu<4>RSEM8n52_ zGV%2gsm9xAM>X>+KVhHJHV2D;e*L_+%ZWtC@w8rTj4filGen-^3ahCff2pBC{`UeP z6aT#crJqt3UWfMieIUrYxK>R=@=j?Nzdr{gMrLi28E~7f`i%Ml`VdEALWZ@12mR%m zm%}6=KkN4$C>nZIs}6&D^lJ_g_v-^}Zzxnxpml2s=<)e>m0@3m&-on5U5Eoo^US#T}1-n&V8 zlZz$x#Bv!{iX+r=-F)Bc>mfN0YHDHClj~g`9$J>Oo}ms(XE*<`=GBz6y08IevGE*r zWFN2k@h~o4X9j=l%naE?&120}C-42wRj*V4A#?Uv!ZUoR;ILG*LdJDAz$JXe>=cw{ zT=PE6OtTrXDx4`UDYl`GEGvkN7)2g|qD`lT>A4pd>IzKd(Y^(tw1^{)_b7dKyN%8~ zk0Ia13|s2P)>b*Vt2gj7+tNJ4xKhzW)$sJX@SJGSxOWv(vrEG-F;JzuqJT0RGZPA6 zE4>fD07MLQeau`+q>)d=<071jp(>j+5_y{p8z+2{U{$uJU+bmSKP82`4NDlWIQ}a@W^J<3ML;7^R%}5DcxVyIZy0-mnQhq{%}jax z>njaHxX75zY!KzwW7cG`577nO}QT2FnTg@!oElflOH#b=(F$J9g?OmKnGh&QFCNwX)POcFdNradjn`7DEWzy zd|)8G@{S4b!bL#7P;Eyb$^u@N8=#qd`gSTik+S$bIMvDThFa7?7~V)aGxNfoLLdNz zv*5~VzodimIHpF~aKoPG?vm#|5v$Q_0s5S8?d`4T<|wj)k8PF~mpb>=^#&3()xCxO z&$`-Hn1sU_nXgxYTc8iRaaUD+KP$Oatl=rAVLCq@(J~Y9fYN=Py%#;L{UqO=gbqzLr2H@|-7aJugPXq5SdI?hv*e_e_fL~cOI zQw+RBc>Xz2m(od0q$Vf~6s~sSAcD$OGF+@w?+9TH)-%y@P*t!q-|$*UzQv<+t984$ z;HNpZ+vxQ@ygjm#o`VzXadTyIrLK5bX4yMcG`Uk|?VGcN;2pX*tY3n79l}`sJX=&y zb;;@NiPASt+mJ?d62s0@)d`hd?h&AZQMS4PbfY4E+4e}uxwvdiJl{s z>6Yeh%AL5Ho+KBaon8cNuU9FpsgO4UwK8$~0Eh-noOp2U6X89#)=hn5^Ep8;rqJT@ zbg#~Sn|u|V6dKmDpO8oD(B3)%5K1-Dk1+TBL917aep4CsnH-r`VuF#!ooOE1lsfEB zm)e48egSw!<6aft*rPfSJFZ?Lr(f4APH03v7ZhfoAq#tU1MnG1Wb3J`NqD)732E_p z3Y8_z@VR7i-38w_$Zr<2GcG@O?>I7h0-JhjzPw%#T47Zf!9*U9KFIP_-C4{!oFmWD zq-5|VeC^Mp@sxb7%K3e>%0o{Mg6tOzoKNM9N#*AgM}N*Q;Ei+ILG&smGop;Au%#O* zcy{|X4EL}CpfY@(b-P101xz3P&yg39$eQy#nxslJw>bDuw3aiRZDjp@En!RV3y&ZS zeZQ8C*d7cK@!(W#dw+d=0t2`4z6{m@0?8SeLk`8{hSncz)K;pSRR~<3J&W&M)d^+8 z^QN)o?e73(P_)X-lV@4o(UgS$J z>MOvSr;M{M)a<>}E}GARA(V8S+Qq=d#E6E%D-KNPC{*X%O2QR$Ib{Z&*e1b{G3vpg zN_Ft&FrwOrZrJ{d92sy}mE}INsksSFOYz?NFcp*goc0@Kc-CxL`Mx`yWWQ%2|5ksq zWj9oc4art~RqfGaer