diff --git a/.github/workflows/check-all-links.yml b/.github/workflows/check-all-links.yml index 9ccad4dd39..f5c6c8ba85 100644 --- a/.github/workflows/check-all-links.yml +++ b/.github/workflows/check-all-links.yml @@ -3,6 +3,13 @@ name: Check all content (MDX) links on: pull_request: +permissions: + actions: read + checks: read + contents: read + issues: write + pull-requests: write + jobs: check-for-absolute-urls: name: "Check for absolute prisma.io urls" @@ -41,6 +48,8 @@ jobs: pull-request: ${{ github.event.pull_request.number }} body: ${{ steps.absolute-urls.outputs.body }} body-includes: absolute URLs + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: report success run: | @@ -105,3 +114,5 @@ jobs: pull-request: ${{ github.event.pull_request.number }} body: ${{ steps.redirects.outputs.body }} body-includes: following redirects + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/image-optimise.yml b/.github/workflows/image-optimise.yml index 38daca6e1c..3910cd0b60 100644 --- a/.github/workflows/image-optimise.yml +++ b/.github/workflows/image-optimise.yml @@ -51,7 +51,7 @@ jobs: if: | github.event_name != 'pull_request' && steps.calibre.outputs.markdown != '' - uses: peter-evans/create-pull-request@v6.0.5 + uses: peter-evans/create-pull-request@v7.0.3 with: title: Auto Compress Images branch-suffix: timestamp diff --git a/.github/workflows/list-changed-pages.yml b/.github/workflows/list-changed-pages.yml index 274de5f644..ef730b3600 100644 --- a/.github/workflows/list-changed-pages.yml +++ b/.github/workflows/list-changed-pages.yml @@ -6,6 +6,13 @@ on: paths: - "content/**/*" +permissions: + actions: read + checks: read + contents: read + issues: write + pull-requests: write + jobs: post-files-changed-comment: name: "Post files changed comment" @@ -15,7 +22,7 @@ jobs: - name: Get all changed markdown files id: changed-files - uses: tj-actions/changed-files@v44 + uses: tj-actions/changed-files@v45 with: files: content/**/*.{md,mdx} @@ -51,3 +58,5 @@ jobs: pull-request: ${{ github.event.pull_request.number }} body: ${{ steps.build-comment-body.outputs.body }} body-includes: "original | preview" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/lost-pixel.yml b/.github/workflows/lost-pixel.yml index ff8c811c9a..d826d5217d 100644 --- a/.github/workflows/lost-pixel.yml +++ b/.github/workflows/lost-pixel.yml @@ -11,7 +11,7 @@ jobs: - name: Get all changed markdown files id: changed-files - uses: tj-actions/changed-files@v44 + uses: tj-actions/changed-files@v45 with: files: content/**/*.{md,mdx} @@ -50,6 +50,6 @@ jobs: run: sed -i -e 's/_/\//g' -e 's|prisma\.io||g' -re 's/(name.+)(\/)(\")/\1-\3/g' lost-pixel-pages.json - name: Lost Pixel - uses: lost-pixel/lost-pixel@v3.17.0 + uses: lost-pixel/lost-pixel@v3.18.2 env: LOST_PIXEL_API_KEY: ${{ secrets.LOST_PIXEL_API_KEY }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9af0c8433e..685b577dc9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,6 +30,6 @@ Similar to issues, we do not have hard and fast rules for Pull Requests. If you The Prisma team may ask for changes before a PR can be merged. As these changes are made, please mark the corresponding comments as "resolved". If you need help on a pull request or would like feedback, please feel free to mention the `@Dev-Connections` team. -As a final note, if you're still working on a PR, please utilize the "Draft Pull Request" feature to let us know that your work is not yet ready. +As a final note, if you're still working on a PR, please utilize the "Draft Pull Request" feature to let us know that your work is not yet ready. Thank you again for contributing to our documentation! diff --git a/cSpell.json b/cSpell.json index 3dbbc5aad4..309d495451 100644 --- a/cSpell.json +++ b/cSpell.json @@ -78,7 +78,9 @@ "Zenstack", "Streamdal", "leaderboard", - "typesense" + "typesense", + "Solidstart", + "Astro" ], "ignoreWords": [ "Ania", @@ -98,7 +100,10 @@ "Nikolas", "Supavisor", "inshellisense", - "janedoe" + "janedoe", + "unindexed", + "Hyperdrive", + "pgcat" ], "patterns": [ { diff --git a/content/100-getting-started/01-quickstart.mdx b/content/100-getting-started/01-quickstart.mdx index 797c9d44dd..c020f0104c 100644 --- a/content/100-getting-started/01-quickstart.mdx +++ b/content/100-getting-started/01-quickstart.mdx @@ -63,7 +63,7 @@ Finally, set up Prisma ORM with the `init` command of the Prisma CLI: npx prisma init --datasource-provider sqlite ``` -This creates a new `prisma` directory with a `prisma.schema` file and configures SQLite as your database. You're now ready to model your data and create your database with some tables. +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 @@ -427,6 +427,33 @@ If you want to move forward with Prisma ORM using your own PostgreSQL, MySQL, Mo 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. +### Build real-time apps with Prisma Pulse + +[Prisma Pulse](/pulse) enables you to create applications that instantly react to changes in your database, allowing you to build type-safe real-time features and applications easily: + +| Demo | Description | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | +| [`starter`](https://github.com/prisma/prisma-examples/tree/latest/pulse/starter) | A Prisma Pulse starter app | +| [`email-with-resend`](https://github.com/prisma/prisma-examples/tree/latest/pulse/email-with-resend) | An example app to send emails to new users using Prisma Pulse and Resend | +| [`fullstack-leaderboard`](https://github.com/prisma/prisma-examples/tree/latest/pulse/fullstack-leaderboard) | A live leaderboard (built with Next.js) | +| [`fullstack-simple-chat`](https://github.com/prisma/prisma-examples/tree/latest/pulse/fullstack-simple-chat) | A simple chat app (built with Next.js & Express) | +| [`product-search-with-typesense`](https://github.com/prisma/prisma-examples/tree/latest/pulse/product-search-with-typesense) | A cron job that syncs data into Typesense (built with Hono.js) | +| [`data-sync-with-bigquery`](https://github.com/prisma/prisma-examples/tree/latest/pulse/data-sync-with-bigquery) | A script that automatically syncs data into Google BigQuery | + +### 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: 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 index 9e18212dd8..8b1c31d1b1 100644 --- 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 @@ -39,3 +39,5 @@ Here's a short explanation of each component: - `HOST`: The host where a [`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://docs.mongodb.com/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 + +If you see the following error: `Error in connector: SCRAM failure: Authentication failed.`, you can specify the source database for the authentication by adding `?authSource=admin` to the end of the connection string. See [this GitHub discussion](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) for additional details. \ No newline at end of file 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 index d7f85a172a..6ce766ccb4 100644 --- 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 @@ -96,7 +96,7 @@ To evolve the app, you need to follow the same flow of the tutorial: The [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository contains a number of ready-to-run examples: - + diff --git a/content/100-getting-started/index.mdx b/content/100-getting-started/index.mdx index e68c7301ca..06dd149a1e 100644 --- a/content/100-getting-started/index.mdx +++ b/content/100-getting-started/index.mdx @@ -13,6 +13,7 @@ import { Bolt, BorderBox, BoxTitle, + Inspect, Database, Grid, LinkCard, @@ -33,9 +34,11 @@ Explore our products that make it easy to build and scale data-driven applicatio [**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 Accelerate**](/accelerate/what-is-accelerate) is a global database cache with scalable connection pooling to make your queries fast. +[**Prisma Optimize**](/optimize/) helps you analyze queries, generate insights, and provides recommendations to make your database queries faster. -[**Prisma Pulse**](/pulse/what-is-pulse) allows you to react to database changes with type-safe model subscriptions. +[**Prisma Accelerate**](/accelerate) is a global database cache with scalable connection pooling to make your queries fast. + +[**Prisma Pulse**](/pulse) allows you to react to database changes with type-safe model streams in real-time. @@ -68,7 +71,7 @@ _These options don't require you to have your own database running._ _Select one of these options if you want to connect Prisma ORM to your own database._ - +

Set up Prisma ORM from scratch with your favorite database and @@ -194,3 +197,22 @@ Build real-time applications by subscribing to data changes in your database usi link="https://github.com/prisma/prisma-examples?tab=readme-ov-file#prisma-pulse" /> + +## Prisma Optimize + +Make your database queries faster by using the insights and recommendations generated by Prisma Optimize. + + + + + diff --git a/content/200-orm/050-overview/100-introduction/250-should-you-use-prisma.mdx b/content/200-orm/050-overview/100-introduction/250-should-you-use-prisma.mdx index 750877c06e..1fa46fdc21 100644 --- a/content/200-orm/050-overview/100-introduction/250-should-you-use-prisma.mdx +++ b/content/200-orm/050-overview/100-introduction/250-should-you-use-prisma.mdx @@ -64,7 +64,6 @@ Prisma ORM is the only _fully_ type-safe ORM in the TypeScript ecosystem. The ge Development of Prisma ORM's open source tools is happening in the open. Most of it happens directly on GitHub in the main [`prisma/prisma`](https://github.com/prisma/prisma) repo: - issues and PRs in our repos are triaged and prioritized (usually within 1-2 days) -- there is a public [roadmap](https://pris.ly/roadmap) that is kept up to date with our plans - new [releases](https://github.com/prisma/prisma/releases) with new features and improvements are issued every three weeks - we have a dedicated support team that responds to questions in [GitHub Discussions](https://github.com/prisma/prisma/discussions) @@ -104,7 +103,7 @@ _Alternatives_: [Hasura](https://hasura.io/), [Postgraphile](https://www.graphil ### ... you want to use raw, type-safe SQL for querying your database -While Prisma ORM does allow you to [send plain SQL queries](/orm/prisma-client/queries/raw-database-access/raw-queries) to your database, it might not be the best fit if you prefer to work with a SQL-based abstraction that you want to be type-safe. Prisma ORM's main benefit is to provide an abstraction layer that makes you more productive compared to writing SQL. +While Prisma ORM does allow you to [send plain SQL queries](/orm/prisma-client/using-raw-sql/raw-queries) to your database, it might not be the best fit if you prefer to work with a SQL-based abstraction that is type-safe. Prisma ORM's main benefit is to provide an abstraction layer that makes you more productive compared to writing SQL directly. If you're a solo developer that is very comfortable with SQL, and you just want to be sure that your database layer is type-safe, a lower-level TypeScript database library might be better for you. 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 44dd55c87b..eed97f41ae 100644 --- a/content/200-orm/050-overview/500-databases/600-mongodb.mdx +++ b/content/200-orm/050-overview/500-databases/600-mongodb.mdx @@ -59,7 +59,7 @@ Migrating your database over time is an important part of the development cycle. -When using MongoDB, be aware that the “coupling” between your schema and the database is purposefully designed to be less rigid than with with SQL databases; MongoDB will not enforce the schema, so you have to verify data integrity. +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. diff --git a/content/200-orm/050-overview/600-beyond-prisma-orm.mdx b/content/200-orm/050-overview/600-beyond-prisma-orm.mdx new file mode 100644 index 0000000000..8a343c63af --- /dev/null +++ b/content/200-orm/050-overview/600-beyond-prisma-orm.mdx @@ -0,0 +1,170 @@ +--- +title: Beyond Prisma ORM +sidebar_label: Beyond Prisma ORM +description: Prisma ORM addresses many development needs, but Prisma's additional products like Accelerate and Pulse can further enhance performance and real-time capabilities. +--- + +As a Prisma ORM user, you're already experiencing the power of type-safe database queries and intuitive data modeling. When scaling production applications, however, new challenges emerge. As an app matures it’s a given that you’ll begin to experience connection pooling complexities, find ways to effectively cache common queries, or develop sophisticated, event-driven systems to handle real-time or time-sensitive features. + +Instead of spending your valuable time overcoming these challenges, let’s explore how Prisma can help by extending the capabilities of the ORM as your application grows. + +## Boost application performance with Prisma Accelerate + +As your application scales, you'll likely need tools to handle increased traffic efficiently. This often involves implementing connection pooling to manage database connections and caching strategies to reduce database load and improve response times. Prisma Accelerate addresses these needs in a single solution, eliminating the need to set up and manage separate infrastructure. + +Prisma Accelerate is particularly useful for applications deployed to serverless and edge environments (also know as Function-as-a-Service) because these deployments lend themselves towards many orders of magnitude more connections being created than a traditional, long-lived application. For these apps, Prisma Accelerate has the added benefit of protecting your database from day one and keeping your app online [regardless of traffic you experience](https://www.prisma.io/blog/saving-black-friday-with-connection-pooling). + +Try out the [Accelerate speed test](https://accelerate-speed-test.prisma.io/) to see what’s possible. + +### Improve query performance with connection pooling + +Place your connection pooler in one of 15+ global regions, minimizing latency for database operations. Enable high-performance distributed workloads across serverless and edge environments. + +### Reduce query latency and database load with caching + +Cache query results across 300+ global points of presence. Accelerate extends your Prisma Client, offering intuitive, granular control over caching patterns such as `ttl` and `swr` on a per-query basis. + +### Handle scaling traffic with managed infrastructure + +Scale to millions of queries per day without infrastructure changes. Efficiently manage database connections and serve more users with fewer resources. + +### Get started with Accelerate today + +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 { withAccelerate } from '@prisma/extension-accelerate' + +// 1. Extend your Prisma Client with the Accelerate extension +const prisma = new PrismaClient().$extends(withAccelerate()) + +// 2. (Optionally) add cache to your Prisma queries +const users = await prisma.user.findMany({ + cacheStrategy: { + ttl: 30, // Consider data fresh for 30 seconds + swr: 60 // Serve stale data for up to 60 seconds while fetching fresh data + } +}) +``` + +To see more examples, visit our [examples repo](https://github.com/prisma/prisma-examples) or try them out yourself with `npx try-prisma`. + +[Sign up for Accelerate](https://console.prisma.io/login) + +## Build real-time, event-driven applications with Prisma Pulse + +HTTP requests resulting in reads and writes to your database is straightforward with Prisma ORM. But what if you wanted to trigger specific code based on events or only run a given function based on changes to your database? + +With Pulse, you can reliably stream database changes directly to your application! No need to constantly poll the database for changes or set up complex infrastructure to achieve this. + +Pulse extends your Prisma Client, giving you an API that allows you to react to database changes as they happen with the same, great developer experience of Prisma ORM. + +```tsx +import { PrismaClient } from '@prisma/client' +import { withPulse } from '@prisma/extension-pulse' + +// Extend your Prisma Client with the Pulse extension +const prisma = new PrismaClient().$extends( + withPulse({ apiKey: process.env.PULSE_API_KEY }) +) + +// You're now ready to develop real-time features with Pulse! +const stream = await prisma.user.stream() + +for await (const event of stream) { + console.log('Received database event:', event) + +} +``` + +:::info + +View the event object and Pulse API: [Pulse API Reference](/pulse/api-reference) + +::: + +### Simplify event-driven workflows + +Remove the need for complicated scheduling and queues and let events arrive directly from your database. + +```tsx +// Stream new users on the `User` model in real-time +const stream = await prisma.user.stream({ + create: {}, // This stream will include any User.create event. + name: 'user-create-events' // Name is optional, but allows you to stop and restart the stream without losing any events. +}); + +for await (let event of stream) { + const { email } = event.created; + + // Send welcome email to user after sign up + await sendWelcomeEmail({ email }); +} +``` + +### Build real-time experiences + +When someone sends a chat message through your app, it’s critical that it’s delivered quickly. Power any real-time functionality with Pulse as the database-event engine. + +```tsx +// Stream unread messages on the `Message` model in real-time +const stream = await prisma.message.stream({ + create: { read: false }, // Filter for unread messages +}); + +for await (let event of stream) { + const { senderId, message, chatId } = event.created; + + // Update the chat UI and send a notification + await sendMessageInChat({ senderId, message, chatId }); +} +``` + +### Keep services in sync + +Synchronize data to external services when your data changes without cluttering your code with extra API calls. + +```tsx +// Stream new orders on the `Order` model in real-time +const stream = await prisma.order.stream({ + create: {}, // This stream will include any User.create event. + name: 'user-create-events' // Name is optional, but allows you to stop and restart the stream without losing any events. +}); + +for await (let event of stream) { + const { orderId, orderItems } = event.created; + + // Update the inventory + await updateExternalInventoryFromOrder({ orderId, orderItems }); +} +``` + +To see more examples, visit our [examples repo](https://github.com/prisma/prisma-examples) or try them out yourself with `npx try-prisma`. + +[Sign up for Pulse](https://console.prisma.io/login). + +## Grow with Prisma + +Both Accelerate and Pulse take features built into Prisma ORM and build upon them by adding additional capabilities like globally-optimized caching and real-time data synchronization. Get started for free the [Prisma Data Platform](https://console.prisma.io/login) and explore how Accelerate and Pulse can help you build scalable, high-performance applications! + +Improving developer experience doesn’t stop at Accelerate and Pulse. Prisma is building and expanding our products to improve every aspect of Data DX and we’d love to hear what you think. Join our community and learn more about our products below. + +Both Accelerate and Pulse build on Prisma ORM through [Prisma Client Extensions](/orm/prisma-client/client-extensions). This opens up features that we couldn’t include in the ORM like globally-optimized caching and real-time data synchronization. Create a free [Prisma Data Platform](https://console.prisma.io/login) account and explore how Accelerate and Pulse can help you build scalable, high-performance applications! + +Improving developer experience doesn’t stop at Accelerate and Pulse. Prisma is building and expanding our products to improve every aspect of Data DX and we’d love to hear what you think. Join our community and learn more about our products below + + +

+
+
+ [Accelerate](https://www.prisma.io/data-platform/accelerate) +
+
+ [Pulse](https://www.prisma.io/data-platform/pulse) +
+
+ [Optimize](https://www.prisma.io/blog/prisma-optimize-early-access) +
+
+
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 ff8dd82283..627b342001 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 @@ -65,7 +65,7 @@ The following is a list of community created generators. If you want to create y > **Note**: Community projects are not maintained or officially supported by Prisma and some features may be out of sync. Use at your own discretion. If you create a community generator, please use this naming convention: `prisma-generator-`. -- [`prisma-dbml-generator`](https://notiz.dev/blog/prisma-dbml-generator): Transforms the Prisma schema into [Database Markup Language](https://www.dbml.org/home/) (DBML) which allows for an easy visual representation +- [`prisma-dbml-generator`](https://notiz.dev/blog/prisma-dbml-generator): Transforms the Prisma schema into [Database Markup Language](https://dbml.dbdiagram.io/home/) (DBML) which allows for an easy visual representation - [`prisma-docs-generator`](https://github.com/pantharshit00/prisma-docs-generator): Generates an individual API reference for Prisma Client - [`prisma-json-schema-generator`](https://github.com/valentinpalkovic/prisma-json-schema-generator): Transforms the Prisma schema in [JSON schema](https://json-schema.org/) - [`prisma-json-types-generator`](https://github.com/arthurfiorette/prisma-json-types-generator): Adds support for [Strongly Typed `Json`](https://github.com/arthurfiorette/prisma-json-types-generator#readme) fields for all databases. It goes on `prisma-client-js` output and changes the json fields to match the type you provide. Helping with code generators, intellisense and much more. All of that without affecting any runtime code. @@ -78,6 +78,7 @@ The following is a list of community created generators. If you want to create y - [`prisma-kysely`](https://github.com/valtyr/prisma-kysely): Generates type definitions for Kysely, a TypeScript SQL query builder. This can be useful to perform queries against your database from an edge runtime, or to write more complex SQL queries not possible in Prisma without dropping type safety. - [`prisma-generator-nestjs-dto`](https://github.com/vegardit/prisma-generator-nestjs-dto): Generates DTO and Entity classes with relation `connect` and `create` options for use with [NestJS Resources](https://docs.nestjs.com/recipes/crud-generator) and [@nestjs/swagger](https://www.npmjs.com/package/@nestjs/swagger) - [`prisma-erd-generator`](https://github.com/keonik/prisma-erd-generator): Generates an entity relationship diagram +- [`prisma-generator-plantuml-erd`](https://github.com/dbgso/prisma-generator-plantuml-erd/tree/main/packages/generator): Generator to generate ER diagrams for PlantUML. Markdown and Asciidoc documents can also be generated by activating the option. - [`prisma-class-generator`](https://github.com/kimjbstar/prisma-class-generator): Generates classes from your Prisma Schema that can be used as DTO, Swagger Response, TypeGraphQL and so on. - [`zod-prisma`](https://github.com/CarterGrimmeisen/zod-prisma): Creates Zod schemas from your Prisma models. - [`prisma-pothos-types`](https://github.com/hayes/pothos/tree/main/packages/plugin-prisma): Makes it easier to define Prisma-based object types, and helps solve n+1 queries for relations. It also has integrations for the Relay plugin to make defining nodes and connections easy and efficient. 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 970bce8f80..ea948299d6 100644 --- a/content/200-orm/100-prisma-schema/10-overview/index.mdx +++ b/content/200-orm/100-prisma-schema/10-overview/index.mdx @@ -117,7 +117,7 @@ enum Role { ## Syntax -Prisma Schema files are written in Prisma Schema Language (PSL). See the [data sources](/orm/prisma-schema/overview/data-sources), [generators](/orm/prisma-schema/overview/generators), [data model definition**](/orm/prisma-schema/data-model) and of course [Prisma Schema API reference](/orm/reference/prisma-schema-reference) pages for details and examples. +Prisma Schema files are written in Prisma Schema Language (PSL). See the [data sources](/orm/prisma-schema/overview/data-sources), [generators](/orm/prisma-schema/overview/generators), [data model definition](/orm/prisma-schema/data-model) and of course [Prisma Schema API reference](/orm/reference/prisma-schema-reference) pages for details and examples. ### VS Code 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 a000234ff2..65d06499c0 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 @@ -134,7 +134,7 @@ The data model definition is made up of: The corresponding database looks like this: -![](/img/orm/sample-database.png) +![Sample database](/img/orm/sample-database.png)
@@ -567,7 +567,7 @@ location Unsupported("POLYGON")? The `Unsupported` type allows you to define fields in the Prisma schema for database types that are not yet supported by Prisma ORM. For example, MySQL's `POLYGON` type is not currently supported by Prisma ORM, but can now be added to the Prisma schema using the `Unsupported("POLYGON")` type. -Fields of type `Unsupported` are not available in the generated Prisma Client API, but you can still use Prisma ORM's [raw database access](/orm/prisma-client/queries/raw-database-access/raw-queries) feature to query these fields. +Fields of type `Unsupported` do not appear in the generated Prisma Client API, but you can still use Prisma ORM’s [raw database access feature](/orm/prisma-client/using-raw-sql/raw-queries) to query these fields. > **Note**: If a model has **mandatory `Unsupported` fields**, the generated client will not include `create` or `update` methods for that model. @@ -575,7 +575,7 @@ Fields of type `Unsupported` are not available in the generated Prisma Client AP ## Defining attributes -Attributes modify the behavior of fields or model blocks. The following example includes three field attributes ([`@id`](/orm/reference/prisma-schema-reference#id) , [`@default`](/orm/reference/prisma-schema-reference#default) , and [`@unique`](/orm/reference/prisma-schema-reference#unique) ) and one block attribute ([`@@unique`](/orm/reference/prisma-schema-reference#unique-1) ): +Attributes modify the behavior of fields or model blocks. The following example includes three field attributes ([`@id`](/orm/reference/prisma-schema-reference#id) , [`@default`](/orm/reference/prisma-schema-reference#default) , and [`@unique`](/orm/reference/prisma-schema-reference#unique) ) and one block attribute ([`@@unique`](/orm/reference/prisma-schema-reference#unique-1)): @@ -761,6 +761,8 @@ model Post { title String //highlight-next-line published Boolean @default(false) + //highlight-next-line + data Json @default("{ \"hello\": \"world\" }") author User @relation(fields: [authorId], references: [id]) authorId Int categories Category[] @relation(references: [id]) @@ -795,6 +797,7 @@ Default values can be: - Static values that correspond to the field type, such as `5` (`Int`), `Hello` (`String`), or `false` (`Boolean`) - [Lists](/orm/reference/prisma-schema-reference#-modifier) of static values, such as `[5, 6, 8]` (`Int[]`) or `["Hello", "Goodbye"]` (`String`[]). These are available in Prisma ORM versions `4.0.0` and later, when using supported databases (PostgreSQL, CockroachDB and MongoDB) - [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\" }")`. 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 b522c14c52..d1a3e1d132 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 @@ -264,22 +264,19 @@ model Category { -```sql -CREATE TABLE "Category" ( - id SERIAL PRIMARY KEY, - name TEXT NOT NULL -); -CREATE TABLE "Post" ( - id SERIAL PRIMARY KEY, - title TEXT NOT NULL -); --- Relation table + indexes ------------------------------------------------------- -CREATE TABLE "_CategoryToPost" ( - "A" integer NOT NULL REFERENCES "Category"(id), - "B" integer NOT NULL REFERENCES "Post"(id) -); -CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON "_CategoryToPost"("A" int4_ops,"B" int4_ops); -CREATE INDEX "_CategoryToPost_B_index" ON "_CategoryToPost"("B" int4_ops); +```prisma +model Post { + id String @id @default(auto()) @map("_id") @db.ObjectId + categoryIDs String[] @db.ObjectId + categories Category[] @relation(fields: [categoryIDs], references: [id]) +} + +model Category { + id String @id @default(auto()) @map("_id") @db.ObjectId + name String + postIDs String[] @db.ObjectId + posts Post[] @relation(fields: [postIDs], references: [id]) +} ``` 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 a859de22e0..debec24c0f 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 @@ -295,7 +295,7 @@ model Category { -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 scalars](/orm/prisma-schema/data-model/relations#relation-scalar-fields)) so you can focus on the [relation fields](#relation-fields). +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). @@ -337,7 +337,7 @@ If you're not using Prisma Migrate but obtain your data model from [introspectio Relation [fields](/orm/prisma-schema/data-model/models#defining-fields) are fields on a Prisma [model](/orm/prisma-schema/data-model/models#defining-models) that do _not_ have a [scalar type](/orm/prisma-schema/data-model/models#scalar-fields). Instead, their type is another model. -Every relation must have exactly two relation fields, one on each model. In the case of one-to-one and one-to-many relations, an additional _relation scalar field_ is required which gets linked by one of the two relation fields in the `@relation` attribute. This relation scalar is the direct representation of the _foreign key_ in the underlying database. +Every relation must have exactly two relation fields, one on each model. In the case of one-to-one and one-to-many relations, an additional _relation scalar field_ is required which gets linked by one of the two relation fields in the `@relation` attribute. This relation scalar field is the direct representation of the _foreign key_ in the underlying database. @@ -348,13 +348,13 @@ model User { id Int @id @default(autoincrement()) email String @unique role Role @default(USER) - posts Post[] + posts Post[] // relation field (defined only at the Prisma ORM level) } model Post { id Int @id @default(autoincrement()) title String - author User @relation(fields: [authorId], references: [id]) + author User @relation(fields: [authorId], references: [id]) // relation field (uses the relation scalar field `authorId` below) authorId Int // relation scalar field (used in the `@relation` attribute above) } ``` @@ -367,13 +367,13 @@ model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique role Role @default(USER) - posts Post[] + posts Post[] // relation field (defined only at the Prisma ORM level) } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String - author User @relation(fields: [authorId], references: [id]) + author User @relation(fields: [authorId], references: [id]) // relation field (uses the relation scalar field `authorId` below) authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above) } ``` @@ -381,42 +381,9 @@ model Post { -These models have the following fields: - - - - -| Model | Field | Relational | Relation field | -| :----- | :--------- | :--------- | :--------------------------- | -| `User` | `id` | `Int` | No | -| | `email` | `String` | No | -| | `role` | `Role` | No | -| | `posts` | `Post[]` | **Yes** (Prisma ORM-level) | -| `Post` | `id` | `Int` | No | -| | `title` | `String` | No | -| | `authorId` | `Int` | No (_relation scalar field_) | -| | `author` | `User` | **Yes** (_annotated_) | - - - - -| Model | Field | Relational | Relation field | Notes | -| :----- | :--------- | :--------- | :--------------------------- | -------------------------------------- | -| `User` | `id` | `String` | No | Underlying database type is `ObjectId` | -| | `email` | `String` | No | -| | `role` | `Role` | No | -| | `posts` | `Post[]` | **Yes** (Prisma ORM-level) | -| `Post` | `id` | `String` | No | -| | `title` | `String` | No | -| | `authorId` | `String` | No (_relation scalar field_) | Underlying database type is `ObjectId` | -| | `author` | `User` | **Yes** (_annotated_) | - - - - Both `posts` and `author` are relation fields because their types are not scalar types but other models. -Also note that the annotated relation field `author` needs to link the relation scalar field `authorId` on the `Post` model inside the `@relation` attribute. The relation scalar represents the foreign key in the underlying database. +Also note that the [annotated relation field](#annotated-relation-fields) `author` needs to link the relation scalar field `authorId` on the `Post` model inside the `@relation` attribute. The relation scalar field represents the foreign key in the underlying database. The other relation field called `posts` is defined purely on a Prisma ORM-level, it doesn't manifest in the database. @@ -453,13 +420,7 @@ A scalar field _becomes_ a relation scalar field when it's used in the `fields` ### Relation scalar fields - - -Relation scalar fields are read-only in the generated [Prisma Client API](/orm/prisma-client). If you want to update a relation in your code, you can do so using [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes). - - - -#### Relation scalar naming conventions +#### Relation scalar field naming conventions Because a relation scalar field always _belongs_ to a relation field, the following naming convention is common: 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 c8551900ec..f78802b4ef 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 @@ -366,6 +366,6 @@ Some databases support materialized views, e.g. [PostgreSQL](https://www.postgre Materialized views persist the result of the view query for faster access and only update it on demand. -Currently Prisma ORM has no understanding of materialized views, but when you [manually create a view](#create-a-view-in-the-underlying-database) you can also create a materialized view by using the corresponding command in the underlying database. You can then use Prisma Client's [raw query functionality](/orm/prisma-client/queries/raw-database-access) to execute the command to refresh the view manually. +Currently, Prisma ORM does not support materialized views. However, when you [manually create a view](#create-a-view-in-the-underlying-database), you can also create a materialized view with the corresponding command in the underlying database. You can then use Prisma Client's [TypedSQL functionality](/orm/prisma-client/using-raw-sql) to execute the command and refresh the view manually. In the future Prisma Client might support marking individual views as materialized and add a Prisma Client method to refresh the materialized view. Please comment on our [`views` feedback issue](https://github.com/prisma/prisma/issues/17335) with your use case. 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 e120f9d159..ef695f72d3 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 @@ -79,5 +79,5 @@ const posts = await prisma.$primary().post.findMany() You can use the `$replica()` method to explicitly execute your query against a replica instead of your primary database: ```ts -const result = await prisma.$replica().$queryRaw`SELECT ...` +const result = await prisma.$replica().user.findFirst(...) ``` 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 2f43f712a4..ce7cfa30ac 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 @@ -904,7 +904,7 @@ await prisma.$transaction([deleteProfile, deletePosts, deleteUsers]) #### Deleting all data with raw SQL / `TRUNCATE` -If you are comfortable working with raw SQL you can perform a `TRUNCATE` on a table by utilizing [`$executeRawUnsafe`](/orm/prisma-client/queries/raw-database-access/raw-queries#executerawunsafe). +If you are comfortable working with raw SQL, you can perform a `TRUNCATE` query on a table using [`$executeRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#executerawunsafe). In the following examples, the first tab shows how to perform a `TRUNCATE` on a Postgres database by using a `$queryRaw` look up that maps over the table and `TRUNCATES` all tables in a single query. diff --git a/content/200-orm/200-prisma-client/100-queries/035-select-fields.mdx b/content/200-orm/200-prisma-client/100-queries/035-select-fields.mdx index dfbaf54e98..303d3e5b69 100644 --- a/content/200-orm/200-prisma-client/100-queries/035-select-fields.mdx +++ b/content/200-orm/200-prisma-client/100-queries/035-select-fields.mdx @@ -14,7 +14,7 @@ By default, when a query returns records (as opposed to a count), the result inc To customize the result: -- Use [`select`](/orm/reference/prisma-client-reference#select) to return specific fields - [you can also use a nested `select` to include relation fields](/orm/prisma-client/queries/relation-queries#select-specific-relation-fields) +- Use [`select`](/orm/reference/prisma-client-reference#select) to return specific fields - [you can also use a nested `select` to include relation fields](/orm/prisma-client/queries/relation-queries#select-specific-fields-of-included-relations) - Use [`include`](/orm/reference/prisma-client-reference#include) to explicitly [include relations](/orm/prisma-client/queries/relation-queries#nested-reads) Selecting only the fields and relations that you require rather than relying on the default selection set can ✔ reduce the size of the response and ✔ improve query speed. @@ -314,7 +314,7 @@ const users = await prisma.user.findMany({ For more information about querying relations, refer to the following documentation: - [Include a relation (including all fields)](/orm/prisma-client/queries/relation-queries#include-all-fields-for-a-specific-relation) -- [Select specific relation fields](/orm/prisma-client/queries/relation-queries#select-specific-relation-fields) +- [Select specific relation fields](/orm/prisma-client/queries/relation-queries#select-specific-fields-of-included-relations) ## Relation count 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 844914b8cc..6e69d71ce8 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 @@ -241,9 +241,9 @@ const user = await prisma.user.findFirst({ -### Select specific relation fields +### Select specific fields of included relations -You can use a nested `select` to choose a subset of relation fields to return. For example, the following query returns the user's `name` and the `title` of each related post: +You can use a nested `select` to choose a subset of fields of relations to return. For example, the following query returns the user's `name` and the `title` of each related post: @@ -444,7 +444,7 @@ const result = await prisma.user.findFirst({ include: { posts: { where: { - published: true, + published: false, }, orderBy: { title: 'asc', 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 b092bf9f2d..093b7aa65e 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 @@ -418,9 +418,11 @@ const getUsersByRelevance = await prisma.user.findMany({ }) ``` -:::info +
-Enabling the `fullTextSearch` preview feature breaks the imports of the `OrderByWithRelationInput` TypeScript types. It is is renamed to `OrderByWithRelationAndSearchRelevanceInput`. +:::note + +Prior to Prisma ORM 5.16.0, enabling the `fullTextSearch` preview feature would rename the `OrderByWithRelationInput` TypeScript types to `OrderByWithRelationAndSearchRelevanceInput`. If you are using the Preview feature, you will need to update your type imports. ::: 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 853085d728..f33ac3d4a0 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 @@ -129,9 +129,11 @@ You can also use raw queries inside of a `$transaction`: ```ts +import { selectUserTitles, updateUserName } from '@prisma/client/sql' + const [userList, updateUser] = await prisma.$transaction([ - prisma.$queryRaw`SELECT 'title' FROM User`, - prisma.$executeRaw`UPDATE User SET name = 'Hello' WHERE id = 2;`, + prisma.$queryRawTyped(selectUserTitles()), + prisma.$queryRawTyped(updateUserName(2)), ]) ``` @@ -1148,10 +1150,9 @@ This section describes how to build your own optimistic concurrency control. See - ✔ You anticipate a high number of concurrent requests (multiple people booking cinema seats) - ✔ You anticipate that conflicts between those concurrent requests will be rare -Avoiding locks in a application with a high number of concurrent requests makes the application more resilient to load and more scalable overall. Although locking is not inherently bad, locking in a high concurrency environment can lead to unintended consequences - even if you are locking individual rows, and only for a short amount of time. For more information, see: +Avoiding locks in an application with a high number of concurrent requests makes the application more resilient to load and more scalable overall. Although locking is not inherently bad, locking in a high concurrency environment can lead to unintended consequences - even if you are locking individual rows, and only for a short amount of time. For more information, see: - [Why ROWLOCK Hints Can Make Queries Slower and Blocking Worse in SQL Server](https://littlekendra.com/2016/02/04/why-rowlock-hints-can-make-queries-slower-and-blocking-worse-in-sql-server/) -- [The High Concurrency strategy](https://www.ibm.com/developerworks/library/j-ts5/index.html) #### Scenario: Reserving a seat at the cinema 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 58e49dcfb5..6f0b6c8cb7 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 @@ -243,38 +243,86 @@ const result = await prisma.blogs.findMany({ }) ``` -However, if you try to search on `title` alone, the search will fail with the error "Cannot find a fulltext index to use for the search" and the message code is `P2030`, because the index requires a search on both fields. +However, if you try to search on `title` alone, the search will fail with the error "Cannot find a fulltext index to use for the search" and the message code is `P2030`, because the search requires an index on both fields. ## Full-text search with raw SQL -Full-text search is currently in Preview and due to a [known issue](https://github.com/prisma/prisma/issues/23627), you may be seeing slow search queries. If that's the case, you can optimize your query using [raw SQL](/orm/prisma-client/queries/raw-database-access). +Full-text search is currently in Preview, and due to a [known issue](https://github.com/prisma/prisma/issues/23627), you might experience slow search queries. If so, you can optimize your query using [TypedSQL](/orm/prisma-client/using-raw-sql). ### PostgreSQL -In PostgreSQL, you can use `to_tsvector` and `to_tsquery` to express your search query: +With [TypedSQL](/orm/prisma-client/using-raw-sql), you can use PostgreSQL's `to_tsvector` and `to_tsquery` to express your search query. -```ts -const term = `cat` -const result = - await prisma.$queryRaw`SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term});` -``` + + + + + ```sql + SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term}); + ``` + + + + + + ```ts + import { fullTextSearch } from "@prisma/client/sql" + + const term = `cat` + const result = await prisma.$queryRawTyped(fullTextSearch(term)) + ``` + + + + > **Note**: Depending on your language preferences, you may exchange `english` against another language in the SQL statement. If you want to include a wildcard in your search term, you can do this as follows: -```ts -const term = `cat:*` -const result = - await prisma.$queryRaw`SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term});` -``` + + + + + ```sql + SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term}); + ``` + + + + + + ```ts + //highlight-next-line + const term = `cat:*` + const result = await prisma.$queryRawTyped(fullTextSearch(term)) + ``` + + + + ### MySQL In MySQL, you can express your search query as follows: -```ts -const term = `cat` -const result = - await prisma.$queryRaw`SELECT * FROM Blog WHERE MATCH(content) AGAINST(${term} IN NATURAL LANGUAGE MODE);` -``` + + + + + ```sql + SELECT * FROM Blog WHERE MATCH(content) AGAINST(${term} IN NATURAL LANGUAGE MODE); + ``` + + + + + + ```ts + const term = `cat` + const result = await prisma.$queryRawTyped(fullTextSearch(term)) + ``` + + + + diff --git a/content/200-orm/200-prisma-client/100-queries/063-excluding-fields.mdx b/content/200-orm/200-prisma-client/100-queries/063-excluding-fields.mdx index c3762162b1..71a586ad84 100644 --- a/content/200-orm/200-prisma-client/100-queries/063-excluding-fields.mdx +++ b/content/200-orm/200-prisma-client/100-queries/063-excluding-fields.mdx @@ -4,15 +4,185 @@ metaTitle: 'Excluding fields' metaDescription: 'This page explains how to exclude sensitive fields from Prisma Client' --- - - By default Prisma Client returns all fields from a model. You can use `select` to narrow the result set, but that can be unwieldy if you have a large model and you only want to exclude one or two fields. -Prisma Client doesn't have a native way of excluding fields yet, but it's easy to create a function that you can use to exclude certain fields in a type-safe way. +:::info + +As of Prisma ORM 5.16.0, excluding fields globally and locally is supported via the `omitApi` Preview feature. + +::: + +## Excluding a field globally using `omit` + +The following is a type-safe way to exclude a field globally using the [`omitApi` Preview feature](/orm/reference/preview-features): + + + + + +```prisma +generator client { + provider = "prisma-client-js" + previewFeatures = ["omitApi"] +} + +model User { + id Int @id @default(autoincrement()) + firstName String + lastName String + email String @unique + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} +``` + + + + + +```tsx +const prisma = new PrismaClient({ + omit: { + user: { + password: true + } + } +}) + +// The password field is excluded in all queries, including this one +const user = await prisma.user.findUnique({ where: { id: 1 } }) +``` + + + + + +## Excluding a field locally using `omit` - +The following is a type-safe way to exclude a field locally using the `omitApi` Preview feature: -## Excluding the password field + + + + +```prisma +generator client { + provider = "prisma-client-js" + previewFeatures = ["omitApi"] +} + +model User { + id Int @id @default(autoincrement()) + firstName String + lastName String + email String @unique + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} +``` + + + + + +```tsx +const prisma = new PrismaClient() + +// The password field is excluded only in this query +const user = await prisma.user.findUnique({ + omit: { + password: true + }, + where: { + id: 1 + } +}) +``` + + + + + +## How to omit multiple fields + +Omitting multiple fields works the same as selecting multiple fields: add multiple key-value pairs to the omit option. +Using the same schema as before, you could omit password and email with the following: + +```tsx +const prisma = new PrismaClient() + +// password and email are excluded +const user = await prisma.user.findUnique({ + omit: { + email: true, + password: true, + }, + where: { + id: 1, + }, +}) +``` + +Multiple fields can be omitted locally and globally. + +## How to select a previously omitted field + +If you [omit a field globally](#excluding-a-field-globally-using-omit), you can "override" by either selecting the field specifically or by setting `omit` to `false` in a query. + + + + + +```tsx +const user = await prisma.user.findUnique({ + select: { + firstName: true, + lastName: true, + password: true // The password field is now selected. + }, + where: { + id: 1 + } +}) +``` + + + + + +```tsx +const user = await prisma.user.findUnique({ + omit: { + password: false // The password field is now selected. + }, + where: { + id: 1 + } +}) +``` + + + + + +## When to use `omit` globally or locally + +It's important to understand when to omit a field globally or locally: + +- If you are omitting a field in order to prevent it from accidentally being included in a query, it's best to omit it globally. For example: Globally omitting the password field from a User model so that sensitive information doesn't accidentally get exposed. +- If you are omitting a field because it's not needed in a query, it's best to omit it locally. + +Local omit (when an `omit` option is provided in a query) only applies to the query it is defined in, while a global omit applies to every query made with the same Prisma Client instance, [unless a specific select is used or the omit is overridden](#how-to-select-a-previously-omitted-field). + +## Excluding the password field without using `omit` + +:::note + +The `omitApi` Preview feature, released in Prisma ORM 5.13.0, is the preferred way of omitting fields from a query result. The ability to globally omit fields was added to the `omitApi` Preview feature in Prisma ORM 5.16.0. This documentation is still relevant for versions of Prisma ORM prior to 5.13.0. + +::: The following is a type-safe `exclude` function returns a user without the `password` field. @@ -62,9 +232,3 @@ function main() { In the TypeScript example, we've provided two generics: `User` and `Key`. The `Key` generic is defined as the keys of a `User` (e.g. `email`, `password`, `firstName`, etc.). These generics flow through the logic, returning a `User` that omits the list of `Key`s provided. - -## Going further - -- Learn how you can move the `exclude` function into [a custom model](/orm/prisma-client/queries/custom-models). -- Instead of excluding fields, another option is to [obfuscate the field](https://github.com/prisma/prisma-client-extensions/tree/main/obfuscated-fields). -- There's an [outstanding feature request](https://github.com/prisma/prisma/issues/5042) to add exclude support natively in Prisma Client. If you'd like to see that happen, make sure to upvote that issue and share your use case! 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 a263861e5c..c545b42052 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 @@ -170,14 +170,72 @@ The MongoDB uses a RegEx rule for case-insensitive filtering. ### SQLite provider -By default, SQLite itself only [supports case-insensitive comparisons of ASCII characters](https://www.sqlite.org/faq.html#q18). Therefore, Prisma Client does not offer support for case-insensitive filtering with SQLite. +By default, text fields created by Prisma Client in SQLite databases do not support case-insensitive filtering. In SQLite, only [case-insensitive comparisons of ASCII characters](https://www.sqlite.org/faq.html#q18) are possible. -To enable limited support (ASCII only) for case-insensitive filtering on a per-column basis, use `COLLATE NOCASE` when you define table columns: +To enable limited support (ASCII only) for case-insensitive filtering on a per-column basis, you will need to add `COLLATE NOCASE` when you define a text column. + +#### Adding case-insensitive filtering to a new column. + +To add case-insensitive filtering to a new column, you will need to modify the migration file that is created by Prisma Client. + +Taking the following Prisma Schema model: + +```prisma +model User { + id Int @id + email String +} +``` + +and using `prisma migrate dev --create-only` to create the following migration file: + +```sql +-- CreateTable +CREATE TABLE "User" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "email" TEXT NOT NULL +); +``` + +You would need to add `COLLATE NOCASE` to the `email` column in order to make case-insensitive filtering possible: + +```sql +-- CreateTable +CREATE TABLE "User" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + //highlight-next-line + "email" TEXT NOT NULL COLLATE NOCASE +); +``` + +#### Adding case-insensitive filtering to an existing column. + +Since columns cannot be updated in SQLite, `COLLATE NOCASE` can only be added to an existing column by creating a blank migration file and migrating data to a new table. + +Taking the following Prisma Schema model: + +```prisma +model User { + id Int @id + email String +} +``` + +and using `prisma migrate dev --create-only` to create an empty migration file, you will need to rename the current `User` table and create a new `User` table with `COLLATE NOCASE`. ```sql -CREATE TABLE mytable ( - sample TEXT COLLATE NOCASE /* collating sequence NOCASE */ +-- UpdateTable +ALTER TABLE "User" RENAME TO "User_old"; + +CREATE TABLE "User" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "email" TEXT NOT NULL COLLATE NOCASE ); + +INSERT INTO "User" (id, email) +SELECT id, email FROM "User_old"; + +DROP TABLE "User_old"; ``` ### Microsoft SQL Server provider diff --git a/content/200-orm/200-prisma-client/100-queries/090-raw-database-access/index.mdx b/content/200-orm/200-prisma-client/100-queries/090-raw-database-access/index.mdx deleted file mode 100644 index 7411f18751..0000000000 --- a/content/200-orm/200-prisma-client/100-queries/090-raw-database-access/index.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: 'Raw database access' -metaTitle: 'Raw database access' -metaDescription: 'Raw database access with Prisma Client.' -hide_table_of_contents: true ---- - -While Prisma ORM aims to make all your database queries intuitive, type-safe, and convenient, there may be situations where you need to drop down to raw queries. - -This may happen for several reasons, e.g., because you need to optimize the performance of a specific query or because your data requirements can't be expressed by Prisma Client's query API. - -In that case, you can use one of Prisma Client's escape hatches, such as `$queryRaw` or `$executeRaw`, to send raw queries to the database. - -When using relational databases, you can use **community tools** that can still vastly improve the developer experience writing raw SQL, e.g., by enabling type safety or providing auto-completion for your SQL queries: - -- [`prisma-extension-kysely`](https://github.com/eoin-obrien/prisma-extension-kysely): A Client extension that uses the [Kysely](https://kysely.dev/) SQL query builder API to compose SQL queries in TypeScript, with auto-completion and type safety, and submits them through Prisma Client's connection pool. -- [SafeQL](https://safeql.dev/compatibility/prisma.html): An ESLint plugin enabling syntax highlighting and type safety for SQL strings inside Prisma ORM's raw SQL escape hatches. For a tutorial on using SafeQL, visit this [page](/orm/prisma-client/queries/raw-database-access/custom-and-type-safe-queries). - -## In this section - - 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 ec29e1502c..d9d8bd4461 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 @@ -5,15 +5,17 @@ metaDescription: 'How Prisma optimizes queries under the hood' tocDepth: 3 --- - - This guide describes ways to optimize query performance, debug performance issues, and how to tackle common performance issues such as the [n+1 problem](#solving-the-n1-problem). - +:::tip + +To debug slow queries, you can use [Prisma Optimize](/optimize) and follow the [recommendations](/optimize/recommendations) provided to improve query performance in your app. + +::: ## Debugging performance issues -To help you debug and diagnose performance issues, you can [log query events at client level](/orm/prisma-client/observability-and-logging/logging#event-based-logging), which allows you to see the generated queries, parameters, and durations. +To help you debug and diagnose performance issues, you can [log query events at client level](/orm/prisma-client/observability-and-logging/logging#event-based-logging), which allows you to see the generated queries, parameters, and durations. Alternatively, if you are only interested in the time taken to run a query, you can implement [logging middleware](/orm/prisma-client/client-extensions/middleware/logging-middleware). 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 new file mode 100644 index 0000000000..b2e27a45ac --- /dev/null +++ b/content/200-orm/200-prisma-client/150-using-raw-sql/100-typedsql.mdx @@ -0,0 +1,224 @@ +--- +title: 'TypedSQL' +metaTitle: 'Writing Type-safe SQL with TypedSQL and Prisma Client' +metaDescription: 'Learn how to use TypedSQL to write fully type-safe SQL queries that are compatible with any SQL console and Prisma Client.' +sidebar_class_name: preview-badge +--- + +## Getting started with TypedSQL + +To start using TypedSQL in your Prisma project, follow these steps: + +1. Ensure you have `@prisma/client` and `prisma` installed and updated to at least version `5.19.0`. + + ```terminal + npm install @prisma/client@latest + npm install -D prisma@latest + ``` + +1. Add the `typedSql` preview feature flag to your `schema.prisma` file: + + ```prisma + generator client { + provider = "prisma-client-js" + previewFeatures = ["typedSql"] + } + ``` + +1. Create a `sql` directory inside your `prisma` directory. This is where you'll write your SQL queries. + + ```terminal + mkdir -p prisma/sql + ``` + +1. Create a new `.sql` file in your `prisma/sql` directory. For example, `getUsersWithPosts.sql`. Note that the file name must be a valid JS identifier and cannot start with a `$`. + +1. Write your SQL queries in your new `.sql` file. For example: + + ```sql title="prisma/sql/getUsersWithPosts.sql" + SELECT u.id, u.name, COUNT(p.id) as "postCount" + FROM "User" u + LEFT JOIN "Post" p ON u.id = p."authorId" + GROUP BY u.id, u.name + ``` + +1. Generate Prisma Client with the `sql` flag to ensure TypeScript functions and types for your SQL queries are created: + + :::warning + + Make sure that any pending migrations are applied before generating the client with the `sql` flag. + + ::: + + ```terminal + prisma generate --sql + ``` + + If you don't want to regenerate the client after every change, this command also works with the existing `--watch` flag: + + ```terminal + prisma generate --sql --watch + ``` + +1. Now you can import and use your SQL queries in your TypeScript code: + + ```typescript title="/src/index.ts" + import { PrismaClient } from '@prisma/client' + import { getUsersWithPosts } from '@prisma/client/sql' + + const prisma = new PrismaClient() + + const usersWithPostCounts = await prisma.$queryRawTyped(getUsersWithPosts()) + console.log(usersWithPostCounts) + ``` + +## Passing Arguments to TypedSQL Queries + +To pass arguments to your TypedSQL queries, you can use parameterized queries. This allows you to write flexible and reusable SQL statements while maintaining type safety. Here's how to do it: + +1. In your SQL file, use placeholders for the parameters you want to pass. The syntax for placeholders depends on your database engine: + + + + For PostgreSQL, use the positional placeholders `$1`, `$2`, etc.: + + ```sql title="prisma/sql/getUsersByAge.sql" + SELECT id, name, age + FROM users + WHERE age > $1 AND age < $2 + ``` + + + For MySQL, use the positional placeholders `?`: + + ```sql title="prisma/sql/getUsersByAge.sql" + SELECT id, name, age + FROM users + WHERE age > ? AND age < ? + ``` + + + In SQLite, there are a number of different placeholders you can use. Postional placeholders (`$1`, `$2`, etc.), general placeholders (`?`), and named placeholders (`:minAge`, `:maxAge`, etc.) are all available. For this example, we'll use named placeholders `:minAge` and `:maxAge`: + + ```sql title="prisma/sql/getUsersByAge.sql" + SELECT id, name, age + FROM users + WHERE age > :minAge AND age < :maxAge + ``` + + + + :::note + + See below for information on how to [define argument types in your SQL files](#defining-argument-types-in-your-sql-files). + + ::: + +1. When using the generated function in your TypeScript code, pass the arguments as additional parameters to `$queryRawTyped`: + + ```typescript title="/src/index.ts" + import { PrismaClient } from '@prisma/client' + import { getUsersByAge } from '@prisma/client/sql' + + const prisma = new PrismaClient() + + const minAge = 18 + const maxAge = 30 + const users = await prisma.$queryRawTyped(getUsersByAge(minAge, maxAge)) + console.log(users) + ``` + +By using parameterized queries, you ensure type safety and protect against SQL injection vulnerabilities. The TypedSQL generator will create the appropriate TypeScript types for the parameters based on your SQL query, providing full type checking for both the query results and the input parameters. + +### Passing array arguments to TypedSQL + +TypedSQL supports passing arrays as arguments for PostgreSQL. Use PostgreSQL's `ANY` operator with an array parameter. + +```sql title="prisma/sql/getUsersByIds.sql" +SELECT id, name, email +FROM users +WHERE id = ANY($1) +``` + +```typescript title="/src/index.ts" +import { PrismaClient } from '@prisma/client' +import { getUsersByIds } from '@prisma/client/sql' + +const prisma = new PrismaClient() + +const userIds = [1, 2, 3] +const users = await prisma.$queryRawTyped(getUsersByIds(userIds)) +console.log(users) +``` + +TypedSQL will generate the appropriate TypeScript types for the array parameter, ensuring type safety for both the input and the query results. + +:::note + +When passing array arguments, be mindful of the maximum number of placeholders your database supports in a single query. For very large arrays, you may need to split the query into multiple smaller queries. + +::: + +### Defining argument types in your SQL files + +Argument typing in TypedSQL is accomplished via specific comments in your SQL files. These comments are of the form: + +```sql +-- @param {Type} $N:alias optional description +``` + +Where `Type` is a valid database type, `N` is the position of the argument in the query, and `alias` is an optional alias for the argument that is used in the TypeScript type. + +As an example, if you needed to type a single string argument with the alias `name` and the description "The name of the user", you would add the following comment to your SQL file: +```sql +-- @param {String} $1:name The name of the user +``` + +Currently accepted types are `Int`, `BigInt`, `Float`, `Boolean`, `String`, `DateTime`, `Json`, `Bytes`, and `Decimal`. + +Taking the [example from above](#passing-arguments-to-typedsql-queries), the SQL file would look like this: + +```sql +-- @param {Int} $1:minAge +-- @param {Int} $2:maxAge +SELECT id, name, age +FROM users +WHERE age > $1 AND age < $2 +``` + +The format of argument type definitions is the same regardless of the database engine. + +## Examples + +For practical examples of how to use TypedSQL in various scenarios, please refer to the [Prisma Examples repo](https://github.com/prisma/prisma-examples). This repo contains a collection of ready-to-run Prisma example projects that demonstrate best practices and common use cases, including TypedSQL implementations. + +## Limitations of TypedSQL + +### Supported Databases + +TypedSQL supports modern versions of MySQL and PostgreSQL without any further configuration. For MySQL versions older than 8.0 and all SQLite versions, you will need to manually [describe argument types](#defining-argument-types-in-your-sql-files) in your SQL files. The types of inputs are inferred in all supported versions of PostgreSQL and MySQL 8.0 and later. + +TypedSQL does not work with MongoDB, as it is specifically designed for SQL databases. + +### 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. + +### Dynamic SQL Queries with Dynamic Columns + +TypedSQL does not natively support constructing SQL queries with dynamically added columns. When you need to create a query where the columns are determined at runtime, you must use the `$queryRaw` and `$executeRaw` methods. These methods allow for the execution of raw SQL, which can include dynamic column selections. + +**Example of a query using dynamic column selection:** + +```typescript +const columns = 'name, email, age'; // Columns determined at runtime +const result = await prisma.$queryRawUnsafe( + `SELECT ${columns} FROM Users WHERE active = true` +); +``` + +In this example, the columns to be selected are defined dynamically and included in the SQL query. While this approach provides flexibility, it requires careful attention to security, particularly to [avoid SQL injection vulnerabilities](/orm/prisma-client/using-raw-sql/raw-queries#sql-injection-prevention). Additionally, using raw SQL queries means foregoing the type-safety and DX of TypedSQL. + +## Acknowledgements + +This feature was heavily inspired by [PgTyped](https://github.com/adelsz/pgtyped) and [SQLx](https://github.com/launchbadge/sqlx). Additionally, SQLite parsing is handled by SQLx. diff --git a/content/200-orm/200-prisma-client/100-queries/090-raw-database-access/050-raw-queries.mdx b/content/200-orm/200-prisma-client/150-using-raw-sql/200-raw-queries.mdx similarity index 97% rename from content/200-orm/200-prisma-client/100-queries/090-raw-database-access/050-raw-queries.mdx rename to content/200-orm/200-prisma-client/150-using-raw-sql/200-raw-queries.mdx index ce14180886..c8e01b7da6 100644 --- a/content/200-orm/200-prisma-client/100-queries/090-raw-database-access/050-raw-queries.mdx +++ b/content/200-orm/200-prisma-client/150-using-raw-sql/200-raw-queries.mdx @@ -2,9 +2,16 @@ title: 'Raw queries' metaTitle: 'Raw queries' metaDescription: 'Learn how you can send raw SQL and MongoDB queries to your database using the raw() methods from the Prisma Client API.' -tocDepth: 3 --- +:::warning + +With Prisma ORM `5.19.0`, we have released [TypedSQL](/orm/prisma-client/using-raw-sql). TypedSQL is a new way to write SQL queries that are type-safe and even easier to add to your workflow. + +We strongly recommend using TypedSQL queries over the legacy raw queries described below whenever possible. + +::: + Prisma Client supports the option of sending raw queries to your database. You may wish to use raw queries if: - you want to run a heavily optimized query @@ -249,31 +256,31 @@ Be aware that: ```ts no-lines const name = 'Bob' - await prisma.$queryRaw`UPDATE user SET greeting = 'My name is ${name}';` + await prisma.$executeRaw`UPDATE user SET greeting = 'My name is ${name}';` ``` Instead, you can either pass the whole string as a variable, or use string concatenation: ```ts no-lines const name = 'My name is Bob' - await prisma.$queryRaw`UPDATE user SET greeting = ${name};` + await prisma.$executeRaw`UPDATE user SET greeting = ${name};` ``` ```ts no-lines const name = 'Bob' - await prisma.$queryRaw`UPDATE user SET greeting = 'My name is ' || ${name};` + await prisma.$executeRaw`UPDATE user SET greeting = 'My name is ' || ${name};` ``` - Template variables can only be used for data values (such as `email` in the example above). Variables cannot be used for identifiers such as column names, table names or database names, or for SQL keywords. For example, the following two queries would **not** work: ```ts no-lines const myTable = 'user' - await prisma.$queryRaw`UPDATE ${myTable} SET active = true;` + await prisma.$executeRaw`UPDATE ${myTable} SET active = true;` ``` ```ts no-lines const ordering = 'desc' - await prisma.$queryRaw`UPDATE User SET active = true ORDER BY ${desc};` + await prisma.$executeRaw`UPDATE User SET active = true ORDER BY ${desc};` ``` #### Return type @@ -696,7 +703,7 @@ console.log(result) #### Using `$queryRawUnsafe` and `$executeRawUnsafe` unsafely -If you cannot use tagged templates, you can instead use [`$queryRawUnsafe`](/orm/prisma-client/queries/raw-database-access/raw-queries#queryrawunsafe) or [`$executeRawUnsafe`](/orm/prisma-client/queries/raw-database-access/raw-queries#executerawunsafe) but **be aware that your these functions make it much more likely that your code will be vulnerable to SQL injection**. +If you cannot use tagged templates, you can instead use [`$queryRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#queryrawunsafe) or [`$executeRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#executerawunsafe). However, **be aware that these functions significantly increase the risk of SQL injection vulnerabilities in your code**. The following example concatenates `query` and `inputString`. Prisma Client ❌ **cannot** escape `inputString` in this example, which makes it vulnerable to SQL injection: @@ -791,11 +798,11 @@ prisma.$runCommandRaw({ }) ``` - +:::warning Do not use `$runCommandRaw()` for queries which contain the `"find"` or `"aggregate"` commands, because you might be unable to fetch all data. This is because MongoDB returns a [cursor](https://docs.mongodb.com/manual/tutorial/iterate-a-cursor/) that is attached to your MongoDB session, and you might not hit the same MongoDB session every time. For these queries, you should use the specialised [`findRaw()`](#findraw) and [`aggregateRaw()`](#aggregateraw) methods instead. - +::: #### Return type diff --git a/content/200-orm/200-prisma-client/100-queries/090-raw-database-access/100-custom-and-type-safe-queries.mdx b/content/200-orm/200-prisma-client/150-using-raw-sql/300-safeql.mdx similarity index 96% rename from content/200-orm/200-prisma-client/100-queries/090-raw-database-access/100-custom-and-type-safe-queries.mdx rename to content/200-orm/200-prisma-client/150-using-raw-sql/300-safeql.mdx index 80d32a67f1..8192708195 100644 --- a/content/200-orm/200-prisma-client/100-queries/090-raw-database-access/100-custom-and-type-safe-queries.mdx +++ b/content/200-orm/200-prisma-client/150-using-raw-sql/300-safeql.mdx @@ -1,6 +1,6 @@ --- -title: 'Custom & type-safe queries' -metaTitle: 'Custom & type-safe queries' +title: 'SafeQL & Prisma Client' +metaTitle: 'Integrate SafeQL with Prisma Client' metaDescription: 'Learn how to use SafeQL and Prisma Client extensions to work around features not natively supported by Prisma, such as PostGIS.' --- @@ -10,6 +10,12 @@ This page explains how to improve the experience of writing raw SQL in Prisma OR The example will be using [PostGIS](https://postgis.net/) and PostgreSQL, but is applicable to any raw SQL queries that you might need in your application. +:::note + +This page builds on the [legacy raw query methods](/orm/prisma-client/using-raw-sql/raw-queries) available in Prisma Client. While many use cases for raw SQL in Prisma Client are covered by [TypedSQL](/orm/prisma-client/using-raw-sql/typedsql), using these legacy methods is still the recommended approach for working with `Unsupported` fields. + +::: + ## What is SafeQL? [SafeQL](https://safeql.dev/) allows for advanced linting and type safety within raw SQL queries. After setup, SafeQL works with Prisma Client `$queryRaw` and `$executeRaw` to provide type safety when raw queries are required. @@ -36,7 +42,7 @@ Prisma Client supports write operations on models with a required `Unsupported` If you haven't already, enable the `postgresqlExtensions` Preview feature and add the `postgis` PostgreSQL extension in your Prisma schema: -```prisma highlight=3,9;add +```prisma generator client { provider = "prisma-client-js" //add-next-line diff --git a/content/200-orm/200-prisma-client/150-using-raw-sql/index.mdx b/content/200-orm/200-prisma-client/150-using-raw-sql/index.mdx new file mode 100644 index 0000000000..b598c28e4c --- /dev/null +++ b/content/200-orm/200-prisma-client/150-using-raw-sql/index.mdx @@ -0,0 +1,71 @@ +--- +title: 'Write your own SQL' +metaTitle: 'Write Your Own SQL in Prisma Client' +metaDescription: 'Learn how to use raw SQL queries in Prisma Client.' +--- + +While the Prisma Client API aims to make all your database queries intuitive, type-safe, and convenient, there may still be situations where raw SQL is the best tool for the job. + +This can happen for various reasons, such as the need to optimize the performance of a specific query or because your data requirements can't be fully expressed by Prisma Client's query API. + +In most cases, [TypedSQL](#writing-type-safe-queries-with-prisma-client-and-typedsql) allows you to express your query in SQL while still benefiting from Prisma Client's excellent user experience. However, since TypedSQL is statically typed, it may not handle certain scenarios, such as dynamically generated `WHERE` clauses. In these cases, you will need to use [`$queryRaw`](/orm/prisma-client/using-raw-sql/raw-queries#queryraw) or [`$executeRaw`](/orm/prisma-client/using-raw-sql/raw-queries#executeraw), or their unsafe counterparts. + +## Writing type-safe queries with Prisma Client and TypedSQL + +:::info + +TypedSQL is available in Prisma ORM 5.19.0 and later. For raw database access in previous versions, see [our raw queries documentation](/orm/prisma-client/using-raw-sql/raw-queries). + +::: + +### What is TypedSQL? + +TypedSQL is a new feature of Prisma ORM that allows you to write your queries in `.sql` files while still enjoying the great developer experience of Prisma Client. You can write the code you're comfortable with and benefit from fully-typed inputs and outputs. + +With TypedSQL, you can: + +1. Write complex SQL queries using familiar syntax +2. Benefit from full IDE support and syntax highlighting for SQL +3. Import your SQL queries as fully typed functions in your TypeScript code +4. Maintain the flexibility of raw SQL with the safety of Prisma's type system + +TypedSQL is particularly useful for: + +- Complex reporting queries that are difficult to express using Prisma's query API +- Performance-critical operations that require fine-tuned SQL +- Leveraging database-specific features not yet supported in Prisma's API + +By using TypedSQL, you can write efficient, type-safe database queries without sacrificing the power and flexibility of raw SQL. This feature allows you to seamlessly integrate custom SQL queries into your Prisma-powered applications, ensuring type safety and improving developer productivity. + +For a detailed guide on how to get started with TypedSQL, including setup instructions and usage examples, please refer to our [TypedSQL documentation](/orm/prisma-client/using-raw-sql/typedsql). + +## Raw queries + +Prior to version 5.19.0, Prisma Client only supported raw SQL queries that were not type-safe and required manual mapping of the query result to the desired type. + +While not as ergonomic as [TypedSQL](#writing-type-safe-queries-with-prisma-client-and-typedsql), these queries are still supported and are useful when TypedSQL queries are not possible either due to features not yet supported in TypedSQL or when the query is dynamically generated. + +### Alternative approaches to raw SQL queries in relational databases + +Prisma ORM supports four methods to execute raw SQL queries in relational databases: + +- [`$queryRaw`](/orm/prisma-client/using-raw-sql/raw-queries#queryraw) +- [`$executeRaw`](/orm/prisma-client/using-raw-sql/raw-queries#executeraw) +- [`$queryRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#queryrawunsafe) +- [`$executeRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#executerawunsafe) + +These commands are similar to using TypedSQL, but they are not type-safe and are written as strings in your code rather than in dedicated `.sql` files. + +### Alternative approaches to raw queries in document databases + +For MongoDB, Prisma ORM supports three methods to execute raw queries: + +- [`$runCommandRaw`](/orm/prisma-client/using-raw-sql/raw-queries#runcommandraw) +- [`.findRaw`](/orm/prisma-client/using-raw-sql/raw-queries#findraw) +- [`.aggregateRaw`](/orm/prisma-client/using-raw-sql/raw-queries#aggregateraw) + +These methods allow you to execute raw MongoDB commands and queries, providing flexibility when you need to use MongoDB-specific features or optimizations. + +`$runCommandRaw` is used to execute database commands, `.findRaw` is used to find documents that match a filter, and `.aggregateRaw` is used for aggregation operations. All three methods are available from Prisma version 3.9.0 and later. + +Similar to raw queries in relational databases, these methods are not type-safe and require manual handling of the query results. \ No newline at end of file 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 b24e361f48..e58a2cfc52 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 @@ -1000,3 +1000,15 @@ No - it is not yet possible to filter on the presence of a specific key. ### Is case insensitive filtering supported? No - [case insensitive filtering](https://github.com/prisma/prisma/issues/7390) is not yet supported. + +### How to set a default value for JSON fields? + +When you want to set a `@default` value the `Json` type, you need to enclose it with double-quotes inside the `@default` attribute (and potentially escape any "inner" double-quotes using a backslash), for example: + +```prisma +model User { + id Int @id @default(autoincrement()) + json1 Json @default("[]") + json2 Json @default("{ \"hello\": \"world\" }") +} +``` \ No newline at end of file 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 5ff9281997..72cbd01d7f 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 @@ -142,7 +142,7 @@ const prisma = new PrismaClient().$extends({ }) ``` -In the event a [raw query](/orm/prisma-client/queries/raw-database-access/raw-queries) is invoked, the `model` argument passed to the callback will be `undefined`. +In the event a [raw query](/orm/prisma-client/using-raw-sql/raw-queries) is invoked, the `model` argument passed to the callback will be `undefined`. For example, you can use the `$allOperations` method to log queries as follows: diff --git a/content/200-orm/200-prisma-client/300-client-extensions/200-extension-examples.mdx b/content/200-orm/200-prisma-client/300-client-extensions/200-extension-examples.mdx index 76cc926c50..7a8e48b647 100644 --- a/content/200-orm/200-prisma-client/300-client-extensions/200-extension-examples.mdx +++ b/content/200-orm/200-prisma-client/300-client-extensions/200-extension-examples.mdx @@ -29,6 +29,8 @@ The following is a list of extensions created by the community. If you want to c | [`prisma-extension-random`](https://github.com/nkeil/prisma-extension-random) | Lets you query for random rows in your database | | [`prisma-paginate`](https://github.com/sandrewTx08/prisma-paginate) | Adds support for paginating read queries | | [`prisma-extension-streamdal`](https://github.com/streamdal/prisma-extension-streamdal) | Adds support for Code-Native data pipelines using Streamdal | +| [`prisma-rbac`](https://github.com/multipliedtwice/prisma-rbac) | Adds customizable role-based access control | +| [`prisma-extension-redis`](https://github.com/yxx4c/prisma-extension-redis) | Extensive Prisma extension designed for efficient caching and cache invalidation using Redis and Dragonfly Databases | If you have built an extension and would like to see it featured, feel free to add it to the list by opening a pull request. 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 index cbb8e892b3..b44123c383 100644 --- 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 @@ -14,7 +14,7 @@ The following sample uses [middleware](/orm/prisma-client/client-extensions/midd -**Note:** This page demonstrates a sample use of middleware. We do not intend the sample to be a fully functional soft delete feature. +**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. 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 77b2313739..9940d6d11b 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 @@ -29,7 +29,7 @@ This section covers changes you will need to make to your application, regardles Depending on the version of Node.js, your Prisma schema should contain either `rhel-openssl-1.0.x` or `rhel-openssl-3.0.x` in the `generator` block: - + diff --git a/content/200-orm/200-prisma-client/500-deployment/301-edge/100-overview.mdx b/content/200-orm/200-prisma-client/500-deployment/301-edge/100-overview.mdx index 049508df76..2b6d0ea9b5 100644 --- a/content/200-orm/200-prisma-client/500-deployment/301-edge/100-overview.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/301-edge/100-overview.mdx @@ -1,12 +1,11 @@ --- -title: 'Overview' -metaTitle: 'Overview (Deploy Prisma ORM at the Edge)' +title: 'Deploying edge functions with Prisma ORM' +metaTitle: 'Overview: Deploy Prisma ORM at the Edge' metaDescription: 'Learn how to deploy your Prisma-backed apps to edge functions like Cloudflare Workers or Vercel Edge Functions' +sidebar_label: 'Overview' tocDepth: 2 --- -## Deploying edge functions with Prisma ORM - You can deploy an application that uses Prisma ORM to the edge. Depending on which edge function provider and which database you use, there are different considerations and things to be aware of. Here is a brief overview of all the edge function providers that are currently supported by Prisma ORM: 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 c44eced826..dc7bdb7cce 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 @@ -20,17 +20,17 @@ This guide demonstrates how to deploy an application to Deno Deploy in conjuncti ## Prerequisites -- a free [Prisma Data Platform](https://console.prisma.io) account +- a free [Prisma Data Platform](https://console.prisma.io/login) account - a free [Deno Deploy](https://deno.com/deploy) account - a PostgreSQL database - Node.js & npm installed -- Deno v1.29.4 or later installed. [Learn more](https://deno.land/manual/getting_started/installation). +- Deno v1.29.4 or later installed. [Learn more](https://docs.deno.com/runtime/manual/#install-deno). - (Recommended) Latest version of Prisma ORM. -- (Recommended) Deno extension for VS Code. [Learn more](https://deno.land/manual/getting_started/setup_your_environment#visual-studio-code). +- (Recommended) Deno extension for VS Code. [Learn more](https://docs.deno.com/runtime/manual/references/vscode_deno/). ## 1. Set up your application -To start, you create a directory for your project, and then use `deno run` to initialize your application with `prisma init` as an [npm package with npm specifiers](https://deno.land/manual/node/npm_specifiers). +To start, you create a directory for your project, and then use `deno run` to initialize your application with `prisma init` as an [npm package with npm specifiers](https://docs.deno.com/runtime/manual/node/npm_specifiers/). To set up your application: @@ -149,7 +149,7 @@ serve(handler) **VS Code error: `An import path cannot end with a '.ts' extension`**

-If you use VS Code and see the error `An import path cannot end with a '.ts' extension` for the `import` statements at the beginning of `index.ts`, you need to install the [Deno extension for VS Code](https://deno.land/manual/getting_started/setup_your_environment#visual-studio-code), select **View** > **Command Palette** and run the command **Deno: Initialize Workspace Configuration**. This tells VS Code that the TypeScript files in the current project need to run with Deno, which then triggers the correct validations. +If you use VS Code and see the error `An import path cannot end with a '.ts' extension` for the `import` statements at the beginning of `index.ts`, you need to install the [Deno extension for VS Code](https://docs.deno.com/runtime/manual/references/vscode_deno/), select **View** > **Command Palette** and run the command **Deno: Initialize Workspace Configuration**. This tells VS Code that the TypeScript files in the current project need to run with Deno, which then triggers the correct validations. @@ -163,7 +163,7 @@ After that, you test your application locally. To get started with Prisma Accelerate: -1. Sign up for a free [Prisma Data Platform account](https://console.prisma.io/) +1. Sign up for a free [Prisma Data Platform account](https://console.prisma.io/login) 1. Create a project 1. Navigate to the project you created 1. Enable Accelerate 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 fe736c8989..1a5faa315c 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 @@ -46,7 +46,7 @@ name: Deploy on: push: paths: - - ./prisma/migrations/** # Only run this workflow when migrations are updated + - prisma/migrations/** # Only run this workflow when migrations are updated branches: - main diff --git a/content/200-orm/200-prisma-client/500-deployment/600-deploy-migrations-from-a-local-environment.mdx b/content/200-orm/200-prisma-client/500-deployment/600-deploy-migrations-from-a-local-environment.mdx index 4ee4dddc38..ca9259c0d3 100644 --- a/content/200-orm/200-prisma-client/500-deployment/600-deploy-migrations-from-a-local-environment.mdx +++ b/content/200-orm/200-prisma-client/500-deployment/600-deploy-migrations-from-a-local-environment.mdx @@ -53,4 +53,4 @@ The pipeline should handle deployment to staging and production environments, an When you add Prisma Migrate to an **existing database**, you must [baseline](/orm/prisma-migrate/workflows/baselining) the production database. Baselining is performed **once**, and can be done from a local instance. -![](/img/orm/baseline-production-from-local.png) +![Baselining production from local with Prisma ORM](/img/orm/baseline-production-from-local.png) 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 e92f8c1241..ab210dfbbd 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 @@ -6,7 +6,7 @@ metaDescription: 'This page explains how to enable debugging output for Prisma C -You can enable debugging output in Prisma Client via the [`DEBUG`](/orm/reference/environment-variables-reference#debug) environment variable. It accepts two namespaces to print debugging output: +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: - `prisma:engine`: Prints relevant debug messages happening in a Prisma ORM [engine](https://github.com/prisma/prisma-engines/) - `prisma:client`: Prints relevant debug messages happening in the Prisma Client runtime 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 98f13afed4..d9fa3942c4 100644 --- a/content/200-orm/300-prisma-migrate/050-getting-started.mdx +++ b/content/200-orm/300-prisma-migrate/050-getting-started.mdx @@ -1,7 +1,8 @@ --- -title: 'Getting started' -metaTitle: 'Getting started' -metaDescription: 'Getting started' +title: 'Getting started with Prisma Migrate' +metaTitle: 'Getting started with Prisma Migrate' +metaDescription: 'Learn how to migrate your schema in a development environment using Prisma Migrate.' +sidebar_label: 'Getting started' tocDepth: 3 --- diff --git a/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/010-mental-model.mdx b/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/010-mental-model.mdx index 28e3aec478..a17acfd481 100644 --- a/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/010-mental-model.mdx +++ b/content/200-orm/300-prisma-migrate/200-understanding-prisma-migrate/010-mental-model.mdx @@ -25,11 +25,11 @@ The two main schema migration patterns are: - **Model/Entity-first migration:** with this pattern, you define the structure of the database schema with code and then use a migration tool to generate the SQL, for example, for syncing your application and database schema. -![](./mental-model-illustrations/entity-first-migration-flow.png) +![Model-first migration flow](./mental-model-illustrations/entity-first-migration-flow.png) - **Database-first migration:** with this pattern, you define the structure of your database and apply it to your database using SQL. You then _introspect_ the database to generate the code that describes the structure of your database to sync your application and database schema. -![](./mental-model-illustrations/database-first-migration-flow.png) +![Database-first migration flow](./mental-model-illustrations/database-first-migration-flow.png) @@ -171,7 +171,7 @@ Under the hood, the `migrate deploy` command: 1. Applies pending migrations 1. Updates `_prisma_migrations` table with the new migrations -![](../300-workflows/deploy-db.png) +![Workflow of Prisma Migrate](../300-workflows/deploy-db.png) The command should be run in an automated CI/ CD environment, for example GitHub Actions. 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 da4b30b2d3..87acbd79a4 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 @@ -9,7 +9,7 @@ tocDepth: 3 This guide describes how to seed your database using Prisma Client and Prisma ORM's integrated seeding functionality. Seeding allows you to consistently re-create the same data in your database and can be used to: -- Populate your database with data that is required for your application to start - for example, a default language or a default currency. +- Populate your database with data that is required for your application to start, such as a default language or currency. - Provide basic data for validating and using your application in a development environment. This is particularly useful if you are using Prisma Migrate, which sometimes requires resetting your development database. @@ -57,17 +57,19 @@ This can be useful to reduce memory usage (RAM) and increase execution speed of ## Integrated seeding with Prisma Migrate -Database seeding happens in two ways with Prisma ORM: manually with `prisma db seed` and automatically in `prisma migrate dev` and `prisma migrate reset`. +Database seeding happens in two ways with Prisma ORM: manually with `prisma db seed` and automatically in `prisma migrate reset` and (in some scenarios) `prisma migrate dev`. With `prisma db seed`, _you_ decide when to invoke the seed command. It can be useful for a test setup or to prepare a new development environment, for example. -Prisma Migrate also integrates seamlessly with your seeds, assuming you follow the steps in the section below. When Prisma Migrate resets the development database, seeding is triggered automatically if you have a "seed" property in the "prisma" section in your package.json. +Prisma Migrate also integrates seamlessly with your seeds, assuming you follow the steps in the section below. Seeding is triggered automatically when Prisma Migrate resets the development database. Prisma Migrate resets the database and triggers seeding in the following scenarios: - You manually run the `prisma migrate reset` CLI command. - The database is reset interactively in the context of using `prisma migrate dev` - for example, as a result of migration history conflicts or database schema drift. -- When you want to use `prisma migrate dev` or `prisma migrate reset` without seeding, you can pass the --skip-seed flag. +- The database is actually created by `prisma migrate dev`, because it did not exist before. + +When you want to use `prisma migrate dev` or `prisma migrate reset` without seeding, you can pass the `--skip-seed` flag. ## Example seed scripts @@ -411,8 +413,6 @@ psql file.sql 2. Execute `npx @snaplet/seed init prisma/seed` to initialize Snaplet Seed in your Prisma project. This command generates the seed client and creates an example seed file at `prisma/seed/seed.ts`. - > **Note:** Snaplet Seed also has an [AI-enhanced version](https://www.snaplet.dev/seed#ai). You can opt in for improved seed data quality with a free Snaplet account. - 3. Use the generated `@snaplet/seed` client within the `prisma/seed/seed.ts` file to compose your seeds. Here's how to create new users and posts by modifying the initially generated `prisma/seed/seed.ts` file: diff --git a/content/200-orm/300-prisma-migrate/300-workflows/100-team-development.mdx b/content/200-orm/300-prisma-migrate/300-workflows/100-team-development.mdx index 9f6437bee4..cce0dc57a8 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/100-team-development.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/100-team-development.mdx @@ -16,7 +16,7 @@ To incorporate changes from collaborators: npx prisma migrate dev ``` -Migrations are **applied in the same order as they were created**. The creation date is part of the migration subfolder name - for example, `20210316081837-updated-fields` was created on `2021-03-16-08:08:37`. +Migrations are **applied in the same order as they were created**. The creation date is part of the migration subfolder name - for example, `20210316081837-updated-fields` was created on `2021-03-16-08:18:37`. diff --git a/content/200-orm/300-prisma-migrate/300-workflows/45-data-migration.mdx b/content/200-orm/300-prisma-migrate/300-workflows/45-data-migration.mdx index 5c2fda3a5b..bd852bc07f 100644 --- a/content/200-orm/300-prisma-migrate/300-workflows/45-data-migration.mdx +++ b/content/200-orm/300-prisma-migrate/300-workflows/45-data-migration.mdx @@ -147,8 +147,6 @@ Inside the generated migration folder from the previous step, create a file call Add the following code to migrate the data from the `published` field to the `status` field in the file you just created: -Update your `package.json` file to include the data migration file: - ```ts file=prisma/migrations/20230417131956_add-status-column/data-migration.ts import { PrismaClient } from '@prisma/client' diff --git a/content/200-orm/300-prisma-migrate/300-workflows/existing-database.png b/content/200-orm/300-prisma-migrate/300-workflows/existing-database.png index c91a0b6b86..27842c8233 100644 Binary files a/content/200-orm/300-prisma-migrate/300-workflows/existing-database.png and b/content/200-orm/300-prisma-migrate/300-workflows/existing-database.png differ 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 f7ab37ad16..3101c0b8db 100644 --- a/content/200-orm/500-reference/050-prisma-client-reference.mdx +++ b/content/200-orm/500-reference/050-prisma-client-reference.mdx @@ -1641,11 +1641,11 @@ const groupUsers = await prisma.user.groupBy({ ### `findRaw()` -See: [Raw database access (`findRaw()`)](/orm/prisma-client/queries/raw-database-access/raw-queries#findraw). +See: [Using Raw SQL (`findRaw()`)](/orm/prisma-client/using-raw-sql/raw-queries#findraw). ### `aggreagateRaw()` -See: [Raw database access (`aggreagateRaw()`)](/orm/prisma-client/queries/raw-database-access/raw-queries#aggregateraw). +See: [Using Raw SQL (`aggreagateRaw()`)](/orm/prisma-client/using-raw-sql/raw-queries#aggregateraw). ## Model query options @@ -3062,6 +3062,8 @@ const user = await prisma.profile.create({ }) ``` +However, you can't use both the direct approach and the `connect` approach in the same query. See [this issue comment](https://github.com/prisma/prisma/issues/4322#issuecomment-737976117) for details. + ##### Create a new `Post` record and connect it to an existing `User` record ```ts @@ -3560,13 +3562,34 @@ const result = await prisma.user.findMany({ }) ``` +:::warning + +`not` will return all items that do not match a given value. However, if the column is nullable, `NULL` values will not be returned. If you require null values to be returned, use an [`OR`](#or) operator to include `NULL` values. + +::: + +##### Return all users where `name` does **not** equal `"Eleanor"` **including** users where `name` is `NULL` + +```ts +await prisma.user.findMany({ + where: { + OR: [ + { name: { not: 'Eleanor' } }, + { name: null } + ] + } +}) +``` + ### `in` Value `n` exists in list. -#### Remarks +:::note + +`null` values are not returned. For example, if you combine `in` and `NOT` to return a user whose name is _not_ in the list, users with `null` value names are not returned. -- `null` values are not returned. For example, if you combine `in` and `NOT` to return user whose name is _not_ in the list, users with `null` value names are not returned. +::: #### Examples @@ -5148,7 +5171,7 @@ const getUsers = await prisma.user.findMany({ The following query returns all users where the `sanctuaries` array contains the value `"RSPCA"`: - + ```ts @@ -5386,27 +5409,31 @@ Example parameter values: #### Examples -See [middleware examples](/orm/prisma-client/client-extensions/middleware#samples) . +See [middleware examples](/orm/prisma-client/client-extensions/middleware#samples). + +### `$queryRawTyped` + +See: [Using Raw SQL (`$queryRawTyped`)](/orm/prisma-client/using-raw-sql/typedsql). ### `$queryRaw` -See: [Raw database access (`$queryRaw`)](/orm/prisma-client/queries/raw-database-access/raw-queries#queryraw). +See: [Using Raw SQL (`$queryRaw`)](/orm/prisma-client/using-raw-sql/raw-queries#queryraw). ### `$queryRawUnsafe()` -See: [Raw database access (`$queryRawUnsafe()`)](/orm/prisma-client/queries/raw-database-access/raw-queries#queryrawunsafe). +See: [Using Raw SQL (`$queryRawUnsafe()`)](/orm/prisma-client/using-raw-sql/raw-queries#queryrawunsafe). ### `$executeRaw` -See: [Raw database access (`$executeRaw`)](/orm/prisma-client/queries/raw-database-access/raw-queries#executeraw). +See: [Using Raw SQL (`$executeRaw`)](/orm/prisma-client/using-raw-sql/raw-queries#executeraw). ### `$executeRawUnsafe()` -See: [Raw database access (`$executeRawUnsafe()`)](/orm/prisma-client/queries/raw-database-access/raw-queries#executerawunsafe). +See: [Using Raw SQL (`$executeRawUnsafe()`)](/orm/prisma-client/using-raw-sql/raw-queries#executerawunsafe). ### `$runCommandRaw()` -See: [Raw database access (`$runCommandRaw()`)](/orm/prisma-client/queries/raw-database-access/raw-queries#runcommandraw). +See: [Using Raw SQL (`$runCommandRaw()`)](/orm/prisma-client/using-raw-sql/raw-queries#runcommandraw). ### `$transaction()` 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 f177f04f9f..ef7d921c60 100644 --- a/content/200-orm/500-reference/100-prisma-schema-reference.mdx +++ b/content/200-orm/500-reference/100-prisma-schema-reference.mdx @@ -1605,10 +1605,10 @@ Defines a [default value for a field](/orm/prisma-schema/data-model/models#defin - [`cuid()`](#cuid) - [`uuid()`](#uuid) - [`now()`](#now) - - Default values that cannot yet be represented in the Prisma schema are represented by the [`dbgenerated(...)` function](#dbgenerated) when you use [introspection](/orm/prisma-schema/introspection). - Default values are not allowed on relation fields in the Prisma schema. Note however that you can still define default values on the fields backing a relation (the ones listed in the `fields` argument in the `@relation` attribute). A default value on the field backing a relation will mean that relation is populated automatically for you. - Default values can be used with [scalar lists](/orm/prisma-client/special-fields-and-types/working-with-scalar-lists-arrays) in databases that natively support them. +- 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\" }")`. ##### MongoDB 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 6dcad87fc3..1c2a012547 100644 --- a/content/200-orm/500-reference/200-prisma-cli-reference.mdx +++ b/content/200-orm/500-reference/200-prisma-cli-reference.mdx @@ -336,12 +336,14 @@ generator client { #### Options -| Option | Required | Description | Default | -| -------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -| `--data-proxy` | No | The `generate` command will generate Prisma Client for use with [Prisma Accelerate](/accelerate) prior to Prisma 5.0.0. Mutually exclusive with `--accelerate` and `--no-engine`. | -| `--accelerate` | No | The `generate` command will generate Prisma Client for use with [Prisma Accelerate](/accelerate). Mutually exclusive with `--data-proxy` and `--no-engine`. Available in Prisma 5.1.0 and later. | -| `--no-engine` | No | The `generate` command will generate Prisma Client without an accompanied engine for use with [Prisma Accelerate](/accelerate). Mutually exclusive with `--data-proxy` and `--accelerate`. Available in Prisma ORM 5.2.0 and later. | -| `--watch` | No | The `generate` command will continue to watch the `schema.prisma` file and re-generate Prisma Client on file changes. | +| Option | Required | Description | Default | +| --------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `--data-proxy` | No | The `generate` command will generate Prisma Client for use with [Prisma Accelerate](/accelerate) prior to Prisma 5.0.0. Mutually exclusive with `--accelerate` and `--no-engine`. | +| `--accelerate` | No | The `generate` command will generate Prisma Client for use with [Prisma Accelerate](/accelerate). Mutually exclusive with `--data-proxy` and `--no-engine`. Available in Prisma 5.1.0 and later. | +| `--no-engine` | No | The `generate` command will generate Prisma Client without an accompanied engine for use with [Prisma Accelerate](/accelerate). Mutually exclusive with `--data-proxy` and `--accelerate`. Available in Prisma ORM 5.2.0 and later. | +| `--no-hints` | No | The `generate` command will generate Prisma Client without usage hints being printed to the terminal. Available in Prisma ORM 5.16.0 and later. | +| `--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. | @@ -519,8 +521,9 @@ Formats the Prisma schema file, which includes validating, formatting, and persi #### Arguments | Argument | Required | Description | Default | -| ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | +|------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------| | `--schema` | No | Specifies the path to the desired `schema.prisma` file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`, `./prisma/schema.prisma` | +| `--check` | No | Fails if any files are unformatted. This can be used in CI to detect if the schema is formatted correctly | | #### Examples diff --git a/content/200-orm/500-reference/250-error-reference.mdx b/content/200-orm/500-reference/250-error-reference.mdx index 1311944deb..49ce6fee9a 100644 --- a/content/200-orm/500-reference/250-error-reference.mdx +++ b/content/200-orm/500-reference/250-error-reference.mdx @@ -472,13 +472,13 @@ The included usage of the current plan has been exceeded. This can only occur on #### `P6004` (`QueryTimeout`) -The global timeout of Accelerate has been exceeded. You can find the limit [here](/accelerate/limitations#query-timeout-limit). +The global timeout of Accelerate has been exceeded. You can find the limit [here](/accelerate/connection-pooling#query-timeout-limit). > Also see the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout) for more information. #### `P6005` (`InvalidParameters`) -The user supplied invalid parameters. Currently only relevant for transaction methods. For example, setting a timeout that is too high. You can find the limit [here](/accelerate/limitations#interactive-transactions-query-timeout-limit). +The user supplied invalid parameters. Currently only relevant for transaction methods. For example, setting a timeout that is too high. You can find the limit [here](/accelerate/connection-pooling#interactive-transactions-query-timeout-limit). #### `P6006` (`VersionNotSupported`) @@ -490,11 +490,9 @@ The engine failed to start. For example, it couldn't establish a connection to t > Also see the [troubleshooting guide](/accelerate/troubleshoot#p6008-connectionerrorenginestarterror) for more information. -The global response size limit of Accelerate has been exceeded. You can find the limit [here](/accelerate/limitations#response-size-limit). - #### `P6009` (`ResponseSizeLimitExceeded`) -The global response size limit of Accelerate has been exceeded. You can find the limit [here](/accelerate/limitations#response-size-limit). +The global response size limit of Accelerate has been exceeded. You can find the limit [here](/accelerate/connection-pooling#response-size-limit). > Also see the [troubleshooting guide](/accelerate/troubleshoot#p6009-responsesizelimitexceeded) for more information. 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 07b96a63cd..698fe8605e 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 @@ -71,7 +71,7 @@ In the list below, you can find a history of Prisma Client and Prisma schema fea | [`interactiveTransactions`](/orm/prisma-client/queries/transactions#interactive-transactions) | [2.29.0](https://github.com/prisma/prisma/releases/tag/2.29.0) |
  • [4.7.0](https://github.com/prisma/prisma/releases/tag/4.7.0)
  • with Prisma Accelerate [5.1.1](https://github.com/prisma/prisma/releases/tag/5.1.1)
| | [`extendedIndexes`](/orm/prisma-schema/data-model/indexes) | [3.5.0](https://github.com/prisma/prisma/releases/tag/3.5.0) | [4.0.0](https://github.com/prisma/prisma/releases/tag/4.0.0) | | [`filterJson`](/orm/prisma-client/special-fields-and-types/working-with-json-fields#filter-on-a-json-field-simple) | [2.23.0](https://github.com/prisma/prisma/releases/tag/2.23.0) | [4.0.0](https://github.com/prisma/prisma/releases/tag/4.0.0) | -| [`improvedQueryRaw`](/orm/prisma-client/queries/raw-database-access/raw-queries#raw-query-type-mapping) | [3.14.0](https://github.com/prisma/prisma/releases/tag/3.14.0) | [4.0.0](https://github.com/prisma/prisma/releases/tag/4.0.0) | +| [`improvedQueryRaw`](/orm/prisma-client/using-raw-sql/raw-queries#raw-query-type-mapping) | [3.14.0](https://github.com/prisma/prisma/releases/tag/3.14.0) | [4.0.0](https://github.com/prisma/prisma/releases/tag/4.0.0) | | [`cockroachdb`](/orm/overview/databases/cockroachdb) |
  • [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0)
  • migrations in CockroachDB in [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0)
| [3.14.0](https://github.com/prisma/prisma/releases/tag/3.14.0) | | [`mongodb`](/orm/overview/databases/mongodb) |
  • [2.27.0](https://github.com/prisma/prisma/releases/tag/2.27.0)
  • introspection of MongoDB in [3.2.0](https://github.com/prisma/prisma/releases/tag/3.2.0)
  • introspection of embedded documents in [3.4.0](https://github.com/prisma/prisma/releases/tag/3.4.0)
  • MongoDB embedded documents in [3.10.0](https://github.com/prisma/prisma/releases/tag/3.10.0)
  • introspection of embedded documents in [3.10.0](https://github.com/prisma/prisma/releases/tag/3.10.0)
  • raw query support for MongoDB in [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0)
  • filters in embedded documents as an Experimental Feature in [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0)
  • order by embedded documents in [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0)
| [3.12.0](https://github.com/prisma/prisma/releases/tag/3.12.0) | | [`microsoftSqlServer`](/orm/overview/databases/sql-server) | [2.10.0](https://github.com/prisma/prisma/releases/tag/2.10.0) | [3.0.1](https://github.com/prisma/prisma/releases/tag/3.0.1) | diff --git a/content/200-orm/500-reference/500-preview-features/080-cli-preview-features.mdx b/content/200-orm/500-reference/500-preview-features/080-cli-preview-features.mdx index caf3d79670..e62469b681 100644 --- a/content/200-orm/500-reference/500-preview-features/080-cli-preview-features.mdx +++ b/content/200-orm/500-reference/500-preview-features/080-cli-preview-features.mdx @@ -1,7 +1,8 @@ --- -title: 'Prisma CLI' +title: 'Prisma CLI Preview features' metaTitle: 'Prisma CLI Preview features' metaDescription: Prisma CLI features that are currently in Preview. +sidebar_label: 'Prisma CLI' tocDepth: 3 --- 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 fb32510a44..ff95e20ff9 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 @@ -312,7 +312,7 @@ This section includes changes that affect Prisma Client. #### Raw query type mapping: scalar values are now deserialized as their correct JavaScript types -In versions 3.14.x and 3.15.x, [raw query type mapping](/orm/prisma-client/queries/raw-database-access/raw-queries#raw-query-type-mapping) was available with the Preview feature `improvedQueryRaw`. In version 4.0.0, we have made raw query type mapping Generally Available. You do not need to use `improvedQueryRaw` to get this functionality in versions 4.0.0 and later. +In versions 3.14.x and 3.15.x, [raw query type mapping](/orm/prisma-client/using-raw-sql/raw-queries#raw-query-type-mapping) was available with the Preview feature `improvedQueryRaw`. In version 4.0.0, we have made raw query type mapping Generally Available. You do not need to use `improvedQueryRaw` to get this functionality in versions 4.0.0 and later. Raw queries now deserialize scalar values to their corresponding JavaScript types. Note that Prisma ORM infers types from the values themselves and not from the Prisma Schema types. @@ -346,7 +346,7 @@ You must make equivalent code changes for the other data types in the table abov #### Raw query mapping: PostgreSQL type-casts -In versions 3.14.x and 3.15.x, [raw query type mapping](/orm/prisma-client/queries/raw-database-access/raw-queries#raw-query-type-mapping) was available with the Preview feature `improvedQueryRaw`. In version 4.0.0, we have made raw query type mapping Generally Available. You do not need to use `improvedQueryRaw` to get this functionality in versions 4.0.0 and later. +In versions 3.14.x and 3.15.x, [raw query type mapping](/orm/prisma-client/using-raw-sql/raw-queries#raw-query-type-mapping) was available with the Preview feature `improvedQueryRaw`. In version 4.0.0, we have made raw query type mapping Generally Available. You do not need to use `improvedQueryRaw` to get this functionality in versions 4.0.0 and later. Before version 4.0.0, many PostgreSQL type-casts did not work. We have tightened the type coercion rules so that all type-casts now work. As a result, some implicit casts now fail. @@ -370,7 +370,7 @@ await prisma.$queryRaw`select length(${42}::text);` #### Raw query mapping: PostgreSQL and JavaScript integers -In versions 3.14.x and 3.15.x, [raw query type mapping](/orm/prisma-client/queries/raw-database-access/raw-queries#raw-query-type-mapping) was available with the Preview feature `improvedQueryRaw`. In version 4.0.0, we have made raw query type mapping Generally Available. You do not need to use `improvedQueryRaw` to get this functionality in versions 4.0.0 and later. +In versions 3.14.x and 3.15.x, [raw query type mapping](/orm/prisma-client/using-raw-sql/raw-queries#raw-query-type-mapping) was available with the Preview feature `improvedQueryRaw`. In version 4.0.0, we have made raw query type mapping Generally Available. You do not need to use `improvedQueryRaw` to get this functionality in versions 4.0.0 and later. Prisma ORM sends JavaScript integers to PostgreSQL as `INT8`. This might conflict with your user-defined functions that accept only `INT4` as input. 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 784051e861..a099b97d22 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 @@ -23,7 +23,7 @@ When invoking the [`delete()`](/orm/prisma-client/queries/crud#delete-a-single-r The behavior in Prisma ORM 2, without upgrading, does not allow setting referential actions at all. [See Prisma ORM 2.x default referential actions](#prisma-orm-2x-default-referential-actions) -If you need to actually use the cascade behavior configured in the database, you _can_ use [`raw`](/orm/prisma-client/queries/raw-database-access/raw-queries) SQL queries to [delete multiple referenced records](/orm/prisma-client/queries/crud#deleting-all-data-with-raw-sql--truncate). This is because Prisma Client will **not** perform runtime checks on raw queries. +If you need to actually use the cascade behavior configured in the database, you _can_ use [`raw`](/orm/prisma-client/using-raw-sql/raw-queries) SQL queries to [delete multiple referenced records](/orm/prisma-client/queries/crud#deleting-all-data-with-raw-sql--truncate). This is because Prisma Client will **not** perform runtime checks on raw queries. ### Prisma ORM 2.x default referential actions 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 dc8fcae2b9..2180704600 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 @@ -32,13 +32,13 @@ This means that you will notice an impact when running Prisma `migrate` or `db p You can check out the [Named constraints upgrade path](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/named-constraints) for more information on how to proceed. -### [$queryRaw](/orm/prisma-client/queries/raw-database-access/raw-queries) +### [$queryRaw](/orm/prisma-client/using-raw-sql/raw-queries) From version 3.x onwards, the `$queryRaw` method now only supports a template literal. This means that if your application relied on `$queryRaw` calls using _strings_, those calls will **not** work anymore. We advise you to use template literals wherever possible for security reasons or resort to `$queryRawUnsafe` otherwise, after carefully escaping queries to prevent SQL injections. -You can learn more about the new `$queryRaw` and `$queryRawUnsafe` methods in the [Raw database access](/orm/prisma-client/queries/raw-database-access/raw-queries) section of the docs. +You can learn more about the new `$queryRaw` and `$queryRawUnsafe` methods in the [Raw database access](/orm/prisma-client/using-raw-sql/raw-queries) section of the docs. ### [Json Null Equality](/orm/prisma-client/special-fields-and-types/working-with-json-fields#filtering-by-null-values) diff --git a/content/200-orm/800-more/400-comparisons/01-prisma-and-typeorm.mdx b/content/200-orm/800-more/400-comparisons/01-prisma-and-typeorm.mdx index c2ecdcf6c4..6a108fa0d0 100644 --- a/content/200-orm/800-more/400-comparisons/01-prisma-and-typeorm.mdx +++ b/content/200-orm/800-more/400-comparisons/01-prisma-and-typeorm.mdx @@ -24,7 +24,7 @@ It uses the [Prisma schema](/orm/prisma-schema) to define application models in TypeORM and Prisma ORM operate on different levels of abstraction. TypeORM is closer to mirroring SQL in its API while Prisma Client provides a higher-level abstraction that was carefully designed with the common tasks of application developers in mind. Prisma ORM's API design heavily leans on the idea of [making the right thing easy](https://jason.energy/right-thing-easy-thing/). -While Prisma Client operates on a higher-level of abstraction, it strives to expose the full power of the underlying database and lets you drop down to [raw SQL](/orm/prisma-client/queries/raw-database-access/raw-queries) at any time if your use case requires it. +While Prisma Client operates at a higher level of abstraction, it strives to expose the full power of the underlying database, allowing you to drop down to [raw SQL](/orm/prisma-client/using-raw-sql/raw-queries) at any time if your use case requires it. The following sections examine a few examples for how Prisma ORM's and TypeORM's APIs differ in certain scenarios and what the rationale of Prisma ORM's API design is in these cases. diff --git a/content/200-orm/800-more/400-comparisons/03-prisma-and-mongoose.mdx b/content/200-orm/800-more/400-comparisons/03-prisma-and-mongoose.mdx index 3b1d86c8aa..2201e00fb2 100644 --- a/content/200-orm/800-more/400-comparisons/03-prisma-and-mongoose.mdx +++ b/content/200-orm/800-more/400-comparisons/03-prisma-and-mongoose.mdx @@ -213,7 +213,7 @@ await user.save() ## Updating objects -**Prisma ORM ** +**Prisma ORM** ```ts const user = await prisma.user.update({ diff --git a/content/200-orm/800-more/400-comparisons/04-prisma-and-drizzle.mdx b/content/200-orm/800-more/400-comparisons/04-prisma-and-drizzle.mdx index a2037f92dd..69d3afe1ff 100644 --- a/content/200-orm/800-more/400-comparisons/04-prisma-and-drizzle.mdx +++ b/content/200-orm/800-more/400-comparisons/04-prisma-and-drizzle.mdx @@ -23,13 +23,16 @@ While Prisma ORM and Drizzle solve similar problems, they work in very different Drizzle is not _fully_ type safe. As quoted on this [comparison study](https://github.com/thetutlage/meta/discussions/8) done by a 3rd party, "Drizzle gives the impression of type-safety. However, only the query results have type information. You can write invalid queries with Drizzle." With Prisma, you get _full_ type safety thanks to the generated types. This means, less potential for errors when writing code and collaborating with team members. + ## API design & Level of abstraction Drizzle and Prisma ORM operate on different levels of abstraction. Drizzle's philosophy is "If you know SQL, you know Drizzle ORM". It mirrors SQL in its API while Prisma Client provides a higher-level abstraction that was designed with the common tasks of application developers in mind. Prisma ORM's API design heavily leans on the idea of [making the right thing easy](https://jason.energy/right-thing-easy-thing/). -While Prisma Client operates on a higher level of abstraction, you are able to drop down to [raw SQL](/orm/prisma-client/queries/raw-database-access/raw-queries) at any time. However, full use of Prisma ORM and development of your application does not require SQL knowledge. Prisma ORM's goal is to construct a query syntax focused on developer experience and productivity that feels familiar to developers. You can learn more about this here: [Why Prisma](/orm/overview/introduction/why-prisma#application-developers-should-care-about-data--not-sql). +While Prisma Client operates on a higher level of abstraction, you are able to drop down to [raw SQL](/orm/prisma-client/using-raw-sql) at any time. However, full use of Prisma ORM and development of your application does not require SQL knowledge. Prisma ORM's goal is to construct a query syntax focused on developer experience and productivity that feels familiar to developers. You can learn more about this here: [Why Prisma](/orm/overview/introduction/why-prisma#application-developers-should-care-about-data--not-sql). + +For the few queries that are unable to be expressed in the Prisma Client API, Prisma ORM also offers [TypedSQL](/orm/prisma-client/using-raw-sql/typedsql) which provides a more familiar and type-safe experience by directly utilizing `.sql` files. Your existing SQL tooling and workflow can work alongside Prisma Client to handle any level of abstraction desired. -The following sections examine a few examples of how Prisma ORM's and Drizzle's APIs differ in certain scenarios and what the rationale of Prisma ORM's API design is in these cases. +While fully typed SQL queries are available in Prisma ORM with TypedSQL, the following sections examine a few examples of how the Prisma and Drizzle APIs differ and what the rationale of Prisma ORM's API design is in these cases. ### Data modeling @@ -437,8 +440,8 @@ Both Drizzle and Prisma offer products alongside an ORM. Prisma Studio was relea In addition to Prisma Studio, Prisma offers commercial products via the Prisma Data Platform: -- [Prisma Accelerate](https://prisma.io/data-platform/accelerate): A connection pooler and global cache that integrates with Prisma ORM. Users can take advantage of connection pooling immediately and can control caching at an individual query level. -- [Prisma Pulse](https://prisma.io/data-platform/pulse): A change data capture (CDC) service where Prisma Client can subscribe to database changes and receive them in real-time with little to no setup. +- [Prisma Accelerate](https://www.prisma.io/data-platform/accelerate): A connection pooler and global cache that integrates with Prisma ORM. Users can take advantage of connection pooling immediately and can control caching at an individual query level. +- [Prisma Pulse](https://www.prisma.io/data-platform/pulse): A change data capture (CDC) service where Prisma Client can subscribe to database changes and receive them in real-time with little to no setup. These products work hand-in-hand with Prisma ORM to offer comprehensive data tooling, making building data-driven applications easy by following [Data DX](https://datadx.io/) principles. @@ -446,7 +449,7 @@ These products work hand-in-hand with Prisma ORM to offer comprehensive data too Both Drizzle and Prisma ORM have cases where users want to do something not directly supported by the library. Drizzle relies on the expressiveness of SQL to avoid these cases, while Prisma ORM has [Prisma Client extensions](/orm/prisma-client/client-extensions) to allow any user to add additional behaviors to their instance of Prisma Client. These extensions are also shareable, meaning teams can develop them for use across their projects or even for use by other teams. -While Drizzle is a relatively new product, Prisma ORM was [released in 2021](https://www.prisma.io/blog/prisma-the-complete-orm-inw24qjeawmb) and is well established in the JavaScript/TypeScript space. It has proven value and many companies trust [Prisma ORM in production](http://prisma.io/showcase). +While Drizzle is a relatively new product, Prisma ORM was [released in 2021](https://www.prisma.io/blog/prisma-the-complete-orm-inw24qjeawmb) and is well established in the JavaScript/TypeScript space. It has proven value and many companies trust [Prisma ORM in production](https://www.prisma.io/showcase). Prisma ORM is also included as the data layer tool of choice in many meta-frameworks and development platforms like [Amplication](https://amplication.com/), [Wasp](https://wasp-lang.dev/), [RedwoodJS](https://redwoodjs.com/), [KeystoneJS](https://keystonejs.com/), [Remix](https://remix.run/) and the [t3 stack](https://create.t3.gg/). @@ -478,6 +481,4 @@ This tool allows you to evaluate the latency and throughput of various ORMs unde Both Drizzle ORM and Prisma ORM are tools for data access and migrations. Drizzle is focused on being a thin wrapper around a SQL-like syntax while Prisma is focused on a convenient and expressive API. Other important differences include Prisma ORM's support of MSSQL and MongoDB, support for additional features via [Prisma Client extensions](/orm/prisma-client/client-extensions), additional cloud-ready products, and a robust ecosystem. -For teams that use SQL daily, Drizzle offers a convenient wrapper that will feel familiar and is type-safe. Prisma ORM's `$queryRaw` feature, while available, does not provide the same level of type safety. However, the experience of writing raw SQL in Prisma ORM can be enhanced using the [SafeQL](https://safeql.dev/compatibility/prisma.html) community plugin for Prisma ORM, offering syntax highlighting and type-checking in your editor as well. - On the other hand, for teams that are a mix of developers (front-end, back-end, and full-stack) that have varying levels of experience with databases, Prisma ORM offers a comprehensive and easy-to-learn approach for data access and managing database schemas. diff --git a/content/200-orm/800-more/450-migrating-to-prisma/01-migrate-from-typeorm.mdx b/content/200-orm/800-more/450-migrating-to-prisma/01-migrate-from-typeorm.mdx index 94893f5df5..efeddfdbbf 100644 --- a/content/200-orm/800-more/450-migrating-to-prisma/01-migrate-from-typeorm.mdx +++ b/content/200-orm/800-more/450-migrating-to-prisma/01-migrate-from-typeorm.mdx @@ -289,7 +289,7 @@ If you're using VS Code, be sure to install the [Prisma VS Code extension](https If you're not using PostgreSQL, you need to adjust the `provider` field on the `datasource` block to the database you currently use: - +
@@ -342,7 +342,7 @@ datasource db { Once that's done, you can configure your [database connection URL](/orm/reference/connection-urls) in the `.env` file. Here's how the database connection from TypeORM maps to the connection URL format used by Prisma ORM: - +
diff --git a/content/200-orm/800-more/450-migrating-to-prisma/02-migrate-from-sequelize.mdx b/content/200-orm/800-more/450-migrating-to-prisma/02-migrate-from-sequelize.mdx index 3de007b931..9a350c4ebb 100644 --- a/content/200-orm/800-more/450-migrating-to-prisma/02-migrate-from-sequelize.mdx +++ b/content/200-orm/800-more/450-migrating-to-prisma/02-migrate-from-sequelize.mdx @@ -219,7 +219,7 @@ If you're using VS Code, be sure to install the [Prisma VS Code extension](https If you're not using PostgreSQL, you need to adjust the `provider` field on the `datasource` block to the database you currently use: - + @@ -269,7 +269,7 @@ datasource db { Once that's done, you can configure your [database connection URL](/orm/reference/connection-urls) in the `.env` file. Here's how the database connection from Sequelize maps to the connection URL format used by Prisma ORM: - +
diff --git a/content/200-orm/800-more/450-migrating-to-prisma/03-migrate-from-mongoose.mdx b/content/200-orm/800-more/450-migrating-to-prisma/03-migrate-from-mongoose.mdx index 7ea5285637..b6b0c209b5 100644 --- a/content/200-orm/800-more/450-migrating-to-prisma/03-migrate-from-mongoose.mdx +++ b/content/200-orm/800-more/450-migrating-to-prisma/03-migrate-from-mongoose.mdx @@ -23,7 +23,7 @@ Note that the steps for migrating from Mongoose to Prisma ORM are always the sam 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. -Prisma ORM lends itself really well for **incremental adoption**. This means, you don't have migrate your entire project from Mongoose to Prisma ORM at once, but rather you can _step-by-step_ move your database queries from Mongoose to Prisma ORM. +Prisma ORM lends itself really well for **incremental adoption**. This means, you don't have to migrate your entire project from Mongoose to Prisma ORM at once, but rather you can _step-by-step_ move your database queries from Mongoose to Prisma ORM. ## Overview of the sample project diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/100-help-articles/500-comparing-columns-through-raw-queries.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/100-help-articles/500-comparing-columns-through-raw-queries.mdx index 00be4d86c1..146867f787 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/100-help-articles/500-comparing-columns-through-raw-queries.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/100-help-articles/500-comparing-columns-through-raw-queries.mdx @@ -4,21 +4,19 @@ metaTitle: 'Compare columns of the same table with raw queries' metaDescription: 'Compare columns with inbuilt raw query methods in Prisma' --- - - -## Problem - Comparing different columns from the same table is a common scenario that developers encounter. Some examples include comparing two numeric values in the same table or comparing two dates in a same table. There's an existing [GitHub Issue](https://github.com/prisma/prisma/issues/5048) regarding the same. - +:::warning -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) +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](/orm/reference/prisma-client-reference#compare-columns-in-the-same-table). - +The below information is kept for backwards compatibility with Prisma ORM versions prior to 4.3.0. + +::: ## Workaround -Comparing values from two columns in the same table can be achieved by using [raw queries](/orm/prisma-client/queries/raw-database-access/raw-queries). +Comparing values from two columns in the same table can be achieved by using [raw queries](/orm/prisma-client/using-raw-sql/raw-queries). ### Comparing numeric values diff --git a/content/200-orm/800-more/600-help-and-troubleshooting/100-help-articles/900-prisma-nuxt-module.mdx b/content/200-orm/800-more/600-help-and-troubleshooting/100-help-articles/900-prisma-nuxt-module.mdx index ff7e72017d..0820bdae57 100644 --- a/content/200-orm/800-more/600-help-and-troubleshooting/100-help-articles/900-prisma-nuxt-module.mdx +++ b/content/200-orm/800-more/600-help-and-troubleshooting/100-help-articles/900-prisma-nuxt-module.mdx @@ -26,21 +26,19 @@ This module provides several features to streamline the setup and usage of Prism npx nuxi@latest init test-nuxt-app ``` -2. Navigate to project directory and install `@prisma/nuxt`: +2. Navigate to project directory and install `@prisma/nuxt` using the Nuxt CLI: ```terminal cd test-nuxt-app - npm install @prisma/nuxt + npx nuxi@latest module add @prisma/nuxt ``` +
+ :::warning -3. Add `@prisma/nuxt` to your `nuxt.config.ts`: - ```typescript - export default defineNuxtConfig({ - modules: ["@prisma/nuxt"], - devtools: { enabled: true }, - }); - ``` + If you're using `pnpm`, make sure to hoist Prisma dependencies. Follow the steps [here](/orm/more/help-and-troubleshooting/help-articles/prisma-nuxt-module#prisma-studio-not-opening-with-pnpm) for detailed instructions. + + ::: -4. Start the development server: +3. Start the development server: ```terminal npm run dev ``` @@ -85,7 +83,7 @@ This module provides several features to streamline the setup and usage of Prism 5. Install and generate a [Prisma Client](/orm/reference/prisma-client-reference) which enables you to query your DB 6. Prompt you to start the [Prisma Studio](/orm/tools/prisma-studio) -5. You can now use Prisma ORM in your project. If you accepted the prompt to add Prisma Studio, you can access Prisma Studio through the Nuxt Devtools. See the [usage section](#usage) to learn how to use Prisma Client in your app. +4. You can now use Prisma ORM in your project. If you accepted the prompt to add Prisma Studio, you can access Prisma Studio through the Nuxt Devtools. See the [usage section](#usage) to learn how to use Prisma Client in your app. ## Using a different database provider @@ -242,6 +240,12 @@ export default prisma if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma ``` +
+:::info + +Use the `prisma` instance from the `lib` folder if you want to leverage a client using [Prisma Client extensions](/orm/prisma-client/client-extensions). + +::: #### Using the global Prisma Client instance in your API route @@ -304,4 +308,51 @@ The `usePrismaClient` module does not currently allow for configuration of `Pris ### The `usePrismaClient` composable is not supported in edge runtimes -The `usePrismaClient` composable currently relies on a `PrismaClient` instance that does not work in edge runtimes. If you require edge support for the composable, please let us know on [Discord](https://pris.ly/discord) or [GitHub](https://github.com/prisma/nuxt-prisma). \ No newline at end of file +The `usePrismaClient` composable currently relies on a `PrismaClient` instance that does not work in edge runtimes. If you require edge support for the composable, please let us know on [Discord](https://pris.ly/discord) or [GitHub](https://github.com/prisma/nuxt-prisma). + +## Troubleshooting + +### Prisma Studio not opening with `pnpm` + +If you're encountering the following error when using `pnpm` and Prisma Studio isn't opening: + +```terminal +Uncaught SyntaxError: The requested module '/_nuxt/node_modules/.pnpm/*@*/node_modules/@prisma/client/index-browser.js?v=' does not provide an export named 'PrismaClient' (at plugin.mjs?v=*) +``` + +To resolve this issue, create a `.npmrc` file in your project root and add the following configuration to hoist Prisma dependencies: + +```.npmrc file=.npmrc +hoist-pattern[]=*prisma* +``` + +This will ensure that Prisma dependencies are properly resolved by `pnpm`. + +### Resolving `TypeError: Failed to resolve module specifier ".prisma/client/index-browser"` + +If you encounter the following error message in the browser console after building and previewing your application: + +``` +TypeError: Failed to resolve module specifier ".prisma/client/index-browser" +``` +To resolve this issue, add the following configuration to your nuxt.config.ts file: + +```ts file=nuxt.config.ts +import { defineNuxtConfig } from 'nuxt' + +export default defineNuxtConfig({ + modules: [ + '@prisma/nuxt', + ], + // additional config + vite: { + resolve: { + alias: { + '.prisma/client/index-browser': './node_modules/.prisma/client/index-browser.js', + }, + }, + }, +}) +``` + +This configuration ensures that the module specifier is correctly mapped to the appropriate file. \ No newline at end of file diff --git a/content/200-orm/800-more/700-releases.mdx b/content/200-orm/800-more/700-releases.mdx index 064522801f..cfc0d22138 100644 --- a/content/200-orm/800-more/700-releases.mdx +++ b/content/200-orm/800-more/700-releases.mdx @@ -54,12 +54,6 @@ If a feature or product is **Generally Available**: - The solution has been tested for some time and we received enough feedback to consider it stable and ready for production use. - There should be no bugs in 99% of cases (completely bug-free software cannot be guaranteed) -## Roadmap - -Our roadmap helps us share our current priorities: what we are currently working on and what we are planning to work on in the near term. This reflects our _current plans_ today, and the content is subject to change at any time. Actual results and plans may differ as a result of changing our product strategy or reacting to demands from our user base. - -You can [check out the full roadmap here](https://pris.ly/roadmap). - ## Versioning Prisma ORM's release scheme adheres to Semantic Versioning ([SemVer](https://semver.org/)) starting with version `3.x.x`. diff --git a/content/300-accelerate/100-what-is-accelerate.mdx b/content/300-accelerate/100-what-is-accelerate.mdx deleted file mode 100644 index f18880b9d0..0000000000 --- a/content/300-accelerate/100-what-is-accelerate.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: 'What is Accelerate' -metaTitle: 'What is Accelerate' -metaDescription: 'Learn about Accelerate, a global cache and serverless connection pool that makes your database queries faster.' -tocDepth: 3 -toc: true ---- - - - -[Accelerate](https://www.prisma.io/data-platform/accelerate) is a global database cache available in 300 locations that you can use to achieve up to 1000x faster database queries. - -Its main features are: - -- a global cache -- scalable connection pool for serverless and edge applications -- usage of Prisma Client at the edge (e.g. in Cloudflare Workers or Vercel Edge Functions) - -The goal of Accelerate is to improve response times and reduce database load. It works by caching data at the edge using established caching patterns that you control. - -While Accelerate is beneficial for all types of applications, being at the edge provides additional benefits to edge function environments like [Vercel Edge Functions](https://vercel.com/docs/concepts/functions/edge-functions), [Cloudflare Workers](https://workers.cloudflare.com/), and [Deno Deploy](https://deno.com/deploy). Cache hits can be served from data centers near the user regardless of the region of the database. - - - -## See Accelerate in action - -We built a small sample application, [Accelerate Speed Test](https://accelerate-speed-test.prisma.io/). The app compares the performance of cached and uncached queries side by side. The app is [open source](https://github.com/prisma/accelerate-speed-test) and you can clone it to try it yourself. - -![Screenshot of the Accelerate Speed Test app showing cached query performance](/img/accelerate/accelerate.png) diff --git a/content/300-accelerate/200-getting-started.mdx b/content/300-accelerate/200-getting-started.mdx index c6664019a7..47502f8d22 100644 --- a/content/300-accelerate/200-getting-started.mdx +++ b/content/300-accelerate/200-getting-started.mdx @@ -1,7 +1,8 @@ --- -title: 'Getting started' +title: 'Getting started with Prisma Accelerate' metaTitle: 'Getting started with Prisma Accelerate' metaDescription: 'Learn how to get up and running with Prisma Accelerate.' +sidebar_label: 'Getting started' tocDepth: 3 toc: true --- @@ -11,18 +12,18 @@ toc: true To get started with Accelerate, you will need the following: - A [Prisma Data Platform account](https://console.prisma.io) -- A project that uses [Prisma Client](/orm/prisma-client) `4.16.1` or higher. If your project is using interactive transactions, you need to use `5.1.1` or higher. (We always recommend using the latest version of Prisma) +- A project that uses [Prisma Client](/orm/prisma-client) `4.16.1` or higher. If your project is using interactive transactions, you need to use `5.1.1` or higher. (We always recommend using the latest version of Prisma.) - A hosted PostgreSQL, MySQL/MariaDB, PlanetScale, CockroachDB, or MongoDB database ## 1. Enable Accelerate Navigate to your Prisma Data Platform project, choose an environment, and enable Accelerate by providing your database connection string and selecting the region nearest your database. - +:::note -If you require IP allowlisting or firewall configurations with trusted IP addresses, enable Static IP for enhanced security +If you require IP allowlisting or firewall configurations with trusted IP addresses, enable Static IP for enhanced security. Learn more on [how to enable static IP for Accelerate in the Platform Console](/accelerate/static-ip). - +::: ## 2. Add Accelerate to your application diff --git a/content/300-accelerate/250-connection-pooling.mdx b/content/300-accelerate/250-connection-pooling.mdx index c3f9ad8406..2dc1dace7b 100644 --- a/content/300-accelerate/250-connection-pooling.mdx +++ b/content/300-accelerate/250-connection-pooling.mdx @@ -1,54 +1,53 @@ --- title: 'Connection Pooling' -metaTitle: 'Accelerate: Connection Pooling' +metaTitle: 'Prisma Accelerate: Connection Pooling' metaDescription: "Learn about everything you need to know to use Accelerate's connection pooling." --- -A [connection pool](https://en.wikipedia.org/wiki/Connection_pool#:~:text=In%20software%20engineering%2C%20a%20connection,executing%20commands%20on%20a%20database.) is a storage of database connections that can be reused for future requests to the database. When a new connection is requested, it is retrieved from the pool if one is available. Once the connection is no longer needed, it is returned to the pool for reuse. +:::info -[Connection pooling](https://www.prisma.io/dataguide/database-tools/connection-pooling) is important as it allows you to reuse existing connections instead of creating new ones, which can be an expensive operation. +To learn more about connection pooling generally, be sure to check out [Prisma's Data Guide](https://www.prisma.io/dataguide/database-tools/connection-pooling) for a comprehensive overview on what connection pooling is, what it seeks to address, and how it works. -The efficient management of database connections allows the database to process more queries without exhausting the available database connections, making your application more scalable. +::: -Accelerate provides built-in connection pooling by default. By simply using Accelerate, you get the benefits of connection pooling without having to configure anything. However, you can also configure the connection pool to suit your needs. +Accelerate provides built-in connection pooling by default. By using Accelerate, 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. -For more information about connection pooling in Prisma, see the documentation [here](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool). +:::note - - -### Default connection pool size - -By default, Accelerate calculates a default connection pool size using the formula `num_physical_cpus * 2 + 1`. +This document focuses on the connection pooling features of Prisma Accelerate. 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). - +::: -For example, a machine with 2 physical CPUs will have a default connection pool size of `2 * 2 + 1` or `5`. +### Connection Pooling in Accelerate - +By default, Accelerate has a connection limit of `10`. This means that Prisma Accelerate will open at most 10 database connections to your database per Prisma Schema used in Accelerate. For the Starter plan, this is also the maximum connection limit. -This means that Accelerate will create a maximum of 5 connections to the database. If more than 5 connections are requested, Accelerate will queue the requests until a connection is available. +In most cases, this connection limit is sufficient. However, in high traffic or heavy compute environments, you may need to [increase this value](#configuring-the-connection-pool-size). If your project is on the [Pro plan](https://prisma.io/pricing), the maximum connection limit is `100`. For [Business plan](https://prisma.io/pricing) projects the maximum is `1000`. ### Configuring the connection pool size -The connection pool size can be configured via the _database connection string_ in your Platform project (_not_ the Accelerate connection string in your Prisma schema) via the `connection_limit` parameter. For example, set a connection pool size of `10` like this: `postgresql://USER:PASSWORD@HOST:PORT/DATABASE?connection_limit=10`. +When not using Prisma Accelerate, you can configure the connection pool of Prisma ORM [via the connection string](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#setting-the-connection-pool-size). When using Prisma Accelerate *this feature is not available*. Instead, you can configure the connection pool size in your Platform project via the `Connection limit` setting [on Accelerate setup](/accelerate/getting-started). -If nothing is configured, a default value will be used. +#### Autoscaling -To change the size of the connection pool: -1. Open the [Console](https://console.prisma.io/). -1. Select the _project_ in which you're using Accelerate. You might need to select a different _workspace_ if you can't see your project. -1. Select the _environment_ where you want to configure Accelerate's connection pool size. -1. Update the connection string by appending the `connection_limit` argument. +Autoscaling allows Accelerate to dynamically allocate resources based on your application's traffic. As consistent usage approaches the current connection limit, Accelerate will begin allocating new resources to handle the increased load. If traffic continues to rise, Accelerate will scale up further. Conversely, when traffic decreases, Accelerate will scale down accordingly. -![Update database connection string in Accelerate](/img/accelerate/accelerate-update-database-connection-string.png) +Autoscaling is enabled when the Accelerate connection limit is set above the default value. This feature is not available on the Starter plan. +The maximum value of your Accelerate connection limit is based on your [Prisma Data Platform plan](https://prisma.io/pricing). +| Plan | Maximum Connection Limit | +|------------|--------------------------------------| +| Starter | 10 | +| Pro | 100 | +| Business | 1000 | +| Enterprise | [Contact Us](mailto:sales@prisma.io) | ### Configuring the connection pool timeout -The connection pool timeout is the duration, measured in seconds, during which the query engine must process a specific query; failing to do so within this time frame results in an exception being thrown, and the system proceeds to the next query in the queue. +The connection pool timeout is the maximum number of seconds that a query will block while waiting for a connection from Accelerate'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. @@ -63,3 +62,49 @@ postgresql://user:password@localhost:5432/db?connection_limit=10&pool_timeout=20 The default value for `pool_timeout` is `10` seconds.
+ +## Configuring query limits + +You can configure the minimum and maximum query response size, query duration, and transaction limits when using Prisma Accelerate from the **Settings** tab in your Accelerate-enabled project environment. + +### Query timeout limit + +Accelerate has a default global timeout of `10s` for each query, configurable using the slider labeled **Query duration**, based on your subscription plan: + +| Plan | Starter | Pro | Business | +|----------|---------------|--------------|---------------| +| Query timeout | Up to 10 seconds | Up to 20 seconds | Up to 60 seconds | + +See the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout) and our [pricing page](https://www.prisma.io/pricing#accelerate) for more information. + +:::warning +While you can increase the query timeout, it’s recommended to inspect and optimize your database queries if they take longer than 10 seconds. This helps reduce stress on your underlying database, as long-running queries often indicate a need for optimization. Learn more in the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout). +::: + +### Interactive transactions query timeout limit + +Accelerate has a default global timeout of `15s` for each [interactive transaction](/orm/prisma-client/queries/transactions#interactive-transactions), configurable using the slider labeled **Transaction duration**, based on your subscription plan: + +| Plan | Starter | Pro | Business | +|----------------------------|---------------|--------------|---------------| +| Interactive transaction limit | Up to 15 seconds | Up to 30 seconds | Up to 90 seconds | + +See the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout) and our [pricing page](https://www.prisma.io/pricing#accelerate) for more information. + +:::warning +While you can increase the interactive transaction timeout limit, it’s recommended to inspect and optimize your database transactions if they take longer than 15 seconds. Long-running transactions can negatively impact performance and often signal the need for optimization. Learn more in the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout) and review the [warning in the Interactive Transactions section](/orm/prisma-client/queries/transactions#interactive-transactions-1) in our documentation. +::: + +### Response size limit + +Accelerate has a default global response size limit of `5MB`, configurable using the slider labeled **Response size**, based on your subscription plan: + +| Plan | Starter | Pro | Business | +|----------|---------------|--------------|---------------| +| Query size | Up to 5MB | Up to 10MB | Up to 20MB | + +See the [troubleshooting guide](/accelerate/troubleshoot#p6009-responsesizelimitexceeded) and our [pricing page](https://www.prisma.io/pricing#accelerate) for more information. + +:::warning +While you can increase the query response size, it’s recommended to limit data retrieval to what you actually need. This improves database performance, reduces stress on your database, and makes your frontend applications more responsive. Queries exceeding 5 MB in size often indicate a need for optimization. Learn more in the [troubleshooting guide](/accelerate/troubleshoot#p6009-responsesizelimitexceeded). +::: \ No newline at end of file diff --git a/content/300-accelerate/350-static-ip.mdx b/content/300-accelerate/350-static-ip.mdx new file mode 100644 index 0000000000..8744d26ff8 --- /dev/null +++ b/content/300-accelerate/350-static-ip.mdx @@ -0,0 +1,56 @@ +--- +title: "Static IP" +metaTitle: "Enable Static IP for Prisma Accelerate" +metaDescription: "Learn enabling Static IP for Prisma Accelerate." +--- + +You can enable static IP for Accelerate when your security setup requires IP allowlisting or if you're implementing firewalls that only permit access from trusted IPs, ensuring controlled and secure database connections. + +![Result of enabling static IP Accelerate with a database using IP allowlisting](/img/accelerate/result-of-adding-static-ip-to-accelerate.png) + +:::info + +To enable static IP support for Accelerate within an existing or a new project environment, your workspace will need to be on our Pro or Business plans. Take a look at the [pricing page](https://www.prisma.io/pricing#accelerate) for more information. + +::: + +## Enable static IP in Accelerate + +You can opt-in to use static IP for Accelerate in the [Platform Console](https://pris.ly/pdp) in two ways: + +### 1. When enabling Accelerate for your project environment: + +1. Specify your database connection string and connection pool region. +2. Enable static IP by toggling the **Static IP** switch in the **Network restrictions** section. +3. Click on the **Enable Accelerate** button. + +### 2. For projects already using Accelerate: + +1. Navigate to the Accelerate **Settings** tab in the project environment. +2. Enable static IP by toggling the **Static IP** switch in the **Network restrictions** section. + +Enabling static IP for Accelerate will provide you with a list of static IPv4 and IPv6 addresses. + +Example IPv4 address range: +``` +52.86.207.46/32 +100.29.164.162/32 +54.211.230.107/32 +18.235.169.169/32 +54.209.237.70/32 +44.221.111.173/32 +``` + +Example IPv6 address range: +``` +2600:1f18:51ce:b00::/64 +2600:1f18:5acb:9a00::/56 +``` + +Once you have these addresses, configure your database firewall to allow incoming connections only from these IPs and any other trusted IPs that need access to your database. + +:::note + +Since you cannot enable static IP for an existing Accelerate-enabled environment, we recommend opting for static IP when enabling Accelerate in a new environment. Use the same database URL as your existing Accelerate environment to instantly access static IP support for Accelerate. + +::: \ No newline at end of file diff --git a/content/300-accelerate/500-limitations.mdx b/content/300-accelerate/500-limitations.mdx index 55d5da160e..e9694b6fae 100644 --- a/content/300-accelerate/500-limitations.mdx +++ b/content/300-accelerate/500-limitations.mdx @@ -12,25 +12,9 @@ Below are descriptions of known limitations when using Accelerate. If you encoun -## Query timeout limit - -Accelerate has a global timeout of `10s` for each query. Reach out to [support@prisma.io](mailto:support@prisma.io) with your use case if your application requires a greater timeout value. - -> Also see the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout) for more information. - -## Interactive transactions query timeout limit - -Accelerate has a global timeout of `15s` for each [interactive transaction](/orm/prisma-client/queries/transactions#interactive-transactions). Reach out to [support@prisma.io](mailto:support@prisma.io) with your use case if your application requires a greater timeout value. - -## Response size limit - -Accelerate has a global response size limit of `5MB`. Reach out to [support@prisma.io](mailto:support@prisma.io) with your use case if your application requires a larger response size. - -> Also see the [troubleshooting guide](/accelerate/troubleshoot#p6009-responsesizelimitexceeded) for more information. - ## Cannot cache raw queries -At the moment, it is not possible to cache the responses of [raw queries](/orm/prisma-client/queries/raw-database-access/raw-queries). +At the moment, it is not possible to cache the responses of [raw queries](/orm/prisma-client/using-raw-sql/raw-queries). ## Not compatible with the fluent API diff --git a/content/300-accelerate/580-local-development.mdx b/content/300-accelerate/580-local-development.mdx index 053914b1cd..be63eee6ea 100644 --- a/content/300-accelerate/580-local-development.mdx +++ b/content/300-accelerate/580-local-development.mdx @@ -20,7 +20,7 @@ This guide will explain how to use Prisma Accelerate client extension in a devel
-![](/img/accelerate/accelerate-in-dev.png) +![Using Prisma Accelerate client extension in development](/img/accelerate/accelerate-in-dev.png) Accelerate does not work with a local database. However, in a development environment, you can still use Prisma Client with the Accelerate client extension. This setup will not provide Accelerate's connection pooling and caching features. @@ -51,7 +51,7 @@ The following steps outline how to use Prisma ORM and Prisma Accelerate with a l > The extended instance of Prisma Client will use the local database. Hence, Prisma Accelerate will not be used in your development environment to respond to your Prisma Client queries. -![](/img/accelerate/accelerate-in-prod.png) +![Using Prisma Accelerate client extension in production](/img/accelerate/accelerate-in-prod.png) If an Accelerate connection string is used as the `DATABASE_URL` environment variable, Prisma Client will route your queries through Accelerate. diff --git a/content/300-accelerate/600-faq.mdx b/content/300-accelerate/600-faq.mdx index af0ae9fb72..21af7a6551 100644 --- a/content/300-accelerate/600-faq.mdx +++ b/content/300-accelerate/600-faq.mdx @@ -6,19 +6,24 @@ tocDepth: 3 toc: true --- -Below are frequently asked questions about Accelerate. - ## When should I enable static IP for Prisma Accelerate? -A static IP address is an IPv4 or an IPv6 address that is fixed. Unlike dynamic IP addresses, which can change unpredictably, traffic from static IP addresses can be easily identified. Enable static IP for Accelerate when your security setup requires IP allowlisting or if you're implementing firewalls that only permit access from trusted IPs, ensuring controlled and secure database connections. +Enable static IP for Accelerate when your security setup requires IP allowlisting or if you're implementing firewalls that only permit access from trusted IPs, ensuring controlled and secure database connections. + +![Result of enabling static IP Accelerate with a database using IP allowlisting](/img/accelerate/result-of-adding-static-ip-to-accelerate.png) + +Learn more on [how to enable static IP for Accelerate in the Platform Console](/accelerate/static-ip). -![What is a static IP](./images/static-ip.png) +:::info +**What is a static IP?** -For databases using IP allowlisting, enable static IP for Accelerate in your specified project environment, and add the obtained IP address to your database's allowlist to ensure authorized access from Accelerate. +A static IP address is an IPv4 or an IPv6 address that is fixed. Unlike dynamic IP addresses, which can change unpredictably, traffic from static IP addresses can be easily identified. -![](./images/result-of-adding-static-ip-to-accelerate.png) +![What is a static IP](/img/accelerate/static-ip.png) +::: -> ℹ️ To enable static IP support for Accelerate within your existing or new project environment, your workspace will need to be on our **Pro** or **Business** plans. Take a look at the [pricing page](https://www.prisma.io/pricing) for more information. + +> ℹ️ To enable static IP support for Accelerate within your existing or new project environment, your workspace will need to be on our **Pro** or **Business** plans. Take a look at the [pricing page](https://www.prisma.io/pricing#accelerate) for more information. ## Why do I sometimes see unexpected cache behavior? @@ -125,3 +130,45 @@ In the rare event of a service disruption, falling back to a direct connection w If there is a service disruption, it's recommended to verify on the [status page](https://pris.ly/data-platform-status). You can reach out to one of Prisma's [support channels](/platform/support) for assistance. > **Note:** Additionally, it's worth noting that some edge function runtime environments may not support direct connections with Prisma ORM. For further details, refer to our [Edge functions documentation](/orm/prisma-client/deployment/edge/overview). + +## Are each of the queries within an interactive transaction counted separately for billing? + +Yes, [interactive transactions](/orm/prisma-client/queries/transactions#interactive-transactions) are billed based on the individual operations within the transaction. There is no charge for the start, commit, or rollback of the transaction itself. For example, in the following query, there are two billable queries: + +```ts +await prisma.$transaction(async (tx) => { + await tx.user.deleteMany({ where: { name: 'John Doe' } }); + await tx.user.createMany({ data }); +}); +``` + +However, when using the [`$transaction` API for sequential client operations](/orm/prisma-client/queries/transactions#sequential-prisma-client-operations), regardless of the number of queries within the array, it counts as only one billable query. For example: + +```ts +await prisma.$transaction([ + prisma.user.deleteMany({ where: { name: 'John Doe' } }), + prisma.user.createMany({ data }), +]); +``` + +If you don't need [interactive transactions](/orm/prisma-client/queries/transactions#interactive-transactions), you can save costs and improve performance by using [sequential operations transactions](/orm/prisma-client/queries/transactions#sequential-prisma-client-operations). Sequential operations transactions perform better on Accelerate because they execute in one round-trip to the database, while interactive transactions require separate round-trips for start, commit, and each individual operation on the transaction. + +## Do the static IP ranges for Accelerate and Pulse differ? + +No, if you have static IP enabled for both Accelerate and Pulse using the same database URL, the generated static IP ranges will be the same for both products. + +## Can I increase my Accelerate query duration and response size limits? + +Yes, you can increase your Accelerate limits based on your subscription plan. Here are the configurable limits: + +| Limit | Starter | Pro Plan | Business Plan | +|--------------------------------|-------------------|-------------------|-------------------| +| **Query timeout** | Up to 10 seconds | Up to 20 seconds | Up to 60 seconds | +| **Interactive transactions timeout** | Up to 15 seconds | Up to 30 seconds | Up to 90 seconds | +| **Response size** | Up to 5 MB | Up to 10 MB | Up to 20 MB | + +Check the [pricing page](https://www.prisma.io/pricing#accelerate) for more details on the available plans and their corresponding limits. + +:::warning +While you can increase these limits based on your subscription plan, it's *still* recommended to optimize your database operations. [Learn more in our troubleshooting guide.](/accelerate/troubleshoot) +::: \ No newline at end of file diff --git a/content/300-accelerate/650-troubleshoot.mdx b/content/300-accelerate/650-troubleshoot.mdx index da300940f3..a22ef503d6 100644 --- a/content/300-accelerate/650-troubleshoot.mdx +++ b/content/300-accelerate/650-troubleshoot.mdx @@ -14,7 +14,7 @@ When working with Prisma Accelerate, you may encounter errors often highlighted ## [`P6009`](/orm/reference/error-reference#p6009-responsesizelimitexceeded) (`ResponseSizeLimitExceeded`) -This error is triggered when the response size from a database query exceeds the 5MB limit. We've implemented this restriction to safeguard your application performance, as retrieving data over 5MB can significantly slow down your application due to multiple network layers. Typically, transmitting more than 5MB of data is common when conducting ETL (Extract, Transform, Load) operations. However, for other scenarios such as transactional queries, real-time data fetching for user interfaces, bulk data updates, or aggregating large datasets for analytics outside of ETL contexts, it should generally be avoided. These use cases, while essential, can often be optimized to work within the 5MB limit, ensuring smoother performance and a better user experience. +This error is triggered when the response size from a database query exceeds [the configured query response size limit](/accelerate/connection-pooling#response-size-limit). We've implemented this restriction to safeguard your application performance, as retrieving data over 5MB can significantly slow down your application due to multiple network layers. Typically, transmitting more than 5MB of data is common when conducting ETL (Extract, Transform, Load) operations. However, for other scenarios such as transactional queries, real-time data fetching for user interfaces, bulk data updates, or aggregating large datasets for analytics outside of ETL contexts, it should generally be avoided. These use cases, while essential, can often be optimized to work within [the configured query response size limit](/accelerate/connection-pooling#response-size-limit), ensuring smoother performance and a better user experience. ### Possible causes for [`P6009`](/orm/reference/error-reference#p6009-responsesizelimitexceeded) @@ -22,25 +22,27 @@ This error is triggered when the response size from a database query exceeds the This error may arise if images or files stored within your table are being fetched, resulting in a large response size. Storing assets directly in the database is generally discouraged because it significantly impacts database performance and scalability. In addition to performance, it makes database backups slow and significantly increases the cost of storing routine backups. -**Suggested solution:** Store the image/file in a BLOB store like [Cloudflare R2](https://developers.cloudflare.com/r2/), [AWS S3](https://aws.amazon.com/pm/serv-s3/), [Cloudinary](https://cloudinary.com/), etc. These services would allow you to store the assets optimally and return a URL through which you should be able to access the asset. You can store this URL in your table instead of storing the asset directly in database. This would substantially reduce the size of your response. +**Suggested solution:** Configure the [query response size limit](/accelerate/connection-pooling#response-size-limit) to be larger. If the limit is still exceeded, consider storing the image or file in a BLOB store like [Cloudflare R2](https://developers.cloudflare.com/r2/), [AWS S3](https://aws.amazon.com/pm/serv-s3/), or [Cloudinary](https://cloudinary.com/). These services allow you to store assets optimally and return a URL for access. Instead of storing the asset directly in the database, store the URL, which will substantially reduce the response size. + #### Over-fetching of data -In certain cases, a large number of records or fields are unintentionally fetched, which results in exceeding the 5MB limit. This could happen when the [`where`](/orm/reference/prisma-client-reference#where) clause in the query is incorrect or entirely missing. +In certain cases, a large number of records or fields are unintentionally fetched, which results in exceeding [the configured query response size limit](/accelerate/connection-pooling#response-size-limit). This could happen when the [`where`](/orm/reference/prisma-client-reference#where) clause in the query is incorrect or entirely missing. -**Suggested solution:** Double-check if the `where` clause is filtering the data as you expect. Consider using [pagination](/orm/prisma-client/queries/pagination) to prevent a large number of records from being fetched. Additionally, use the [`select`](/orm/reference/prisma-client-reference#select) clause to return only the fields that are being consumed to further reduce the response size. +**Suggested solution:** Configure the [query response size limit](/accelerate/connection-pooling#response-size-limit) to be larger. If the limit is still exceeded, double-check that the `where` clause is filtering data as expected. To prevent fetching too many records, consider using [pagination](/orm/prisma-client/queries/pagination). Additionally, use the [`select`](/orm/reference/prisma-client-reference#select) clause to return only the necessary fields, reducing the response size. #### Fetching a large volume of data In many data processing workflows, especially those involving ETL (Extract-Transform-Load) processes or scheduled CRON jobs, there's a need to extract large amounts of data from data sources (like databases, APIs, or file systems) for analysis, reporting, or further processing. If you are running an ETL/CRON workload that fetches a huge chunk of data for analytical processing then you might run into this limit. -**Suggested solution:** Consider splitting your query to fetch data in batches to prevent the 5MB limit from being reached. By splitting your query to retrieve data in batches, you ensure that each operation fetches only a portion of the total data volume, thereby not exceeding the size limit for a single fetch operation. +**Suggested solution:** Configure the [query response size limit](/accelerate/connection-pooling#response-size-limit) to be larger. If the limit is exceeded, consider splitting your query into batches. This approach ensures that each batch fetches only a portion of the data, preventing you from exceeding the size limit for a single operation. + ## [`P6004`](/orm/reference/error-reference#p6004-querytimeout) (`QueryTimeout`) -This error occurs when a database query fails to return a response within 10 seconds. The 10-second limit includes the duration of waiting for a connection from the pool, network latency to the database, and the execution time of the query itself. We enforce this limit to prevent unintentional long-running queries that can overload system resources. +This error occurs when a database query fails to return a response within [the configured query timeout limit](/accelerate/connection-pooling#query-timeout-limit). The query timeout limit includes the duration of waiting for a connection from the pool, network latency to the database, and the execution time of the query itself. We enforce this limit to prevent unintentional long-running queries that can overload system resources. -> The time for Accelerate's cross-region networking is excluded from the 10-second limit. +> The time for Accelerate's cross-region networking is excluded from [the configured query timeout limit](/accelerate/connection-pooling#query-timeout-limit) limit. ### Possible causes for [`P6004`](/orm/reference/error-reference#p6004-querytimeout) @@ -48,20 +50,17 @@ This error could be caused by numerous reasons. Some of the prominent ones are: #### High traffic and insufficient connections -If the application is receiving very high traffic and there are not a sufficient number of connections available to the database, then the queries would need to wait for a connection to become available. This situation can lead to queries waiting longer than 10 seconds for a connection, ultimately triggering a timeout error if they do not get serviced within this duration. +If the application is receiving very high traffic and there are not a sufficient number of connections available to the database, then the queries would need to wait for a connection to become available. This situation can lead to queries waiting longer than [the configured query timeout limit](/accelerate/connection-pooling#query-timeout-limit) for a connection, ultimately triggering a timeout error if they do not get serviced within this duration. -**Suggested solution**: Review and possibly increase the `connection_limit` specified in the connection string parameter when setting up Accelerate in a platform environment ([reference](/accelerate/connection-pooling#configuring-the-connection-pool-size)). -This limit should align with your database's maximum number of connections. +**Suggested solution**: Review and possibly increase the `connection_limit` specified in the connection string parameter when setting up Accelerate in a platform environment ([reference](/accelerate/connection-pooling#configuring-the-connection-pool-size)). This limit should align with your database's maximum number of connections. -By default, the connection limit is set to 10 unless a -different `connection_limit` is specified in your database connection string. +By default, the connection limit is set to 10 unless a different `connection_limit` is specified in your database connection string. #### Long-running queries -Queries may be slow to respond, hitting the 10-second timeout even when connections are available. This could happen if a very large amount of data is being fetched in a single query or if appropriate indexes are missing from the table. +Queries may be slow to respond, hitting [the configured query timeout limit](/accelerate/connection-pooling#query-timeout-limit) even when connections are available. This could happen if a very large amount of data is being fetched in a single query or if appropriate indexes are missing from the table. -**Suggested solution**: Identify the slow-running queries and fetch only the required data. If you only need to use specific fields from the table, then you can use the select clause in your queries to prevent unnecessary data from being fetched. Additionally, you could consider adding appropriate indexes based on the query to ensure that data is fetched efficiently. -You can also consider isolating long running queries into separate environments, so that these long running queries would not affect the transactional queries. +**Suggested solution**: Configure the [query timeout limit](/accelerate/connection-pooling#query-timeout-limit) to be larger. If the limit is exceeded, identify the slow-running queries and fetch only the necessary data. Use the `select` clause to retrieve specific fields and avoid fetching unnecessary data. Additionally, consider adding appropriate indexes to improve query efficiency. You might also isolate long-running queries into separate environments to prevent them from affecting transactional queries. #### Database resource contention @@ -69,7 +68,7 @@ A common yet challenging issue is when other services operating on the same data Users often rely on CPU and memory usage metrics to gauge database load, which can be misleading. While these are important indicators, they might not fully represent the database's operational state. Direct metrics like the number of reads, writes, and wait times offer a clearer view of the database's performance and should be monitored closely. A noticeable degradation in these metrics, especially in the absence of changes to the queries or data model, suggests that external pressures are affecting database performance. -**Suggestion solution**: If normally quick queries are intermittently slow or timing out without any modifications to them, it's probable that competing queries are exerting pressure on the same database tables. To diagnose this, adopt monitoring tools or leverage your database's inherent capabilities to observe reads, writes, and wait times. Such monitoring will unveil activity patterns or spikes that align with the observed performance dips. +**Suggested solution**: If normally quick queries are intermittently slow or timing out without any modifications to them, it's probable that competing queries are exerting pressure on the same database tables. To diagnose this, adopt monitoring tools or leverage your database's inherent capabilities to observe reads, writes, and wait times. Such monitoring will unveil activity patterns or spikes that align with the observed performance dips. Moreover, it's crucial to periodically scrutinize and refine essential queries and verify that tables are properly indexed. This proactive approach minimizes the vulnerability of these queries to slowdowns caused by competing workloads. @@ -86,7 +85,7 @@ Additionally, direct connections could have a significant impact on your databas If your application's runtime environment supports Prisma ORM natively and you're considering this strategy to circumvent P6009 and P6004 errors, you might create two `PrismaClient` instances: 1. An instance using the Accelerate connection string (prefixed with `prisma://`) for general operations. -2. Another instance with the direct database connection string (e.g., prefixed with `postgres://`, `mysql://`, etc.) for specific operations anticipated to exceed 10 seconds in execution time or to result in responses larger than 5MB. +2. Another instance with the direct database connection string (e.g., prefixed with `postgres://`, `mysql://`, etc.) for specific operations anticipated to exceed [the configured query limit timeout](/accelerate/connection-pooling#query-timeout-limit) or to result in responses larger than [the configured query response size limit](/accelerate/connection-pooling#response-size-limit). ```jsx export const prisma = new PrismaClient({ @@ -110,9 +109,9 @@ This error indicates that Prisma Accelerate cannot establish a connection to you #### Database Not Publicly accessible -Prisma Accelerate currently requires the database to be publicly accessible. If your database is behind a VPC, or access is restricted to specific IP addresses, this error may occur. +If your database is within a VPC or access is limited to specific IP addresses, you might encounter this error if static IP is not enabled for Accelerate or if the static IPs are not permitted in your database firewall. -**Suggested solution:** Ensure your database is publicly accessible, if not, allow public access. Please note this is only an interim requirement, Static IPs are coming soon and will alleviate the need for complete public access if that’s not desirable. +**Suggested solution:** [Enable static IP for Accelerate](/accelerate/static-ip) and configure your database firewall to allow access from the provided static IP addresses. #### Unreachable Database Host/Port diff --git a/content/300-accelerate/800-examples.mdx b/content/300-accelerate/800-examples.mdx new file mode 100644 index 0000000000..aa52becc5e --- /dev/null +++ b/content/300-accelerate/800-examples.mdx @@ -0,0 +1,20 @@ +--- +title: 'Prisma Accelerate examples' +metaTitle: 'Prisma Accelerate: Examples' +metaDescription: 'Check out ready-to-run examples for Prisma Accelerate.' +sidebar_label: 'Examples' +tocDepth: 3 +--- + +Here is a list of ready-to-run example projects that demonstrate how to use Prisma Accelerate: + +| 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 | + + diff --git a/content/300-accelerate/900-compare.mdx b/content/300-accelerate/900-compare.mdx new file mode 100644 index 0000000000..d826e19ed9 --- /dev/null +++ b/content/300-accelerate/900-compare.mdx @@ -0,0 +1,104 @@ +--- +title: 'Compare Accelerate' +metaTitle: 'Comparing Prisma Accelerate to other connection pooling options' +metaDescription: 'Learn how Prisma Accelerate compares to other connection poolers like pgbouncer.' +hide_table_of_contents: true +--- + + + +Prisma Accelerate supports products that serve a global audience, with a global caching system and connection pool that spans multiple regions, providing consistent access to data with low latency no matter where your user (or your database) is located in the world. + +The managed connection pool is designed to support serverless infrastructure, capable of handling high volumes of connections and adapting to traffic spikes with ease. + +Explore how Prisma Accelerate compares to other global cache and connection pool solutions on the market, and discover what sets it apart. + + + +## What makes Accelerate unique? + +Prisma Accelerate is chosen and loved by many for a number of key reasons which make Accelerate unique: + +- [**Query-Level policies**](/accelerate/compare#accelerate-global-cache): Accelerate is the only solution that offers query-level cache policies, allowing you to control the cache strategy for each query specifically. It is common to have some values that need to be cached for a long time, others that need caching for a short time, and some that should not be cached at all. With Accelerate you can do this, and even set different cache strategies per query. +- [**Global by default**](/accelerate/compare#accelerate-global-cache): Accelerate is globally distributed by default. You never need to worry about where a user is located with respect to your database location. +- [**Fully managed**](/accelerate/compare#management): You don't need to manage a server or worry about uptime. Accelerate is fully managed for you. +- [**Auto-scaling**](/accelerate/compare#performance): Accelerate automatically adjusts resources to match workload demands, providing fast and consistent performance during traffic spikes. + +## Accelerate global cache + +Prisma Accelerate offers a powerful global cache, so you can serve data to your users at the edge — the closest point to where the users are located — no matter where your database is hosted. This not only speeds up the experience for users, but also reduces read load on your database as well by avoiding roundtrips. + +| | Accelerate | Hyperdrive | Planetscale Boost | +| --- | --- | --- | --- | +| **Fully Managed** | ✅ | ✅ | ✅ | +| **Globally distributed edge infra** | ✅ | ✅ | ✅ | +| **Control cache policy from code** | ✅ | ❌ | ❌ | +| **Query-level cache policies** | ✅ | ❌ | ❌ | +| **Authenticate with API key** | ✅ | ❌ | ❌ | +| **Postgres compatible** | ✅ | ✅ | ❌ | +| **MySQL compatible** | ✅ | ❌ | ✅ | +| **MongoDB compatible** | ✅ | ❌ | ❌ | +| **Automatic cache updates** | ❌ | ❌ | ✅ | + +**Why are these important?** + +- Since Accelerate extends the Prisma client, you can control caching policies directly from your codebase with just an extra line of code. Integration is seamless. Here is an example using [the stale-while-revalidating caching strategy](/accelerate/caching#stale-while-revalidate-swr): + + ```jsx + await prisma.user.findMany({ + cacheStrategy: { + swr: 60, + }, + }); + ``` + +- Query level cache policies are critical for serious applications, so that you can control which queries are cached, and the characteristics of the policy. You may want certain data in your app to be cached for several days, other data to be cached for a just a few minutes, and other data to be not cached at all. This is only possible with Prisma Accelerate. +- Authenticating with an API key can be a helpful security measure, allowing you to decouple database credentials from application secrets. Easily rotate API keys as often as you like, without needing any credential changes in your database +- Automatic cache updates means that the cache is automatically updated when a change in the database occurs. With Accelerate, you are in control of how the cache is invalidated, using [various caching strategies](/accelerate/caching). + + +## Accelerate connection pool + +Prisma Accelerate includes a globally hosted connection pooler, which allows you to handle peak loads without any problem. Using a connection pool is important especially for serverless infrastructure, which by nature is not able to control connection volume to the database on its own. Prisma Accelerate offers a fully managed, globally colocated option, which auto scales to support any workload. + +### Management + +| | Accelerate | pgbouncer | pgcat | Digital Ocean (pgbouncer) | Neon (pgbouncer) | Supavisor | Hyperdrive | +| --- | --- | --- | --- | --- | --- | --- | --- | +| **Fully managed** | ✅ | ❌ | ❌ | 🟠 | ✅ | ❌ | ✅ | +| **Globally distributed** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| **Integrated with ORM client** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| **Authenticate with API key** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| **Redundancy** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | + +**Why are these important?** + +- If you decide to manage a connection pooler yourself (eg. using pgbouncer or pgcat) you will also be responsible for managing its uptime. If the server crashes, your application may be down until you recover it. Accelerate, as a fully managed solution will be recovered for you transparently, in the unlikely case of any infrastructure issue. +- The hosted pgbouncer option on Digital Ocean is semi-managed, you will need to set it up in your Digital Ocean account, and ensure it is running smoothly at all times. +- Authenticating with an API key can be a helpful security measure, allowing you to decouple database credentials from application secrets. Easily rotate API keys as often as you like, without needing any credential changes in your database +- Redundancy is helpful in the unlikely scenario that your connection pool service goes down. With Accelerate, it is automatically and seamlessly handed over to another server and recovered without any interruption. + +### Performance + +| | Accelerate | pgbouncer | pgcat | Digital Ocean (pgbouncer) | Neon (pgbouncer) | Supavisor | Hyperdrive | +| --- | --- | --- | --- | --- | --- | --- | --- | +| **Auto scaling** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| **Globally distributed** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| **Optimized queries over HTTP** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| **Isolated compute** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | + +**Why are these important?** + +- Accelerate will automatically scale up and down to suit your application workload, meaning you'll never run out of compute resource. Additionally, this provides important redundancy to protect against any single compute instance failing — in the unlikely event of an instance going down, Accelerate will automatically spawn a new instance. +- Cross-region TCP handshakes between the application server and PgBouncer or the database are costly and time-consuming. If connections are reused only at the PgBouncer layer, the TCP handshake and connection setup still consume unnecessary time on every single request, which undermines the efficiency of connection reuse. Prisma Accelerate improves this by leveraging HTTP, which is more efficient for connection management. It reduces the overhead associated with TCP handshakes, resulting in faster, more responsive interactions between your application and the database. +- Never worry about 'noisy neighbors' with isolated compute resources. Other customers never impact on your own performance. + +### Database Support + +| | Accelerate | pgbouncer | pgcat | Digital Ocean (pgbouncer) | Neon (pgbouncer) | Supavisor | Hyperdrive | +| --- | --- | --- | --- | --- | --- | --- | --- | +| **PostgreSQL** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **MySQL** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| **Planetscale** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| **CockroachDB** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| **MongoDB** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | diff --git a/content/300-accelerate/index.mdx b/content/300-accelerate/index.mdx index 8dfbc78e41..f1f698042d 100644 --- a/content/300-accelerate/index.mdx +++ b/content/300-accelerate/index.mdx @@ -4,8 +4,7 @@ metaTitle: 'Prisma Accelerate' metaDescription: 'Prisma Accelerate is a global database cache with built-in connection pooling that helps improve database performance in Serverless and Edge applications.' sidebar_position: 0 hide_table_of_contents: false -pagination_next: 'accelerate/what-is-accelerate' - +pagination_next: 'accelerate/getting-started' --- import { @@ -27,7 +26,15 @@ import { Prisma Accelerate -[Prisma Accelerate](https://www.prisma.io/data-platform/accelerate) is a managed connection pooler with global caching that helps speed up database queries. With Accelerate, you can easily configure connection pooling and choose the right cache strategy for your app. +[Prisma Accelerate](https://www.prisma.io/data-platform/accelerate) is a fully managed global connection pool and caching layer for your existing database, enabling query-level cache policies directly from the Prisma ORM. + +With 15+ global regions, the connection pool scales your app for a global audience, particularly for serverless deployments that risk connection timeouts during peak times. + +Accelerate’s global cache, hosted in 300+ locations, ensures a fast experience for users, regardless of your database’s location. + +You can configure query-level caching strategies directly in your code with Prisma ORM, making setup and tuning easy. + +Together, the connection pool and cache allow you to scale effortlessly and handle traffic spikes without infrastructure concerns. + + + +```ts +import { withPulse } from '@prisma/extension-pulse/node'; +``` + + + + + +```ts +import { withPulse } from '@prisma/extension-pulse/workerd'; +``` + + + +
+ +:::warning + +Using the correct [runtime-specific import](#runtime-specific-imports) prevents the following error: ``` Cannot find module '@prisma/extension-pulse' or its corresponding type declarations. ``` +::: + ### 2.3. Create your first Pulse stream With the Pulse extension applied, you can use Pulse's `.stream()` method on any model defined in your Prisma Schema to stream data change events. diff --git a/content/400-pulse/250-database-setup/100-general-database-instructions.mdx b/content/400-pulse/250-database-setup/100-general-database-instructions.mdx index 032ccbf4fd..2b62b84a10 100644 --- a/content/400-pulse/250-database-setup/100-general-database-instructions.mdx +++ b/content/400-pulse/250-database-setup/100-general-database-instructions.mdx @@ -7,11 +7,11 @@ toc_max_heading_level: 6 toc: true --- - +:::note -Prisma Pulse requires a publicly accessible PostgreSQL (**version 12+**) database with logical replication enabled. To configure specific database providers for Prisma Pulse, visit [here](/pulse/database-setup#provider-specific-instructions). +Prisma Pulse requires a PostgreSQL (**version 12+**) database with logical replication enabled. To configure specific database providers for Prisma Pulse, visit [here](/pulse/database-setup#provider-specific-instructions). - +::: Database replication is the process of creating copies of a database and storing them across various on-premises or cloud destinations. Prisma Pulse uses logical replication to monitor your database for changes. @@ -69,7 +69,7 @@ ALTER TABLE public."User" REPLICA IDENTITY FULL; ## Manage your own publication slot -If you want to enable replication for _specific models_ or use a database provider that restricts superuser access for Prisma Pulse you can configure your own publication slot and use it to enable Pulse. +By default, Pulse monitors all tables for changes in your database. If you want to enable replication for *specific models* or if you use a database provider that restricts superuser access for Prisma Pulse, you can configure your own publication slot. If you want to configure your own publication slot and enable Pulse, you'll need to opt for one of [our paid plans](https://www.prisma.io/pricing#pulse). ### Creating a publication slot @@ -142,7 +142,7 @@ You can learn more about the PostgreSQL's `CREATE PUBLICATION`, supported versio ### Submit your publication slot -You can submit the publication name in the [Console](https://console.prisma.io/), before enabling Prisma Pulse: +You can submit the publication name in the [Console](https://console.prisma.io/login), before enabling Prisma Pulse: 1. To view your [publications](https://www.postgresql.org/docs/current/view-pg-publication-tables.html), execute: @@ -150,9 +150,17 @@ You can submit the publication name in the [Console](https://console.prisma.io/) SELECT * FROM pg_publication_tables; ``` -2. Then you can submit the desired publication name in the Console: +2. Navigate to [Prisma Data Platform](https://pris.ly/pdp) to enable Pulse. - ![](/img/pulse/replication-slot-submission.png) +3. Submit the database connection string and region in the **Database connection** section. + +4. In your project environment configuration for Pulse, enter the publication name in the **Publication name** field. To access this, toggle the **Automatic setup** button in the **Database replication** section (available with a [paid plan](https://www.prisma.io/pricing#pulse)). + +5. After toggling **Automatic setup**, the button will transition to **Advanced setup**, and a textbox labeled **Publication name** will appear. + +6. Copy and paste the publication name from *step 2*. + +7. Click **Enable Pulse**. ### Removing publications diff --git a/content/400-pulse/250-database-setup/300-railway.mdx b/content/400-pulse/250-database-setup/300-railway.mdx index 21e5b9a9ae..d319135c6b 100644 --- a/content/400-pulse/250-database-setup/300-railway.mdx +++ b/content/400-pulse/250-database-setup/300-railway.mdx @@ -36,7 +36,7 @@ The template consists of two [services](https://docs.railway.app/reference/servi ``` > **Note**: > The `DATABASE_URL` can also be found by clicking on the **Postgres** Service and navigating to the **Variables** tab, then clicking the copy icon next to `DATABASE_URL` environment variable value. - > ![](/img/pulse/railway-database-url.png) + > ![Railway template: database URL](/img/pulse/railway-database-url.png) 6. Copy the `DATABASE_URL` connection string and save it for later. Then restart your Railway database for the changes to be reflected: 1. Click on the **Postgres** service that represents your deployed database. 2. Navigate to the **Deployments** tab. @@ -62,10 +62,10 @@ The template consists of three [services](https://docs.railway.app/reference/ser 2. You'll be navigated to a page prompting configuration for both the **restart-db-then-delete-me** and **pulse-starter** service: ![Configure Railway template](/img/pulse/railway-template-configure.png) 1. For the **restart-db-then-delete-me** service, click on the **Configure** button and then save the configuration by clicking on **Save Config**. - 2. On the **pulse-starter** service, locate and click the **Configure** button. Within the **Environment variables** section, you'll find an option to include the `PULSE_API_KEY` environment variable. Keep the `PULSE_API_KEY` field blank for the time being. Once you've set up the database and obtained the database URL from the [Prisma Data Platform](https://console.prisma.io/), you can then add the `PULSE_API_KEY` to the **pulse-starter** service. With the empty field for the Pulse API key, click **Save Config**. + 2. On the **pulse-starter** service, locate and click the **Configure** button. Within the **Environment variables** section, you'll find an option to include the `PULSE_API_KEY` environment variable. Keep the `PULSE_API_KEY` field blank for the time being. Once you've set up the database and obtained the database URL from the [Prisma Data Platform](https://console.prisma.io/login), you can then add the `PULSE_API_KEY` to the **pulse-starter** service. With the empty field for the Pulse API key, click **Save Config**. 3. Click on the **Deploy** button. 3. To set up the database and make it Pulse-ready, complete the steps outlined in the [previous section](#setup-with-template-prisma-pulse-db-only), starting from **step 2.** till **step 8.**, then follow the instructions below. -4. Go to the [Console](https://console.prisma.io/) and select the project in which you want to activate Pulse. If you don't have a project yet, create a new project via the **New project** button. +4. Go to the [Console](https://console.prisma.io/login) and select the project in which you want to activate Pulse. If you don't have a project yet, create a new project via the **New project** button. 5. Navigate to the project's environment in which Pulse should be activated. If you just created a new project, the only available environment is the **Production** environment. 6. Click **Enable Pulse** on the environment's page. 7. Paste the `DATABASE_URL` that you acquired before into the **Database connection string** field. Then, finish the process by clicking **Enable Pulse**. diff --git a/content/400-pulse/250-database-setup/400-neon.mdx b/content/400-pulse/250-database-setup/400-neon.mdx index 255e6331f2..4389fd4cc8 100644 --- a/content/400-pulse/250-database-setup/400-neon.mdx +++ b/content/400-pulse/250-database-setup/400-neon.mdx @@ -12,14 +12,10 @@ This section provides step-by-step instructions to make a [Neon](https://neon.te To enable logical replication on Neon, follow these steps: -1. Navigate to your project in the [Neon console](https://console.neon.tech/). -2. Go to the **Project settings** section from the Neon Dashboard. -3. Go to the **Beta** section in **Project Settings**. -4. Click on **Enable**. - - - You may be restricted from enabling logical replications due to an Enrollment Pause for the Neon logical replication beta phase. Learn more about enabling logical replication in Neon [here](https://neon.tech/docs/guides/logical-replication-neon#enabling-logical-replication-in-neon). - +1. Open your project in the [Neon console](https://console.neon.tech/). +2. In your project dashboard, go to the **Settings** section from the left panel. +3. Navigate to the **Logical Replication** tab in the **Settings** section. +4. Click the **Enable** button to enable logical replication. You have successfully enabled Logical replication for Neon. Now, follow the steps below to configure your Neon database to work with Pulse. @@ -27,17 +23,30 @@ You have successfully enabled Logical replication for Neon. Now, follow the step After enabling logical replication on Neon, follow these steps: -1. Create a publication to listen to database events from your Neon database. Use the **SQL Editor** in your Neon project to execute the SQL query to create a publication to listen to database change events from all tables: +1. Create a publication to track database change events in your Neon database. Open the **SQL Editor** from the left panel of your project dashboard in Neon, and run the following SQL query to create a publication that listens to events from all tables: + ```sql - CREATE Publication $PUBLICATION_NAME FOR ALL TABLES; + -- Replace $PUBLICATION_NAME with a custom name for your publication + CREATE PUBLICATION $PUBLICATION_NAME FOR ALL TABLES; ``` -
- - You can also create a publication to subscribe to database events from *specific tables*. To learn more on managing publications refer to [this](/pulse/database-setup/general-database-instructions#manage-your-own-publication-slot) section. - - -2. Before enabling Prisma Pulse, make sure to insert the publication name (e.g., `$PUBLICATION_NAME`) in the **Publication name** field in your project environment configuration for Pulse in the [Console](https://pris.ly/pdp): - - ![](/img/pulse/replication-slot-submission.png) +
+ :::warning + To manage your own publication slot while enabling Prisma Pulse, you'll need to be on one of our paid plans. Since managing your own publication slot is required when using Neon, upgrading to a paid plan will allow you to seamlessly use Pulse with Neon. For more information, please visit our [pricing page](https://www.prisma.io/pricing#pulse). + ::: + :::info + You can also create a publication to subscribe to database events from *specific tables*. For more details on managing publications, refer to [this section](/pulse/database-setup/general-database-instructions#manage-your-own-publication-slot). + ::: + +2. Navigate to [Prisma Data Platform](https://pris.ly/pdp) to enable Pulse. + +3. Submit the database connection string and region in the **Database connection** section. + +4. In your project environment configuration for Pulse, enter the publication name (e.g., `$PUBLICATION_NAME`) in the **Publication name** field. To access this, toggle the **Automatic setup** button in the **Database replication** section (available with a [paid plan](https://www.prisma.io/pricing#pulse)). + +5. After toggling **Automatic setup**, the button will transition to **Advanced setup**, and a textbox labeled **Publication name** will appear. + +6. Paste the publication name you created in Neon in *step 1*. + +7. Click **Enable Pulse**. Your Neon database is now Pulse-ready! Follow our [getting started](/pulse/getting-started#21-install-the-pulse-client-extension) guide to see how to use Pulse in your application. \ No newline at end of file diff --git a/content/400-pulse/250-database-setup/index.mdx b/content/400-pulse/250-database-setup/index.mdx index cdc4b59460..0886f3a0df 100644 --- a/content/400-pulse/250-database-setup/index.mdx +++ b/content/400-pulse/250-database-setup/index.mdx @@ -12,7 +12,7 @@ Prisma Pulse requires your database to be configured in a specific way. To get y -Prisma Pulse requires a publicly accessible PostgreSQL (**version 12+**) database with [logical replication](/pulse/database-setup/general-database-instructions#enable-logical-replication) enabled. +Prisma Pulse requires a PostgreSQL (**version 12+**) database with [logical replication](/pulse/database-setup/general-database-instructions#enable-logical-replication) enabled. diff --git a/content/400-pulse/275-static-ip.mdx b/content/400-pulse/275-static-ip.mdx new file mode 100644 index 0000000000..16487b34b8 --- /dev/null +++ b/content/400-pulse/275-static-ip.mdx @@ -0,0 +1,38 @@ +--- +title: "Static IP" +metaTitle: "Enable Static IP for Prisma Pulse" +metaDescription: "Learn enabling Static IP for Prisma Pulse." +--- + +You can enable static IP for Pulse when your security setup requires IP allowlisting or if you're implementing firewalls that only permit access from trusted IPs, ensuring controlled and secure database connections. + +![Result of enabling static IP Pulse with a database using IP allowlisting](/img/pulse/result-of-adding-static-ip-to-pulse.png) + +:::info + +To enable static IP support for Pulse within a new project environment, your workspace will need to be on our Pro or Business plans. Take a look at the [pricing page](https://www.prisma.io/pricing#pulse) for more information. + +::: + +## Enable static IP for Pulse + +You can opt-in to use static IP for Pulse when enabling it for a project environment: + +1. Insert the database connection string and the closest region to the database. +2. Toggle the **Static IP** switch in the **Network restrictions** section. This will provide you with a list of static IPv4 and IPv6 addresses. + Example IPv4 address range: + ``` + 52.86.207.46/32 + 100.29.164.162/32 + 54.211.230.107/32 + 18.235.169.169/32 + 54.209.237.70/32 + 44.221.111.173/32 + ``` + Example IPv6 address range: + ``` + 2600:1f18:51ce:b00::/64 + 2600:1f18:5acb:9a00::/56 + ``` +3. Once you have these addresses, configure your database firewall to allow incoming connections only from these IPs and any other trusted IPs that need access to your database. +4. Click on the **Enable Pulse** button. diff --git a/content/400-pulse/300-database-events.mdx b/content/400-pulse/300-database-events.mdx index 8de63f8f65..3c713b3bd5 100644 --- a/content/400-pulse/300-database-events.mdx +++ b/content/400-pulse/300-database-events.mdx @@ -197,9 +197,10 @@ If a `name` is provided, Pulse tracks the delivery of events with a _cursor_. On In case a stream is unavailable for some reason, e.g. because your server was down, the receiver can't acknowledge any events. Once the stream is available again, the stream will pick up at the last cursor position and deliver any events that haven't been acknowledged in the meantime: -![](/img/pulse/with-name.png) +![Resuming event streams with a name argument](/img/pulse/with-name.png) If the `name` option is omitted, no cursor will be associated with the stream and events that happen while a stream is down will not be delivered:` -![](/img/pulse/without-name.png) +![Resuming event streams without a name argument](/img/pulse/without-name.png) +Note that if `name` is provided, only one client can be connected to a stream with that particular `name` at any given time. diff --git a/content/400-pulse/400-api-reference.mdx b/content/400-pulse/400-api-reference.mdx index a17011e510..6063e785f3 100644 --- a/content/400-pulse/400-api-reference.mdx +++ b/content/400-pulse/400-api-reference.mdx @@ -42,12 +42,12 @@ for await (let event of subscription) { You can pass an object with configuration options to `stream()`. The object has the following fields: -| Name | Description | -| :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `name` | The name of the stream. Providing this option enables "resumability" and will make sure you receive events later if your stream isn't active at the time when the event actually happened (e.g. because your server was down). | -| `create` | An object to specify filters for the create events to be received. If you leave the object empty with `create: {}`, you will receive _all_ create events. You can filter on any scalar field of your model. | -| `update` | An object with an `after` field to specify filters for the update events to be received. If you leave the object empty with `update: {}`, you will receive _all_ update events. The filter is applied to the values of the record _after_ an update has been performed. You can filter on any scalar field of your model. | -| `delete` | An object to specify filters for the delete events to be received. You can filter on any scalar field of your model. | +| Name | Description | +| :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `name` | The name of the stream. Providing this option enables "resumability" and will make sure you receive events later if your stream isn't active at the time when the event actually happened (e.g. because your server was down). Note that if `name` is provided, only one client can be connected to a stream with that particular `name` at any given time. | +| `create` | An object to specify filters for the create events to be received. If you leave the object empty with `create: {}`, you will receive _all_ create events. You can filter on any scalar field of your model. | +| `update` | An object with an `after` field to specify filters for the update events to be received. If you leave the object empty with `update: {}`, you will receive _all_ update events. The filter is applied to the values of the record _after_ an update has been performed. You can filter on any scalar field of your model. | +| `delete` | An object to specify filters for the delete events to be received. You can filter on any scalar field of your model. | ### Return type @@ -97,7 +97,7 @@ const stream = await prisma.user.stream({ }); ``` -Learn more about resuming streams [here](/pulse/database-events#resuming-event-streams) +Learn more about resuming streams [here](/pulse/database-events#resuming-event-streams). #### Filter for new `User` records with a non-null value for `name` @@ -289,7 +289,7 @@ The type of the event is generic to the fields of your model. In the case, of th ```ts PulseCreateEvent<{ - id: number; + email: string; name: string | null; }>; @@ -316,13 +316,13 @@ An object of type `PulseUpdateEvent` is returned by any `delete` event that happ A `PulseUpdateEvent` has the following fields: -| Name | Type | Example value | Description | -| :---------- | :------- | :-------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `id` | `string` | `01HYBEER1JPSBVPG2NQADNQTA6` | A unique identifier / idempotency key following the [ULID](https://github.com/ulid/spec#specification) specification. | -| `modelName` | `string` | `User` | The name of the model affected by this event. This is a model name from your Prisma schema. | -| `action` | `string` | `update` | The kind of write-operation performed in the database: `update` | +| Name | Type | Example value | Description | +| :---------- | :------- | :-------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | `string` | `01HYBEER1JPSBVPG2NQADNQTA6` | A unique identifier / idempotency key following the [ULID](https://github.com/ulid/spec#specification) specification. | +| `modelName` | `string` | `User` | The name of the model affected by this event. This is a model name from your Prisma schema. | +| `action` | `string` | `update` | The kind of write-operation performed in the database: `update` | | `before` | `User` | `null` | An object with the _old_ values of the record that was just updated. This only works with when the [`REPLICA IDENTITY`](/pulse/database-setup/general-database-instructions#replica-identity) in your database is set to `FULL`. Otherwise the value will always be `null`. | -| `after` | `User` | See `after` in the example below. | An object with the _new_ values of the record that was just updated. | +| `after` | `User` | See `after` in the example below. | An object with the _new_ values of the record that was just updated. | The type of the event is generic to the fields of your model. In the case, of the `User` model above, it looks as follows: @@ -366,11 +366,11 @@ _With_ having set the `REPLICA IDENDITY` to `FULL`: A `PulseDeleteEvent` has the following fields: -| Name | Type | Example value | Description | -| :---------- | :------- | :--------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `id` | `string` | `01HYBEER1JPSBVPG2NQADNQTA6` | A unique identifier / idempotency key following the [ULID](https://github.com/ulid/spec#specification) specification. | -| `modelName` | `string` | `User` | The name of the model affected by this event. This is a model name from your Prisma schema. | -| `action` | `string` | `delete` | The kind of write-operation performed in the database: `create`, `update` or `delete`. | +| Name | Type | Example value | Description | +| :---------- | :------- | :--------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | `string` | `01HYBEER1JPSBVPG2NQADNQTA6` | A unique identifier / idempotency key following the [ULID](https://github.com/ulid/spec#specification) specification. | +| `modelName` | `string` | `User` | The name of the model affected by this event. This is a model name from your Prisma schema. | +| `action` | `string` | `delete` | The kind of write-operation performed in the database: `create`, `update` or `delete`. | | `deleted` | `User` | `{ id: 3 }` | An object with the values of the record that was just deleted. This only works with when the [`REPLICA IDENTITY`](/pulse/database-setup/general-database-instructions#replica-identity) in your database is set to `FULL`. Otherwise the object will only carry an `id` field. | The type of the event is generic to the fields of your model. In the case, of the `User` model above, it looks as follows: diff --git a/content/400-pulse/500-known-limitations.mdx b/content/400-pulse/500-known-limitations.mdx index 6e930e128e..eee2ec7214 100644 --- a/content/400-pulse/500-known-limitations.mdx +++ b/content/400-pulse/500-known-limitations.mdx @@ -54,5 +54,8 @@ The size limit of [database events](/pulse/database-events) depends on your [sub Note that database events are base64 encoded for transmission. The size limit applies to the _encoded_ not the _original_ size of the event. -If your events exceed the size limit, they will be rejected by Prisma Pulse and won't arrive on the receiver side. You can see how many events have been rejected by Prisma Pulse in the Pulse Dashboard in the [Console](https://console.prisma.io/). +If your events exceed the size limit, they will be rejected by Prisma Pulse and won't arrive on the receiver side. You can see how many events have been rejected by Prisma Pulse in the Pulse Dashboard in the [Console](https://console.prisma.io/login). +## Static IP cannot be enabled for existing Pulse-enabled environments + +Currently, static IP cannot be enabled for an existing Pulse-enabled environment. To use static IP, you must opt-in to use static IP when enabling Pulse in a new environment. As a workaround, create a new environment in your project with the same database connection string as your current Pulse-enabled environment in order to gain static IP support for Pulse. diff --git a/content/400-pulse/600-faq.mdx b/content/400-pulse/600-faq.mdx index 591408ea75..b45e85cf45 100644 --- a/content/400-pulse/600-faq.mdx +++ b/content/400-pulse/600-faq.mdx @@ -37,6 +37,10 @@ Usage of the API is billed according to these factors: - **Events reads**: The number of database events _read_ and _delivered_ by Pulse via `.stream()` - **Event storage**: The amount of disk space the stored events consume (in GiB) +## Will I get charged for event persistence even if I don't use named streams via `name`? + +Yes. If you enable **Event persistence** in your project, your database events will be persisted and you will be charged accordingly. + ## How many Prisma Client instances can subscribe to a database event? The number of Prisma Client instances that can subscribe to via Prisma Pulse has the following limits: @@ -60,10 +64,38 @@ No, Pulse is server-side and subscriptions cannot be initiated directly within c To propagate events to the frontend, you can use a WebSocket library like [socket.io](https://socket.io/). -## How to configure `tsconfig.json` with the Pulse extension? +## How do I import the Pulse Client extension when using `"moduleResolution":"bundler"` in my `tsconfig.json`? + +If you're using [`"moduleResolution": "bundler"`](https://www.typescriptlang.org/docs/handbook/modules/reference.html#bundler) in your `tsconfig.json` file and your Pulse extension version is `1.2.0` or greater, import the Pulse extension based on your runtime: + + + + + +```ts +import { withPulse } from '@prisma/extension-pulse/node'; +``` + + + + + +```ts +import { withPulse } from '@prisma/extension-pulse/workerd'; +``` + + + + + +The Pulse Client extension provides runtime-specific implementations. This approach ensures TypeScript uses the correct type definitions for your target environment and any other multi-entrypoint packages. + +Using the correct runtime-specific import prevents the following error: +``` +Cannot find module '@prisma/extension-pulse' or its corresponding type declarations. +``` -If you're using [`"moduleResolution": "bundler"`](https://www.typescriptlang.org/docs/handbook/modules/reference.html#bundler) in your `tsconfig.json` file, you need to -explicitly set [`customConditions`](https://www.typescriptlang.org/tsconfig/#customConditions) to either `node` or `workerd` depending on your target runtime. This will instruct TypeScript to match the correct type definitions of the Prisma Pulse extension, as well as any other packages that expose multiple entrypoints: +Alternatively, you can configure tsconfig.json to set the correct runtime condition: ```js // tsconfig.json @@ -72,15 +104,45 @@ explicitly set [`customConditions`](https://www.typescriptlang.org/tsconfig/#cus // ...other options "target": "es2022", "moduleResolution": "bundler", - "customConditions": ["workerd"] // or "node" + "customConditions": ["node"] // or "workerd" for Cloudflare Workers } } ``` +
+:::note +We recommend this approach when building a package that uses the Prisma Pulse Client extension as a dependency. +::: -This is needed because Prisma Pulse extension offers separate implementations tailored for various runtimes, such as Node.js and Cloudflare Workers. +Both methods ensure the correct runtime-specific types are used and resolve module resolution errors. -If you don't add this, you may run into the following error when using the `@prisma/extension-pulse` in your application code: +## How can I ensure SSL/TLS encryption works in SSL-only mode with PostgreSQL database and Pulse? + +If you encounter issues with SSL/TLS encryption while using Pulse, ensure your database server has a valid SSL certificate and append `sslmode=require` to your database connection string in your project environment in [Prisma Data Platform](https://pris.ly/pdp), for example: ``` -Cannot find module '@prisma/extension-pulse' or its corresponding type declarations. -``` \ No newline at end of file +postgres://username:password@hostname:port/database?sslmode=require +``` + +This [setting](/orm/overview/databases/postgresql#configuring-an-ssl-connection) will enforce SSL/TLS encryption and accept self-signed certificates. + +## When should I enable static IP for Prisma Pulse? + +Enable static IP for Pulse when your security setup requires IP allowlisting or if you're implementing firewalls that only permit access from trusted IPs, ensuring controlled and secure database connections. + +![Result of enabling static IP Pulse with a database using IP allowlisting](/img/pulse/result-of-adding-static-ip-to-pulse.png) + +Learn more on [how to enable static IP for Pulse in the Platform Console](/pulse/static-ip). + +> ℹ️ To enable static IP support for Accelerate within your existing or new project environment, your workspace will need to be on our **Pro** or **Business** plans. Take a look at the [pricing page](https://www.prisma.io/pricing#accelerate) for more information. + +:::info +**What is a static IP?** + +A static IP address is an IPv4 or an IPv6 address that is fixed. Unlike dynamic IP addresses, which can change unpredictably, traffic from static IP addresses can be easily identified. + +![What is a static IP](/img/accelerate/static-ip.png) +::: + +## Do the static IP ranges for Accelerate and Pulse differ? + +No, if you have static IP enabled for both Accelerate and Pulse using the same database URL, the generated static IP ranges will be the same for both products. \ No newline at end of file diff --git a/content/400-pulse/700-feedback.mdx b/content/400-pulse/700-feedback.mdx index 6a3b7b6f5e..75aef8d337 100644 --- a/content/400-pulse/700-feedback.mdx +++ b/content/400-pulse/700-feedback.mdx @@ -5,8 +5,4 @@ metaDescription: 'Learn where to submit feedback about Prisma Pulse.' tocDepth: 3 --- - - You can submit any feedback about Prisma Pulse in the `#help-and-questions` channel in our community [Discord](https://pris.ly/discord). - - diff --git a/content/400-pulse/800-examples.mdx b/content/400-pulse/800-examples.mdx new file mode 100644 index 0000000000..c46f37d932 --- /dev/null +++ b/content/400-pulse/800-examples.mdx @@ -0,0 +1,19 @@ +--- +title: 'Prisma Pulse examples' +metaTitle: 'Prisma Pulse: Examples' +metaDescription: 'Check out ready-to-run examples for Prisma Pulse.' +sidebar_label: 'Examples' +tocDepth: 3 +--- + +Here is a list of ready-to-run example projects that demonstrate how to use Prisma Pulse to build real-time applications: + +| Demo | Description | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | +| [`starter`](https://github.com/prisma/prisma-examples/tree/latest/pulse/starter) | A Prisma Pulse starter app | +| [`email-with-resend`](https://github.com/prisma/prisma-examples/tree/latest/pulse/email-with-resend) | An example app to send emails to new users using Prisma Pulse and Resend | +| [`fullstack-leaderboard`](https://github.com/prisma/prisma-examples/tree/latest/pulse/fullstack-leaderboard) | A live leaderboard (built with Next.js) | +| [`fullstack-simple-chat`](https://github.com/prisma/prisma-examples/tree/latest/pulse/fullstack-simple-chat) | A simple chat app (built with Next.js & Express) | +| [`product-search-with-typesense`](https://github.com/prisma/prisma-examples/tree/latest/pulse/product-search-with-typesense) | A cron job that syncs data into Typesense (built with Hono.js) | +| [`data-sync-with-bigquery`](https://github.com/prisma/prisma-examples/tree/latest/pulse/data-sync-with-bigquery) | A script that automatically syncs data into Google BigQuery | + diff --git a/content/400-pulse/index.mdx b/content/400-pulse/index.mdx index d4afdaf809..ed8fe580c2 100644 --- a/content/400-pulse/index.mdx +++ b/content/400-pulse/index.mdx @@ -3,8 +3,7 @@ title: '' metaTitle: 'Prisma Pulse' metaDescription: 'Prisma Pulse enables real-time database events with type-safe Prisma Client subscriptions.' sidebar_position: 0 -pagination_next: 'pulse/what-is-pulse' - +pagination_next: 'pulse/getting-started' --- import { @@ -27,7 +26,13 @@ import { Prisma Pulse -[Prisma Pulse](https://www.prisma.io/data-platform/pulse) lets you subscribe to any changes in your database easily and in a type-safe way using Prisma Client, enabling you to trigger events and actions in real-time. +[Prisma Pulse](https://www.prisma.io/data-platform/pulse) lets you build reactive, event-driven applications with your serverless backend, connecting seamlessly to your existing PostgreSQL database. With just a few lines of code, you can react to database changes in real-time. + +This enables real-time tasks like sending welcome emails when a user signs up or simplifying complex batch jobs. + +Pulse offers an alternative to traditional backend systems built with queues or scheduled batch jobs, eliminating the need for hosting, management, and maintenance. + +Pulse provides a simple alternative using the idea of unidirectional data flow (via the [Change Data Capture](https://en.wikipedia.org/wiki/Change_data_capture) pattern). It also integrates seamlessly with Prisma ORM and lets you subscribe to any database change events directly via Prisma Client. -Learn about the main concepts and workflows of the [Prisma Data Platform](https://prisma.io/data-platform/). +Learn about the main concepts and workflows of the [Prisma Data Platform](https://console.prisma.io/login). diff --git a/content/700-optimize/200-getting-started.mdx b/content/700-optimize/200-getting-started.mdx new file mode 100644 index 0000000000..57ee6331e1 --- /dev/null +++ b/content/700-optimize/200-getting-started.mdx @@ -0,0 +1,92 @@ +--- +title: 'Getting Started' +metaTitle: 'Getting started with Prisma Optimize' +metaDescription: 'Learn how to quickly set up and start using Prisma Optimize.' +tocDepth: 3 +toc: true +--- + +## Prerequisites + +Before you begin with Prisma Optimize, ensure you have the following: + +- 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 PostgreSQL, MySQL/MariaDB, CockroachDB, or MS SQL Server database. + +:::note + +Prisma Optimize is intended for use in local environments. Learn more in the [FAQ](/optimize/faq#can-i-use-prisma-optimize-in-production). + +::: + +## 1. Launch Optimize + +1. Log in to your [Prisma Data Platform account](https://console.prisma.io/optimize?utm_source=docs&utm_medium=optimize-page). +2. Follow the instructions to access and launch Prisma Optimize. + +## 2. Add Optimize to your application + +### 2.1. Update Your `schema.prisma` file + +In the `generator` block of your Prisma schema, add the `tracing` preview feature: + +```prisma +generator client { + provider = "prisma-client-js" + previewFeatures = ["tracing"] +} +``` + +Then, generate the Prisma Client: + +```bash +npx prisma generate +``` + +### 2.2. Install the Optimize Prisma Client extension + +Install the latest versions of Prisma Client and the Optimize extension: + +```bash +npm install @prisma/client@latest @prisma/extension-optimize +``` + +### 2.3. Add the Optimize API Key to your `.env` file + +Generate a Prisma Optimize API key and add it to your `.env` file: + +```bash +OPTIMIZE_API_KEY="YOUR_OPTIMIZE_API_KEY" +``` + +### 2.4. Extend your Prisma Client instance + +Extend your existing Prisma Client instance with the Optimize extension: + +```ts +import { PrismaClient } from "@prisma/client"; +import { withOptimize } from "@prisma/extension-optimize"; + +const prisma = new PrismaClient().$extends( + withOptimize({ apiKey: process.env.OPTIMIZE_API_KEY }), +); +``` + +### 2.5. Use Prisma Optimize to generate insights + +Follow these steps to start generating query insights with Prisma Optimize: + +1. In the Optimize dashboard, click the **Start recording** button, then run your app and execute some Prisma queries while recording is active. +2. After your app runs and generates insights based on the executed Prisma queries, click the **Stop recording** button. +3. Explore [individual query details](/optimize/recordings#data-captured-in-a-recording-session) by clicking on them, and check the **Recommendations** tab for any suggested improvements to enhance query performance. + + :::info + Use [Prisma AI](/optimize/prisma-ai) to understand recommendations and apply them within your Prisma model context. + ::: + +For a hands-on learning experience, try out the [step-by-step example](https://github.com/prisma/prisma-examples/tree/latest/optimize/starter). + +## Need help? + +If you need assistance, reach out in the `#help-and-questions` channel on our [Discord](https://pris.ly/discord), or connect with our community to see how others are using Optimize. diff --git a/content/700-optimize/300-recordings.mdx b/content/700-optimize/300-recordings.mdx new file mode 100644 index 0000000000..2ae1727832 --- /dev/null +++ b/content/700-optimize/300-recordings.mdx @@ -0,0 +1,47 @@ +--- +title: 'Recordings' +metaTitle: 'Optimize: Recordings' +metaDescription: "Learn about using Optimize's recording feature." +tocDepth: 3 +toc: true +--- + +The recordings feature helps developers debug and isolate sets of queries into distinct sessions, known as recordings. This targeted approach enables precise performance analysis and optimization by preventing the mixing of queries from different applications or test rounds, leading to clearer insights and more effective debugging. + +## Managing a recording session + +You can manually start and stop recording sessions via the [Optimize dashboard](https://console.prisma.io/optimize) by clicking the **Start Recording** and **Stop Recording** buttons. + +:::warning +A recording will automatically stop if the 10k query limit is reached or if the Prisma schema of the app is changed. +::: + +## Identifying a recording session + +You can rename and tag your recording sessions for easy identification and context. Click on the default name of the session and type the desired name. + +## Data captured in a recording session + +Each recording session captures detailed insights about the queries executed in your app, including: + +- All queries executed during the session. +- The raw query generated and sent to the database by Prisma ORM as **Raw Query**. +- The number of times a query pattern was executed, listed as **Count**. +- [Query performance metrics](/optimize/performance-metrics). +- Errors encountered during query execution. + +Each recording can include up to 10k queries. There are no limits on storage retention. + +## Recommendations from a recording session + +When a recording session ends, Optimize generates recommendations such as: + +- [Excessive number of rows returned](/optimize/recommendations/excessive-number-of-rows-returned) +- [Full table scans caused by LIKE operations](/optimize/recommendations/full-table-scans-caused-by-like-operations) +- [Queries on unindexed columns](/optimize/recommendations/queries-on-unindexed-columns) + +:::info +Use [Prisma AI](/optimize/prisma-ai) to ask follow-up questions about a recommendation. +::: + +Learn more about the recommendations generated by Optimize [here](/optimize/recommendations). diff --git a/content/700-optimize/400-recommendations/100-excessive-number-of-rows-returned.mdx b/content/700-optimize/400-recommendations/100-excessive-number-of-rows-returned.mdx new file mode 100644 index 0000000000..45c2f128f8 --- /dev/null +++ b/content/700-optimize/400-recommendations/100-excessive-number-of-rows-returned.mdx @@ -0,0 +1,30 @@ +--- +title: 'Excessive number of rows returned' +metaTitle: 'Optimize Recommendations: Excessive number of rows returned' +metaDescription: "Learn about the recommendation provided by Optimize for excessive number of rows returned." +tocDepth: 3 +toc: true +--- + +Optimize provides recommendations to help you identify and resolve performance issues caused by excessive number of rows returned from a query. + +The following query targeting a `User` model does not provide a [`take` option](/orm/reference/prisma-client-reference#findmany): + +```ts +await prisma.user.findMany({ where: { email: "janedoe@gmail.com" }}) +``` + +## What is the problem? + +When a query is executed without specifying a limit, it will return all relevant rows, which can lead to several issues: + +### User experience + +- **Viewing data:** Users typically need only a portion of the data at any given time, not all of it at once. +- **Impact on the user's device:** Displaying all the data at once can strain the user's device resources. For example, loading thousands of rows in a web application can slow down or freeze the browser, consuming significant memory and CPU resources. +- **Waiting time:** Retrieving a large number of rows can significantly increase the time it takes to get the data from the database to the user's device. + +### Resource Utilization + +- **Unnecessary data load:** Processing more data than required wastes valuable resources. +- **Memory usage:** Excessive memory consumption can lead to inefficiency and, in severe cases, cause the system to run out of memory, disrupting the service. diff --git a/content/700-optimize/400-recommendations/200-queries-on-unindexed-columns.mdx b/content/700-optimize/400-recommendations/200-queries-on-unindexed-columns.mdx new file mode 100644 index 0000000000..26b6225236 --- /dev/null +++ b/content/700-optimize/400-recommendations/200-queries-on-unindexed-columns.mdx @@ -0,0 +1,85 @@ +--- +title: 'Queries on unindexed columns' +metaTitle: 'Optimize Recommendations: Queries on unindexed columns' +metaDescription: "Learn about the recommendation provided by Optimize for queries on unindexed columns." +tocDepth: 3 +toc: true +--- + +Optimize provides recommendations to help you identify and resolve performance issues caused by missing database indexes. + +The following queries targeting the `User` model use a [`where` property](/orm/prisma-client/queries/filtering-and-sorting) to filter on columns that do not have indexes: + +```ts +await prisma.user.findFirst({ + where: { + name: "Marc" + } +}) + +await prisma.user.findFirst({ + where: { + name: "Jon" + } +}) + +await prisma.user.count({ + where: { + name: "Nikolas" + } +}) +``` + +## What is the problem? + +An index allows the database to retrieve data more quickly, similar to how an index in a book helps you locate information without reading every page. + +When using Prisma with a `where` property, if no indexes are defined for the relevant columns, the database may need to scan every row in the table (a *“full table scan”*) to find matches. This can be undesirable for several reasons: + +### User experience + +For large datasets, if the database must scan the entire table to find matching rows, users will experience longer waiting times. + +### Resource utilization + +- **High CPU usage:** Scanning large tables can significantly increase CPU usage, degrading overall system performance. +- **Memory consumption:** More memory is required to process and store data during a full table scan. +- **Disk I/O:** Full table scans increase disk input/output operations, potentially slowing down other database activities. + +:::warning + +While these issues might not appear in development due to smaller datasets, they can become *significant* problems in production, where datasets are typically much larger. + +::: + + +## More on database indexes + +### How indexes work + +Indexes create a data structure that stores the indexed column's values along with pointers to the corresponding rows in the table. When you query the database using an indexed column, the database can use this index to quickly locate the relevant rows instead of scanning the entire table. + +### The trade-offs of indexing + +- **Space vs. time:** Indexing requires additional storage space to save index data, but it significantly speeds up data retrieval. +- **Update overhead:** Every time data is added to, updated in, or removed from your table, there is an overhead to keep the indexes up to date, which can slow down write operations. + +### When to use indexes + +- **Large datasets:** Indexes are particularly beneficial for tables with a large number of rows. +- **Frequent queries with filtering or sorting:** Use indexes on columns that are frequently used for [filtering or sorting](/orm/prisma-client/queries/filtering-and-sorting#filtering). +- **Looking up related data:** Use indexes on foreign key columns to speed up the retrieval of related records, such as when using [`include`](/orm/prisma-client/queries/relation-queries#include-a-relation). + +### When not to use indexes + +- **Small tables:** For tables with very few rows, the overhead of maintaining indexes might not be worth the performance gain. +- **Write-heavy tables:** Indexes can slow down write operations (`create`, `update`, `delete`) because the index needs to be updated as well. Avoid excessive indexing on models with frequent write operations. +- **Infrequently accessed tables:** If a table is rarely accessed, the benefits of indexing may not justify the overhead. +- **Columns with large data:** Indexing columns with large data can lead to higher storage requirements and might not provide significant performance improvements. +- **Rarely filtered columns:** If a table is often accessed but rarely filtered by a specific column, creating an index on that column may not be beneficial. + +:::warning + +Even if you index a column, the database may not always use it. Many database management systems, such as PostgreSQL and MySQL, have a *query optimizer* that evaluates multiple execution plans and selects the one it estimates to be most efficient. In some cases, this may involve ignoring an existing index in favor of a different execution plan that it determines will perform better for that specific query. + +::: \ No newline at end of file diff --git a/content/700-optimize/400-recommendations/300-full-table-scans-caused-by-like-operations.mdx b/content/700-optimize/400-recommendations/300-full-table-scans-caused-by-like-operations.mdx new file mode 100644 index 0000000000..312f879849 --- /dev/null +++ b/content/700-optimize/400-recommendations/300-full-table-scans-caused-by-like-operations.mdx @@ -0,0 +1,33 @@ +--- +title: 'Full table scans caused by LIKE operations' +metaTitle: 'Optimize Recommendations: Full table scans caused by LIKE operations' +metaDescription: "Learn about the recommendation provided by Optimize for full table scans caused by Like operations." +tocDepth: 3 +toc: true +--- + +Optimize provides recommendations to help you identify and resolve performance issues caused by full table scans from `LIKE` operations. + +The following query targeting the `User` model provides `contains` and `endsWith` as options, which translate to `LIKE` and `ILIKE` SQL operators. + +```jsx +await prisma.user.findMany({ + where: { + email: { contains: "gmail.com" }, + name: { endsWith: "Burk" } + } +}) +``` + +## What is the problem? + +`LIKE` and `ILIKE` operators in SQL can lead to full table scans, potentially impacting performance, especially with larger datasets: + +### UX + +- **Slower load times:** Full table scans can significantly increase the time it takes to retrieve data, leading to longer wait times for users. + +### Resource utilization + +- **Increased resource usage:** Full table scans increase CPU, memory usage, and disk I/O, straining system resources for your database. +- **Increased costs:** In serverless database pricing plans, more intensive resource usage can translate into higher costs. diff --git a/content/700-optimize/400-recommendations/_category_.json b/content/700-optimize/400-recommendations/_category_.json new file mode 100644 index 0000000000..258ab00c98 --- /dev/null +++ b/content/700-optimize/400-recommendations/_category_.json @@ -0,0 +1,4 @@ +{ + "collapsed": false, + "collapsible": false +} diff --git a/content/700-optimize/400-recommendations/index.mdx b/content/700-optimize/400-recommendations/index.mdx new file mode 100644 index 0000000000..cb86fc11bf --- /dev/null +++ b/content/700-optimize/400-recommendations/index.mdx @@ -0,0 +1,15 @@ +--- +title: 'Recommendations' +metaTitle: 'Optimize: Recommendations' +metaDescription: "Learn about the recommendations provided by Optimize." +tocDepth: 3 +toc: true +--- + +Optimize provides recommendations focused on performance improvements such as indexing issues, excessive data retrieval, and inefficient query patterns. Recommendations include: + +:::info +Use [Prisma AI](/optimize/prisma-ai) to ask follow-up questions about any recommendation. +::: + + diff --git a/content/700-optimize/450-prisma-ai.mdx b/content/700-optimize/450-prisma-ai.mdx new file mode 100644 index 0000000000..188aba804a --- /dev/null +++ b/content/700-optimize/450-prisma-ai.mdx @@ -0,0 +1,18 @@ +--- +title: 'Prisma AI' +metaTitle: 'Optimize: Prisma AI' +metaDescription: "Learn about using Optimize's Prisma AI feature." +tocDepth: 3 +toc: true +--- + +Prisma AI enables you to ask follow-up questions on a provided [recommendation](/optimize/recommendations) for additional clarity. + +## Using the Prisma AI + +To interact with the Prisma AI: + +1. Select a recommendation from an Optimize [recording](/optimize/recordings). +2. Click the **Ask AI** button. + +Prisma AI helps you gain deeper insights into a recommendation and learn how to apply it effectively to your Prisma model. \ No newline at end of file diff --git a/content/700-optimize/500-performance-metrics.mdx b/content/700-optimize/500-performance-metrics.mdx new file mode 100644 index 0000000000..b636f2fd30 --- /dev/null +++ b/content/700-optimize/500-performance-metrics.mdx @@ -0,0 +1,29 @@ +--- +title: 'Performance metrics' +metaTitle: 'Optimize: Query performance metrics' +metaDescription: 'Learn about the query performance metrics provided by Optimize.' +tocDepth: 3 +toc: true +--- + +An Optimize recording session provides detailed insights into the latencies of executed queries, capturing key metrics such as average duration, 50th percentile, 99th percentile, and maximal query execution time. + +## Total query durations + +Prisma Optimize measures total latency for query patterns, enabling you to analyze and debug slow queries effectively. + +### Average query duration (**`AVG`**) + +The average query duration reveals the mean execution time across all queries, helping you assess overall performance trends and identify inefficiencies that impact the user experience. + +### 50th percentile (**`P50`**) + +The 50th percentile, or median, query duration indicates the time within which half of your queries complete. This metric offers a clear view of typical user performance, unaffected by outliers. + +### 99th percentile (**`P99`**) + +The 99th percentile query duration highlights the execution time for the slowest 1% of queries. This metric is crucial for uncovering and addressing performance bottlenecks that, while infrequent, can significantly impact user satisfaction. + +### Maximal query duration (**`MAX`**) + +The maximal query duration measures the time taken by the single slowest query. This metric helps identify extreme cases, providing insights into the worst performance scenarios your system might face, so you can diagnose and resolve outliers. diff --git a/content/700-optimize/600-faq.mdx b/content/700-optimize/600-faq.mdx new file mode 100644 index 0000000000..c2e97c8d90 --- /dev/null +++ b/content/700-optimize/600-faq.mdx @@ -0,0 +1,31 @@ +--- +title: "FAQ" +metaTitle: "Prisma Optimize: FAQ" +metaDescription: "Frequently asked questions about Prisma Optimize." +tocDepth: 3 +toc: true +--- + +## Does Optimize automatically implement optimizations? + +Prisma Optimize offers insights and recommendations on how to improve your database queries. It does not alter any existing queries or your Prisma schema. + +## How long is a recording session retained in Optimize? + +There are no limits on the storage retention period. Optimize will store a recording session until you explicitly delete it. + +## Do recommendation limits reset monthly? + +Yes, the recommendation usage resets at the beginning of each calendar month. For example, if you use 5 recommendations by the end of the month, your usage will reset to 0 at the start of the next month. + +## Can I get charged for exceeding the recommendation limit on the starter plan? + +Yes, if you’re on the starter plan, exceeding 5 recommendations in a billing cycle will result in a $5 charge at the end of that cycle. For more information, visit [our pricing page](https://www.prisma.io/pricing#optimize). + +## How does Optimize track viewed recommendations for billing? Are they counted based on generated or viewed recommendations? + +They are counted based on viewed recommendations. Once you click on a recommendation from the recommendations table and view the recommendation's detail page, it counts as being seen. + +## Can I use Prisma Optimize in production? + +No, Prisma Optimize is not intended for production use. It is specifically designed for local development, providing valuable insights and optimizations during that phase. While it’s technically possible to run it in a production environment, doing so could result in performance problems or unexpected behaviors, as Optimize is not built to handle the complexity and scale of production workloads. For the best experience, we recommend using Prisma Optimize solely in your development environment. \ No newline at end of file diff --git a/content/700-optimize/700-known-limitations.mdx b/content/700-optimize/700-known-limitations.mdx new file mode 100644 index 0000000000..100e91d006 --- /dev/null +++ b/content/700-optimize/700-known-limitations.mdx @@ -0,0 +1,53 @@ +--- +title: 'Known limitations' +metaTitle: 'Optimize: Known limitations' +metaDescription: 'Learn about known limitations of Optimize.' +tocDepth: 3 +toc: true +--- + +Below are the known limitations when using Prisma Optimize. If you are aware of any limitations that are missing, please let us know on the `#help-and-questions` channel in our community [Discord](https://pris.ly/discord). + +## Query limit on a recording session + +Each [recording session](/optimize/recordings) can contain a maximum of 10,000 queries. Once this limit is reached, the recording session will end. + +## Recording limit per workspace + +Each [workspace](/platform/about#workspace) can contain a maximum of 100 [recordings](/optimize/recordings). + +## Scope and constraints for the Prisma AI + +While [Prisma AI](/optimize/prisma-ai) can provide helpful guidance to implement a [recommendation](/optimize/recommendations), there are some important limitations to keep in mind: + +- **Information and accuracy**: The AI provides advice based on a broad, general knowledge base and does not have direct access to Prisma ORM documentation. This may occasionally result in inaccuracies or outdated information. + +- **Limited context and adaptation**: The AI does not persist conversations or learn from previous interactions. Its responses are generalized and may not always address the specific needs of advanced users. + +- **Static knowledge and scope**: The AI's knowledge is static and may not include recent updates or best practices after a certain date. It provides advice only within the context of Prisma ORM and cannot modify or execute code, nor interact directly with user environments. + +## Using Prisma Accelerate client extension with the Optimize extension + +When using the [Optimize client extension](https://www.npmjs.com/package/@prisma/extension-optimize) with the [Accelerate client extension](https://www.npmjs.com/package/@prisma/extension-accelerate), ensure the Accelerate client extension is added last to your extended `PrismaClient`. This allows cacheable operations to be received by Optimize. + +```ts +const prisma = new PrismaClient() + .$extends( + withOptimize({ + apiKey: process.env.OPTIMIZE_API_KEY, + }), + ) + .$extends(withAccelerate()); +``` + +### SQL references in MongoDB recommendations + +Prisma Optimize provides helpful recommendations for MongoDB users, though some explanations from [Prisma AI](/optimize/prisma-ai) may reference SQL-specific concepts. However, the [recommendations](/optimize/recommendations) remain useful and applicable to MongoDB environments. + +### Raw query visibility in MongoDB + +Raw queries are visible in MongoDB, though the parameters passed to them are not displayed. + +## Driver adapter compatibility + +Prisma Optimize is not yet compatible with [driver adapters](/orm/overview/databases/database-drivers#driver-adapters). However, as a workaround, you can run your queries locally using the regular Prisma Client along with Prisma Optimize to inspect and improve query performance. diff --git a/content/700-optimize/index.mdx b/content/700-optimize/index.mdx new file mode 100644 index 0000000000..5b3d2cf93a --- /dev/null +++ b/content/700-optimize/index.mdx @@ -0,0 +1,90 @@ +--- +title: 'Optimize' +metaTitle: 'Prisma Optimize' +metaDescription: 'Prisma Optimize is a tool that helps you generate insights on your queries and recommends performance optimizations.' +sidebar_position: 0 +hide_table_of_contents: false +pagination_next: 'optimize/getting-started' +--- + +import { + Bolt, + BorderBox, + BoxTitle, + Database, + Grid, + LinkCard, + List, + SignalStream, + SquareLogo, +} from '@site/src/components/GettingStarted'; + +import { + IconTitle +} from '@site/src/components/shortcodes/index'; + + +Prisma Optimize + +[Prisma Optimize](https://www.prisma.io/data-platform/optimize?utm_source=docs). helps you generate insights and provides recommendations that can help you make your database queries faster. + +This helps you to: + +- Generate insights about your database queries +- Identify errors to help debug your database queries +- Receive recommendations and discuss them with an AI assistant to enhance query performance. + +Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. + + + + + + + +## Supported databases + +Optimize works with the database you already have. + + + + + + + + + +## In this section + + diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 3c219536e1..d305de5b97 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -34,10 +34,11 @@ const config: Config = { // kapa.ai script { src: "https://widget.kapa.ai/kapa-widget.bundle.js", - defer: true, + async: true, "data-website-id": "1b51bb03-43cc-4ef4-95f1-93288a91b560", "data-project-name": "Prisma", "data-project-color": "#2D3748", + "data-user-analytics-fingerprint-enabled": "true", "data-project-logo": "https://www.prisma.io/docs/ai_logo.png", "data-button-text": "Ask AI", "data-modal-example-questions": @@ -55,25 +56,23 @@ const config: Config = { "data-button-box-shadow": "drop-shadow(0px 0.724px 1.251px rgba(14, 18, 28, 0.02)) drop-shadow(0px 1.608px 2.909px rgba(14, 18, 28, 0.04)) drop-shadow(0px 2.793px 5.225px rgba(14, 18, 28, 0.06)) drop-shadow(0px 4.55px 8.671px rgba(14, 18, 28, 0.07)) drop-shadow(0px 7.485px 14.285px rgba(14, 18, 28, 0.08)) drop-shadow(0px 13.358px 24.966px rgba(14, 18, 28, 0.09)) drop-shadow(0px 33px 54px rgba(14, 18, 28, 0.07))", }, - // Enzuzo Cookies Consent script for prisma.io - { - src: "https://app.enzuzo.com/apps/enzuzo/static/js/__enzuzo-cookiebar.js?uuid=5606ab18-eb9a-11ee-98cc-b303d4429aa8", - }, // Tolt script { src: "https://cdn.tolt.io/tolt.js", + async: true, "data-tolt": "fda67739-7ed0-42d2-b716-6da0edbec191", }, + // Common Room + { + src: "https://cdn.cr-relay.com/v1/site/cc8b954c-5f74-4254-a72a-e0d61048bd58/signals.js", + async: true, + }, ], plugins: ["docusaurus-plugin-sass"], presets: [ [ "classic", { - gtag: { - trackingID: "G-YS7QHR40SL", - anonymizeIP: true, - }, googleTagManager: { containerId: "GTM-KCGZPWB", }, @@ -124,6 +123,11 @@ const config: Config = { ], themeConfig: { image: "/docs/social/docs-social.png", + metadata: [ + { name: "twitter:card", content: "summary_large_image" }, + { name: "twitter:site", content: "@prisma" }, + { name: "twitter:creator", content: "@prisma" }, + ], navbar: { logo: { srcDark: "img/logo-white.svg", @@ -153,6 +157,13 @@ const config: Config = { className: "indigo", label: "ORM", }, + { + type: "docSidebar", + sidebarId: "optimizeSidebar", + position: "left", + className: "teal", + label: "Optimize", + }, { type: "docSidebar", sidebarId: "accelerateSidebar", @@ -176,7 +187,7 @@ const config: Config = { { href: "https://console.prisma.io/login?utm_source=docs&utm_medium=login", position: "right", - label: "Login", + label: "Log in", className: "navbar-login-btn internal teal-btn", }, ], @@ -194,6 +205,51 @@ const config: Config = { footer: { style: "dark", links: [ + { + title: "socials", + items: [ + { + label: " ", + href: "https://discord.gg/KQyTW2H5ca", + customProps: { + icon: "fa-brands fa-discord", + internal: true, + }, + }, + { + label: " ", + href: "https://x.com/prisma", + customProps: { + icon: "fa-brands fa-x-twitter", + internal: true, + }, + }, + { + label: " ", + href: "https://www.youtube.com/prismadata", + customProps: { + icon: "fa-brands fa-youtube", + internal: true, + }, + }, + { + label: " ", + href: "https://pris.ly/whatsapp", + customProps: { + icon: "fa-brands fa-whatsapp", + internal: true, + }, + }, + { + label: " ", + href: "https://github.com/prisma", + customProps: { + icon: "fa-brands fa-github", + internal: true, + }, + }, + ], + }, { title: "Product", items: [ @@ -205,6 +261,22 @@ const config: Config = { internal: true, }, }, + { + label: "Studio", + href: "https://www.prisma.io/studio", + target: "_self", + customProps: { + internal: true, + }, + }, + { + label: "Optimize", + href: "https://www.prisma.io/data-platform/optimize", + target: "_self", + customProps: { + internal: true, + }, + }, { label: "Accelerate", href: "https://www.prisma.io/data-platform/accelerate", @@ -262,6 +334,10 @@ const config: Config = { label: "Playground", href: "https://playground.prisma.io/", }, + { + label: "ORM Benchmarks", + href: "https://benchmarks.prisma.io/", + }, { label: "Customer stories", href: "https://www.prisma.io/showcase", @@ -378,54 +454,17 @@ const config: Config = { }, }, { - label: "Security & Compliance", - href: "https://trust.prisma.io/", - target: "_self", - customProps: { - internal: true, - }, - }, - ], - }, - { - items: [ - { - label: " ", - href: "https://discord.gg/KQyTW2H5ca", + label: "Event Code of Conduct", + href: "https://pris.ly/code-conduct", customProps: { - icon: "fa-brands fa-discord", - internal: true, - }, - }, - { - label: " ", - href: "https://x.com/prisma", - customProps: { - icon: "fa-brands fa-x-twitter", - internal: true, - }, - }, - { - label: " ", - href: "https://www.youtube.com/prismadata", - customProps: { - icon: "fa-brands fa-youtube", - internal: true, - }, - }, - { - label: " ", - href: "https://pris.ly/whatsapp", - customProps: { - icon: "fa-brands fa-whatsapp", - internal: true, + dropdown: "legal", }, }, { - label: " ", - href: "https://github.com/prisma", + label: "Security & Compliance", + href: "https://trust.prisma.io/", + target: "_self", customProps: { - icon: "fa-brands fa-github", internal: true, }, }, @@ -472,6 +511,11 @@ const config: Config = { line: "highlight-next-line", block: { start: "highlight-start", end: "highlight-end" }, }, + { + className: "theme-code-block-stronger-line stronger-line", + line: "stronger-next-line", + block: { start: "stronger-start", end: "stronger-end" }, + }, ], }, } satisfies Preset.ThemeConfig, diff --git a/package-lock.json b/package-lock.json index 8685447cc7..0ae1929490 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,10 @@ "name": "docs", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.4.0", - "@docusaurus/preset-classic": "^3.4.0", + "@docusaurus/core": "^3.5.2", + "@docusaurus/preset-classic": "^3.5.2", "@mdx-js/react": "^3.0.0", - "@react-aria/overlays": "^3.22.1", + "@react-aria/overlays": "^3.23.2", "@react-aria/tooltip": "^3.7.4", "@react-aria/utils": "^3.24.1", "clsx": "^2.1.1", @@ -24,15 +24,15 @@ "remark-frontmatter": "^5.0.0", "remark-lint-no-dead-urls": "^1.1.0", "remark-mdx": "^3.0.1", - "sass": "^1.77.5" + "sass": "^1.78.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.4.0", - "@docusaurus/tsconfig": "^3.4.0", - "@docusaurus/types": "^3.4.0", - "prettier": "3.3.2", - "typescript": "~5.4.5", - "wrangler": "^3.60.2" + "@docusaurus/module-type-aliases": "^3.5.2", + "@docusaurus/tsconfig": "^3.5.2", + "@docusaurus/types": "^3.5.2", + "prettier": "3.3.3", + "typescript": "~5.5.4", + "wrangler": "^3.78.3" }, "engines": { "node": ">=18.0" @@ -42,6 +42,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "license": "MIT", "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", "@algolia/autocomplete-shared": "1.9.3" @@ -51,6 +52,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "license": "MIT", "dependencies": { "@algolia/autocomplete-shared": "1.9.3" }, @@ -62,6 +64,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "license": "MIT", "dependencies": { "@algolia/autocomplete-shared": "1.9.3" }, @@ -74,147 +77,281 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "license": "MIT", "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.3.tgz", - "integrity": "sha512-vRHXYCpPlTDE7i6UOy2xE03zHF2C8MEFjPN2v7fRbqVpcOvAUQK81x3Kc21xyb5aSIpYCjWCZbYZuz8Glyzyyg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz", + "integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==", + "license": "MIT", "dependencies": { - "@algolia/cache-common": "4.23.3" + "@algolia/cache-common": "4.24.0" } }, "node_modules/@algolia/cache-common": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.3.tgz", - "integrity": "sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A==" + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.24.0.tgz", + "integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==", + "license": "MIT" }, "node_modules/@algolia/cache-in-memory": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.3.tgz", - "integrity": "sha512-yvpbuUXg/+0rbcagxNT7un0eo3czx2Uf0y4eiR4z4SD7SiptwYTpbuS0IHxcLHG3lq22ukx1T6Kjtk/rT+mqNg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz", + "integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==", + "license": "MIT", "dependencies": { - "@algolia/cache-common": "4.23.3" + "@algolia/cache-common": "4.24.0" } }, "node_modules/@algolia/client-account": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.3.tgz", - "integrity": "sha512-hpa6S5d7iQmretHHF40QGq6hz0anWEHGlULcTIT9tbUssWUriN9AUXIFQ8Ei4w9azD0hc1rUok9/DeQQobhQMA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.24.0.tgz", + "integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==", + "license": "MIT", "dependencies": { - "@algolia/client-common": "4.23.3", - "@algolia/client-search": "4.23.3", - "@algolia/transporter": "4.23.3" + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-account/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-account/node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" } }, "node_modules/@algolia/client-analytics": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.3.tgz", - "integrity": "sha512-LBsEARGS9cj8VkTAVEZphjxTjMVCci+zIIiRhpFun9jGDUlS1XmhCW7CTrnaWeIuCQS/2iPyRqSy1nXPjcBLRA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.24.0.tgz", + "integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==", + "license": "MIT", "dependencies": { - "@algolia/client-common": "4.23.3", - "@algolia/client-search": "4.23.3", - "@algolia/requester-common": "4.23.3", - "@algolia/transporter": "4.23.3" + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" } }, - "node_modules/@algolia/client-common": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.3.tgz", - "integrity": "sha512-l6EiPxdAlg8CYhroqS5ybfIczsGUIAC47slLPOMDeKSVXYG1n0qGiz4RjAHLw2aD0xzh2EXZ7aRguPfz7UKDKw==", + "node_modules/@algolia/client-analytics/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "license": "MIT", "dependencies": { - "@algolia/requester-common": "4.23.3", - "@algolia/transporter": "4.23.3" + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-analytics/node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.4.3.tgz", + "integrity": "sha512-6BoqQ1/Xjwol7kL5Z7TwSphff0mN4pwpydTi6VOkKs7X3piBj6cuJ3FLjHnaVCwMvcaO9hW3gbx+M0u1sYekig==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.3.tgz", - "integrity": "sha512-3E3yF3Ocr1tB/xOZiuC3doHQBQ2zu2MPTYZ0d4lpfWads2WTKG7ZzmGnsHmm63RflvDeLK/UVx7j2b3QuwKQ2g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.24.0.tgz", + "integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-personalization/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "license": "MIT", "dependencies": { - "@algolia/client-common": "4.23.3", - "@algolia/requester-common": "4.23.3", - "@algolia/transporter": "4.23.3" + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" } }, "node_modules/@algolia/client-search": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.3.tgz", - "integrity": "sha512-P4VAKFHqU0wx9O+q29Q8YVuaowaZ5EM77rxfmGnkHUJggh28useXQdopokgwMeYw2XUht49WX5RcTQ40rZIabw==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.4.3.tgz", + "integrity": "sha512-SJ2ofwdyknkwfSXQi7xvrOR93lNxjsgS1+vOdOkOF1t6HgWxnPXHZoP2hUSsrKExSQWmeE7UUbpvhHZkFxGLeA==", + "license": "MIT", + "peer": true, "dependencies": { - "@algolia/client-common": "4.23.3", - "@algolia/requester-common": "4.23.3", - "@algolia/transporter": "4.23.3" + "@algolia/client-common": "5.4.3", + "@algolia/requester-browser-xhr": "5.4.3", + "@algolia/requester-fetch": "5.4.3", + "@algolia/requester-node-http": "5.4.3" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/events": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", - "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==", + "license": "MIT" }, "node_modules/@algolia/logger-common": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.3.tgz", - "integrity": "sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g==" + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.24.0.tgz", + "integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==", + "license": "MIT" }, "node_modules/@algolia/logger-console": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.3.tgz", - "integrity": "sha512-8xoiseoWDKuCVnWP8jHthgaeobDLolh00KJAdMe9XPrWPuf1by732jSpgy2BlsLTaT9m32pHI8CRfrOqQzHv3A==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.24.0.tgz", + "integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==", + "license": "MIT", "dependencies": { - "@algolia/logger-common": "4.23.3" + "@algolia/logger-common": "4.24.0" } }, "node_modules/@algolia/recommend": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.3.tgz", - "integrity": "sha512-9fK4nXZF0bFkdcLBRDexsnGzVmu4TSYZqxdpgBW2tEyfuSSY54D4qSRkLmNkrrz4YFvdh2GM1gA8vSsnZPR73w==", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.23.3", - "@algolia/cache-common": "4.23.3", - "@algolia/cache-in-memory": "4.23.3", - "@algolia/client-common": "4.23.3", - "@algolia/client-search": "4.23.3", - "@algolia/logger-common": "4.23.3", - "@algolia/logger-console": "4.23.3", - "@algolia/requester-browser-xhr": "4.23.3", - "@algolia/requester-common": "4.23.3", - "@algolia/requester-node-http": "4.23.3", - "@algolia/transporter": "4.23.3" + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.24.0.tgz", + "integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==", + "license": "MIT", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/requester-browser-xhr": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", + "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/requester-node-http": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", + "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.3.tgz", - "integrity": "sha512-jDWGIQ96BhXbmONAQsasIpTYWslyjkiGu0Quydjlowe+ciqySpiDUrJHERIRfELE5+wFc7hc1Q5hqjGoV7yghw==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.4.3.tgz", + "integrity": "sha512-XgxyUzUQei5MDNkjss5ioID00sRkazgYAojZpz8B1gNvWaSx/FQd/7MlVoi4HBtSJNi1pkgpsVGGlMp6nTZdyA==", + "license": "MIT", + "peer": true, "dependencies": { - "@algolia/requester-common": "4.23.3" + "@algolia/client-common": "5.4.3" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-common": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.3.tgz", - "integrity": "sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==" + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.24.0.tgz", + "integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==", + "license": "MIT" + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.4.3.tgz", + "integrity": "sha512-Z6VuKQrBd6+TzyL1jsLI1kkoeXTY/g3SR01Z674vTZpdZlimiI9HMMHkgHthtK1speMjfPGDcTggi4TcOxXpMQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.4.3" + }, + "engines": { + "node": ">= 14.0.0" + } }, "node_modules/@algolia/requester-node-http": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.3.tgz", - "integrity": "sha512-zgu++8Uj03IWDEJM3fuNl34s746JnZOWn1Uz5taV1dFyJhVM/kTNw9Ik7YJWiUNHJQXcaD8IXD1eCb0nq/aByA==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.4.3.tgz", + "integrity": "sha512-gNIaj31fFz3pbIM7LiS1iu4/1ZX+lJdWd+UiM9ECaGtZYpkdxxqbfyMHieISVLNsVezOpYgS2BYeKe8d5+se/Q==", + "license": "MIT", + "peer": true, "dependencies": { - "@algolia/requester-common": "4.23.3" + "@algolia/client-common": "5.4.3" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@algolia/transporter": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.3.tgz", - "integrity": "sha512-Wjl5gttqnf/gQKJA+dafnD0Y6Yw97yvfY8R9h0dQltX1GXTgNs1zWgvtWW0tHl1EgMdhAyw189uWiZMnL3QebQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.24.0.tgz", + "integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==", + "license": "MIT", "dependencies": { - "@algolia/cache-common": "4.23.3", - "@algolia/logger-common": "4.23.3", - "@algolia/requester-common": "4.23.3" + "@algolia/cache-common": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/requester-common": "4.24.0" } }, "node_modules/@ampproject/remapping": { @@ -2093,9 +2230,9 @@ } }, "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.2.tgz", - "integrity": "sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz", + "integrity": "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==", "dev": true, "dependencies": { "mime": "^3.0.0" @@ -2117,9 +2254,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20240605.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240605.0.tgz", - "integrity": "sha512-6V4Uze6jEM1mPBdPO6AevPwAOG2s+auEG1vPzZilwbrpn3BbYklEpQqcAZj05uUXaM6rnffnXerW8X8Fc8l4qQ==", + "version": "1.20240909.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240909.0.tgz", + "integrity": "sha512-nJ8jm/6PR8DPzVb4QifNAfSdrFZXNblwIdOhLTU5FpSvFFocmzFX5WgzQagvtmcC9/ZAQyxuf7WynDNyBcoe0Q==", "cpu": [ "x64" ], @@ -2133,9 +2270,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20240605.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240605.0.tgz", - "integrity": "sha512-ZNxjVSeMYUhTfVlrMsVjpN5eHA2kq3+S7ZMsGu5l44ZqFrDygsFDoc9C4anJVUEIHGFUB9LMu4ZTdS5S80hvPQ==", + "version": "1.20240909.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240909.0.tgz", + "integrity": "sha512-gJqKa811oSsoxy9xuoQn7bS0Hr1sY+o3EUORTcEnulG6Kz9NQ6nd8QNdp2Hrk2jmmSqwrNkn+a6PZkWzk6Q0Gw==", "cpu": [ "arm64" ], @@ -2149,9 +2286,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20240605.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240605.0.tgz", - "integrity": "sha512-zqOWDrYEudW5JCcU8lxCFQ96UHJJHrM+uvGaRS4u5nJaEgMr2z7u9I2286+l1R3JWvJdqj9ehGuHQvZkaTADxw==", + "version": "1.20240909.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240909.0.tgz", + "integrity": "sha512-sJrmtccfMg73sZljiBpe4R+lhF58TqzqhF2pQG8HRjyxkzkM1sjpZqfEFaIkNUDqd3/Ibji49fklhPCGXljKSg==", "cpu": [ "x64" ], @@ -2165,9 +2302,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20240605.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240605.0.tgz", - "integrity": "sha512-qFTVNem7bMsU9P1dXUi+kb8EdU5aag1I9RQq6ZLS/zfiJ0a/UasihwQG8lrzT7k9x80VnpyCekNmd625qsVZjQ==", + "version": "1.20240909.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240909.0.tgz", + "integrity": "sha512-dTbSdceyRXPOSER+18AwYRbPQG0e/Dwl2trmfMMCETkfJhNLv1fU3FFMJPjfILijKnhTZHSnHCx0+xwHdon2fg==", "cpu": [ "arm64" ], @@ -2181,9 +2318,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20240605.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240605.0.tgz", - "integrity": "sha512-s0U7d52ALQtb0enbHJ/AXmy+pyBQVoTIaAdAApy/PWrMiAnb8iJhf7A35pRTYfty5SUf7EX9BAPcKmeh+t3N5g==", + "version": "1.20240909.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240909.0.tgz", + "integrity": "sha512-/d4BT0kcWFa7Qc0K4K9+cwVQ1qyPNKiO42JZUijlDlco+TYTPkLO3qGEohmwbfMq+BieK7JTMSgjO81ZHpA0HQ==", "cpu": [ "x64" ], @@ -2196,6 +2333,31 @@ "node": ">=16" } }, + "node_modules/@cloudflare/workers-shared": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-shared/-/workers-shared-0.5.3.tgz", + "integrity": "sha512-Yk5Im7zsyKbzd7qi+DrL7ZJR9+bdZwq9BqZWS4muDIWA8MCUeSLsUC+C9u+jdwfPSi5It2AcQG4f0iwZr6jkkQ==", + "dev": true, + "dependencies": { + "mime": "^3.0.0", + "zod": "^3.22.3" + }, + "engines": { + "node": ">=16.7.0" + } + }, + "node_modules/@cloudflare/workers-shared/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2234,18 +2396,20 @@ } }, "node_modules/@docsearch/css": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", - "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==" + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.1.tgz", + "integrity": "sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==", + "license": "MIT" }, "node_modules/@docsearch/react": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", - "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.1.tgz", + "integrity": "sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==", + "license": "MIT", "dependencies": { "@algolia/autocomplete-core": "1.9.3", "@algolia/autocomplete-preset-algolia": "1.9.3", - "@docsearch/css": "3.6.0", + "@docsearch/css": "3.6.1", "algoliasearch": "^4.19.1" }, "peerDependencies": { @@ -2270,9 +2434,10 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.4.0.tgz", - "integrity": "sha512-g+0wwmN2UJsBqy2fQRQ6fhXruoEa62JDeEa5d8IdTJlMoaDaEDfHh7WjwGRn4opuTQWpjAwP/fbcgyHKlE+64w==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.5.2.tgz", + "integrity": "sha512-4Z1WkhCSkX4KO0Fw5m/Vuc7Q3NxBG53NE5u59Rs96fWkMPZVSrzEPP16/Nk6cWb/shK7xXPndTmalJtw7twL/w==", + "license": "MIT", "dependencies": { "@babel/core": "^7.23.3", "@babel/generator": "^7.23.3", @@ -2284,12 +2449,12 @@ "@babel/runtime": "^7.22.6", "@babel/runtime-corejs3": "^7.22.6", "@babel/traverse": "^7.22.8", - "@docusaurus/cssnano-preset": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "@docusaurus/cssnano-preset": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "autoprefixer": "^10.4.14", "babel-loader": "^9.1.3", "babel-plugin-dynamic-import-node": "^2.3.3", @@ -2350,14 +2515,15 @@ "node": ">=18.0" }, "peerDependencies": { + "@mdx-js/react": "^3.0.0", "react": "^18.0.0", "react-dom": "^18.0.0" } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.4.0.tgz", - "integrity": "sha512-qwLFSz6v/pZHy/UP32IrprmH5ORce86BGtN0eBtG75PpzQJAzp9gefspox+s8IEOr0oZKuQ/nhzZ3xwyc3jYJQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.5.2.tgz", + "integrity": "sha512-D3KiQXOMA8+O0tqORBrTOEQyQxNIfPm9jEaJoALjjSjc2M/ZAWcUfPQEnwr2JB2TadHw2gqWgpZckQmrVWkytA==", "dependencies": { "cssnano-preset-advanced": "^6.1.2", "postcss": "^8.4.38", @@ -2369,9 +2535,10 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.4.0.tgz", - "integrity": "sha512-bZwkX+9SJ8lB9kVRkXw+xvHYSMGG4bpYHKGXeXFvyVc79NMeeBSGgzd4TQLHH+DYeOJoCdl8flrFJVxlZ0wo/Q==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.5.2.tgz", + "integrity": "sha512-LHC540SGkeLfyT3RHK3gAMK6aS5TRqOD4R72BEU/DE2M/TY8WwEUAMY576UUc/oNJXv8pGhBmQB6N9p3pt8LQw==", + "license": "MIT", "dependencies": { "chalk": "^4.1.2", "tslib": "^2.6.0" @@ -2381,13 +2548,14 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.4.0.tgz", - "integrity": "sha512-kSSbrrk4nTjf4d+wtBA9H+FGauf2gCax89kV8SUSJu3qaTdSIKdWERlngsiHaCFgZ7laTJ8a67UFf+xlFPtuTw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.5.2.tgz", + "integrity": "sha512-ku3xO9vZdwpiMIVd8BzWV0DCqGEbCP5zs1iHfKX50vw6jX8vQo0ylYo1YJMZyz6e+JFJ17HYHT5FzVidz2IflA==", + "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "@docusaurus/logger": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -2419,11 +2587,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz", - "integrity": "sha512-A1AyS8WF5Bkjnb8s+guTDuYmUiwJzNrtchebBHpc0gz0PyHJNMaybUlSrmJjHVcGrya0LKI4YcR3lBDQfXRYLw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.5.2.tgz", + "integrity": "sha512-Z+Xu3+2rvKef/YKTMxZHsEXp1y92ac0ngjDiExRdqGTmEKtCUpkbNYH8v5eXo5Ls+dnW88n6WTa+Q54kLOkwPg==", + "license": "MIT", "dependencies": { - "@docusaurus/types": "3.4.0", + "@docusaurus/types": "3.5.2", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2437,18 +2606,20 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.4.0.tgz", - "integrity": "sha512-vv6ZAj78ibR5Jh7XBUT4ndIjmlAxkijM3Sx5MAAzC1gyv0vupDQNhzuFg1USQmQVj3P5I6bquk12etPV3LJ+Xw==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "cheerio": "^1.0.0-rc.12", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.5.2.tgz", + "integrity": "sha512-R7ghWnMvjSf+aeNDH0K4fjyQnt5L0KzUEnUhmf1e3jZrv3wogeytZNN6n7X8yHcMsuZHPOrctQhXWnmxu+IRRg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "cheerio": "1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", "lodash": "^4.17.21", @@ -2463,23 +2634,26 @@ "node": ">=18.0" }, "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", "react": "^18.0.0", "react-dom": "^18.0.0" } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz", - "integrity": "sha512-HkUCZffhBo7ocYheD9oZvMcDloRnGhBMOZRyVcAQRFmZPmNqSyISlXA1tQCIxW+r478fty97XXAGjNYzBjpCsg==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/module-type-aliases": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.5.2.tgz", + "integrity": "sha512-Bt+OXn/CPtVqM3Di44vHjE7rPCEsRCB/DMo2qoOuozB9f7+lsdrHvD0QCHdBs0uhz6deYJDppAr2VgqybKPlVQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/module-type-aliases": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", @@ -2498,15 +2672,16 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.4.0.tgz", - "integrity": "sha512-h2+VN/0JjpR8fIkDEAoadNjfR3oLzB+v1qSXbIAKjQ46JAHx3X22n9nqS+BWSQnTnp1AjkjSvZyJMekmcwxzxg==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.5.2.tgz", + "integrity": "sha512-WzhHjNpoQAUz/ueO10cnundRz+VUtkjFhhaQ9jApyv1a46FPURO4cef89pyNIOMny1fjDz/NUN2z6Yi+5WUrCw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -2520,13 +2695,14 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.4.0.tgz", - "integrity": "sha512-uV7FDUNXGyDSD3PwUaf5YijX91T5/H9SX4ErEcshzwgzWwBtK37nUWPU3ZLJfeTavX3fycTOqk9TglpOLaWkCg==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.5.2.tgz", + "integrity": "sha512-kBK6GlN0itCkrmHuCS6aX1wmoWc5wpd5KJlqQ1FyrF0cLDnvsYSnh7+ftdwzt7G6lGBho8lrVwkkL9/iQvaSOA==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", + "@docusaurus/core": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", "fs-extra": "^11.1.1", "react-json-view-lite": "^1.2.0", "tslib": "^2.6.0" @@ -2540,13 +2716,14 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.4.0.tgz", - "integrity": "sha512-mCArluxEGi3cmYHqsgpGGt3IyLCrFBxPsxNZ56Mpur0xSlInnIHoeLDH7FvVVcPJRPSQ9/MfRqLsainRw+BojA==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.5.2.tgz", + "integrity": "sha512-rjEkJH/tJ8OXRE9bwhV2mb/WP93V441rD6XnM6MIluu7rk8qg38iSxS43ga2V2Q/2ib53PcqbDEJDG/yWQRJhQ==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "@docusaurus/core": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "tslib": "^2.6.0" }, "engines": { @@ -2558,13 +2735,14 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.4.0.tgz", - "integrity": "sha512-Dsgg6PLAqzZw5wZ4QjUYc8Z2KqJqXxHxq3vIoyoBWiLEEfigIs7wHR+oiWUQy3Zk9MIk6JTYj7tMoQU0Jm3nqA==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.5.2.tgz", + "integrity": "sha512-lm8XL3xLkTPHFKKjLjEEAHUrW0SZBSHBE1I+i/tmYMBsjCcUB5UJ52geS5PSiOCFVR74tbPGcPHEV/gaaxFeSA==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "@docusaurus/core": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -2577,13 +2755,14 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.4.0.tgz", - "integrity": "sha512-O9tX1BTwxIhgXpOLpFDueYA9DWk69WCbDRrjYoMQtFHSkTyE7RhNgyjSPREUWJb9i+YUg3OrsvrBYRl64FCPCQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.5.2.tgz", + "integrity": "sha512-QkpX68PMOMu10Mvgvr5CfZAzZQFx8WLlOiUQ/Qmmcl6mjGK6H21WLT5x7xDmcpCoKA/3CegsqIqBR+nA137lQg==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "@docusaurus/core": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "tslib": "^2.6.0" }, "engines": { @@ -2595,16 +2774,17 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.4.0.tgz", - "integrity": "sha512-+0VDvx9SmNrFNgwPoeoCha+tRoAjopwT0+pYO1xAbyLcewXSemq+eLxEa46Q1/aoOaJQ0qqHELuQM7iS2gp33Q==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.5.2.tgz", + "integrity": "sha512-DnlqYyRAdQ4NHY28TfHuVk414ft2uruP4QWCH//jzpHjqvKyXjj2fmDtI8RPUBh9K8iZKFMHRnLtzJKySPWvFA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -2618,23 +2798,24 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.4.0.tgz", - "integrity": "sha512-Ohj6KB7siKqZaQhNJVMBBUzT3Nnp6eTKqO+FXO3qu/n1hJl3YLwVKTWBg28LF7MWrKu46UuYavwMRxud0VyqHg==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/plugin-content-blog": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/plugin-content-pages": "3.4.0", - "@docusaurus/plugin-debug": "3.4.0", - "@docusaurus/plugin-google-analytics": "3.4.0", - "@docusaurus/plugin-google-gtag": "3.4.0", - "@docusaurus/plugin-google-tag-manager": "3.4.0", - "@docusaurus/plugin-sitemap": "3.4.0", - "@docusaurus/theme-classic": "3.4.0", - "@docusaurus/theme-common": "3.4.0", - "@docusaurus/theme-search-algolia": "3.4.0", - "@docusaurus/types": "3.4.0" + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.5.2.tgz", + "integrity": "sha512-3ihfXQ95aOHiLB5uCu+9PRy2gZCeSZoDcqpnDvf3B+sTrMvMTr8qRUzBvWkoIqc82yG5prCboRjk1SVILKx6sg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/plugin-content-blog": "3.5.2", + "@docusaurus/plugin-content-docs": "3.5.2", + "@docusaurus/plugin-content-pages": "3.5.2", + "@docusaurus/plugin-debug": "3.5.2", + "@docusaurus/plugin-google-analytics": "3.5.2", + "@docusaurus/plugin-google-gtag": "3.5.2", + "@docusaurus/plugin-google-tag-manager": "3.5.2", + "@docusaurus/plugin-sitemap": "3.5.2", + "@docusaurus/theme-classic": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/theme-search-algolia": "3.5.2", + "@docusaurus/types": "3.5.2" }, "engines": { "node": ">=18.0" @@ -2645,26 +2826,27 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.4.0.tgz", - "integrity": "sha512-0IPtmxsBYv2adr1GnZRdMkEQt1YW6tpzrUPj02YxNpvJ5+ju4E13J5tB4nfdaen/tfR1hmpSPlTFPvTf4kwy8Q==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/module-type-aliases": "3.4.0", - "@docusaurus/plugin-content-blog": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/plugin-content-pages": "3.4.0", - "@docusaurus/theme-common": "3.4.0", - "@docusaurus/theme-translations": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.5.2.tgz", + "integrity": "sha512-XRpinSix3NBv95Rk7xeMF9k4safMkwnpSgThn0UNQNumKvmcIYjfkwfh2BhwYh/BxMXQHJ/PdmNh22TQFpIaYg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/module-type-aliases": "3.5.2", + "@docusaurus/plugin-content-blog": "3.5.2", + "@docusaurus/plugin-content-docs": "3.5.2", + "@docusaurus/plugin-content-pages": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/theme-translations": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", - "infima": "0.2.0-alpha.43", + "infima": "0.2.0-alpha.44", "lodash": "^4.17.21", "nprogress": "^0.2.0", "postcss": "^8.4.26", @@ -2684,17 +2866,15 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.4.0.tgz", - "integrity": "sha512-0A27alXuv7ZdCg28oPE8nH/Iz73/IUejVaCazqu9elS4ypjiLhK3KfzdSQBnL/g7YfHSlymZKdiOHEo8fJ0qMA==", - "dependencies": { - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/module-type-aliases": "3.4.0", - "@docusaurus/plugin-content-blog": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/plugin-content-pages": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.5.2.tgz", + "integrity": "sha512-QXqlm9S6x9Ibwjs7I2yEDgsCocp708DrCrgHgKwg2n2AY0YQ6IjU0gAK35lHRLOvAoJUfCKpQAwUykB0R7+Eew==", + "license": "MIT", + "dependencies": { + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/module-type-aliases": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2708,23 +2888,25 @@ "node": ">=18.0" }, "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", "react": "^18.0.0", "react-dom": "^18.0.0" } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.4.0.tgz", - "integrity": "sha512-aiHFx7OCw4Wck1z6IoShVdUWIjntC8FHCw9c5dR8r3q4Ynh+zkS8y2eFFunN/DL6RXPzpnvKCg3vhLQYJDmT9Q==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.5.2.tgz", + "integrity": "sha512-qW53kp3VzMnEqZGjakaV90sst3iN1o32PH+nawv1uepROO8aEGxptcq2R5rsv7aBShSRbZwIobdvSYKsZ5pqvA==", + "license": "MIT", "dependencies": { "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/theme-common": "3.4.0", - "@docusaurus/theme-translations": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", + "@docusaurus/core": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/plugin-content-docs": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/theme-translations": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", "algoliasearch": "^4.18.0", "algoliasearch-helper": "^3.13.3", "clsx": "^2.0.0", @@ -2743,9 +2925,10 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.4.0.tgz", - "integrity": "sha512-zSxCSpmQCCdQU5Q4CnX/ID8CSUUI3fvmq4hU/GNP/XoAWtXo9SAVnM3TzpU8Gb//H3WCsT8mJcTfyOk3d9ftNg==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.5.2.tgz", + "integrity": "sha512-GPZLcu4aT1EmqSTmbdpVrDENGR2yObFEX8ssEFYTCiAIVc0EihNSdOIBTazUvgNqwvnoU1A8vIs1xyzc3LITTw==", + "license": "MIT", "dependencies": { "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -2755,15 +2938,17 @@ } }, "node_modules/@docusaurus/tsconfig": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.4.0.tgz", - "integrity": "sha512-0qENiJ+TRaeTzcg4olrnh0BQ7eCxTgbYWBnWUeQDc84UYkt/T3pDNnm3SiQkqPb+YQ1qtYFlC0RriAElclo8Dg==", - "dev": true + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.5.2.tgz", + "integrity": "sha512-rQ7toURCFnWAIn8ubcquDs0ewhPwviMzxh6WpRjBW7sJVCXb6yzwUaY3HMNa0VXCFw+qkIbFywrMTf+Pb4uHWQ==", + "dev": true, + "license": "MIT" }, "node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.5.2.tgz", + "integrity": "sha512-N6GntLXoLVUwkZw7zCxwy9QiuEXIcTVzA9AkmNw16oc0AP3SXLrMmDMMBIfgqwuKWa6Ox6epHol9kMtJqekACw==", + "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", @@ -2781,12 +2966,13 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.4.0.tgz", - "integrity": "sha512-fRwnu3L3nnWaXOgs88BVBmG1yGjcQqZNHG+vInhEa2Sz2oQB+ZjbEMO5Rh9ePFpZ0YDiDUhpaVjwmS+AU2F14g==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.5.2.tgz", + "integrity": "sha512-33QvcNFh+Gv+C2dP9Y9xWEzMgf3JzrpL2nW9PopidiohS1nDcyknKRx2DWaFvyVTTYIkkABVSr073VTj/NITNA==", + "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.4.0", - "@docusaurus/utils-common": "3.4.0", + "@docusaurus/logger": "3.5.2", + "@docusaurus/utils-common": "3.5.2", "@svgr/webpack": "^8.1.0", "escape-string-regexp": "^4.0.0", "file-loader": "^6.2.0", @@ -2819,9 +3005,10 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.4.0.tgz", - "integrity": "sha512-NVx54Wr4rCEKsjOH5QEVvxIqVvm+9kh7q8aYTU5WzUU9/Hctd6aTrcZ3G0Id4zYJ+AeaG5K5qHA4CY5Kcm2iyQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.5.2.tgz", + "integrity": "sha512-i0AZjHiRgJU6d7faQngIhuHKNrszpL/SHQPgF1zH4H+Ij6E9NBYGy6pkcGWToIv7IVPbs+pQLh1P3whn0gWXVg==", + "license": "MIT", "dependencies": { "tslib": "^2.6.0" }, @@ -2838,13 +3025,14 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.4.0.tgz", - "integrity": "sha512-hYQ9fM+AXYVTWxJOT1EuNaRnrR2WGpRdLDQG07O8UOpsvCPWUVOeo26Rbm0JWY2sGLfzAb+tvJ62yF+8F+TV0g==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.5.2.tgz", + "integrity": "sha512-m+Foq7augzXqB6HufdS139PFxDC5d5q2QKZy8q0qYYvGdI6nnlNsGH4cIGsgBnV7smz+mopl3g4asbSDvMV0jA==", + "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", + "@docusaurus/logger": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", @@ -3427,9 +3615,9 @@ } }, "node_modules/@internationalized/date": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.4.tgz", - "integrity": "sha512-qoVJVro+O0rBaw+8HPjUB1iH8Ihf8oziEnqMnvhJUSuVIrHOuZ6eNLHNvzXJKUvAtaDiqMnRlg8Z2mgh09BlUw==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.5.tgz", + "integrity": "sha512-H+CfYvOZ0LTJeeLOqm19E3uj/4YjrmOFtBufDHPfvtI80hFAMqtrp7oCACpe4Cil5l8S0Qu/9dYfZc/5lY8WQQ==", "dependencies": { "@swc/helpers": "^0.5.0" } @@ -3668,78 +3856,78 @@ "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" }, "node_modules/@react-aria/focus": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.17.1.tgz", - "integrity": "sha512-FLTySoSNqX++u0nWZJPPN5etXY0WBxaIe/YuL/GTEeuqUIuC/2bJSaw5hlsM6T2yjy6Y/VAxBcKSdAFUlU6njQ==", + "version": "3.18.2", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.18.2.tgz", + "integrity": "sha512-Jc/IY+StjA3uqN73o6txKQ527RFU7gnG5crEl5Xy3V+gbYp2O5L3ezAo/E0Ipi2cyMbG6T5Iit1IDs7hcGu8aw==", "dependencies": { - "@react-aria/interactions": "^3.21.3", - "@react-aria/utils": "^3.24.1", - "@react-types/shared": "^3.23.1", + "@react-aria/interactions": "^3.22.2", + "@react-aria/utils": "^3.25.2", + "@react-types/shared": "^3.24.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-aria/i18n": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.11.1.tgz", - "integrity": "sha512-vuiBHw1kZruNMYeKkTGGnmPyMnM5T+gT8bz97H1FqIq1hQ6OPzmtBZ6W6l6OIMjeHI5oJo4utTwfZl495GALFQ==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.2.tgz", + "integrity": "sha512-PvEyC6JWylTpe8dQEWqQwV6GiA+pbTxHQd//BxtMSapRW3JT9obObAnb/nFhj3HthkUvqHyj0oO1bfeN+mtD8A==", "dependencies": { - "@internationalized/date": "^3.5.4", + "@internationalized/date": "^3.5.5", "@internationalized/message": "^3.1.4", "@internationalized/number": "^3.5.3", "@internationalized/string": "^3.2.3", - "@react-aria/ssr": "^3.9.4", - "@react-aria/utils": "^3.24.1", - "@react-types/shared": "^3.23.1", + "@react-aria/ssr": "^3.9.5", + "@react-aria/utils": "^3.25.2", + "@react-types/shared": "^3.24.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-aria/interactions": { - "version": "3.21.3", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.21.3.tgz", - "integrity": "sha512-BWIuf4qCs5FreDJ9AguawLVS0lV9UU+sK4CCnbCNNmYqOWY+1+gRXCsnOM32K+oMESBxilAjdHW5n1hsMqYMpA==", + "version": "3.22.2", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.22.2.tgz", + "integrity": "sha512-xE/77fRVSlqHp2sfkrMeNLrqf2amF/RyuAS6T5oDJemRSgYM3UoxTbWjucPhfnoW7r32pFPHHgz4lbdX8xqD/g==", "dependencies": { - "@react-aria/ssr": "^3.9.4", - "@react-aria/utils": "^3.24.1", - "@react-types/shared": "^3.23.1", + "@react-aria/ssr": "^3.9.5", + "@react-aria/utils": "^3.25.2", + "@react-types/shared": "^3.24.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-aria/overlays": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.22.1.tgz", - "integrity": "sha512-GHiFMWO4EQ6+j6b5QCnNoOYiyx1Gk8ZiwLzzglCI4q1NY5AG2EAmfU4Z1+Gtrf2S5Y0zHbumC7rs9GnPoGLUYg==", - "dependencies": { - "@react-aria/focus": "^3.17.1", - "@react-aria/i18n": "^3.11.1", - "@react-aria/interactions": "^3.21.3", - "@react-aria/ssr": "^3.9.4", - "@react-aria/utils": "^3.24.1", - "@react-aria/visually-hidden": "^3.8.12", - "@react-stately/overlays": "^3.6.7", - "@react-types/button": "^3.9.4", - "@react-types/overlays": "^3.8.7", - "@react-types/shared": "^3.23.1", + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.23.2.tgz", + "integrity": "sha512-vjlplr953YAuJfHiP4O+CyrTlr6OaFgXAGrzWq4MVMjnpV/PT5VRJWYFHR0sUGlHTPqeKS4NZbi/xCSgl/3pGQ==", + "dependencies": { + "@react-aria/focus": "^3.18.2", + "@react-aria/i18n": "^3.12.2", + "@react-aria/interactions": "^3.22.2", + "@react-aria/ssr": "^3.9.5", + "@react-aria/utils": "^3.25.2", + "@react-aria/visually-hidden": "^3.8.15", + "@react-stately/overlays": "^3.6.10", + "@react-types/button": "^3.9.6", + "@react-types/overlays": "^3.8.9", + "@react-types/shared": "^3.24.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-aria/ssr": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.4.tgz", - "integrity": "sha512-4jmAigVq409qcJvQyuorsmBR4+9r3+JEC60wC+Y0MZV0HCtTmm8D9guYXlJMdx0SSkgj0hHAyFm/HvPNFofCoQ==", + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.5.tgz", + "integrity": "sha512-xEwGKoysu+oXulibNUSkXf8itW0npHHTa6c4AyYeZIJyRoegeteYuFpZUBPtIDE8RfHdNsSmE1ssOkxRnwbkuQ==", "dependencies": { "@swc/helpers": "^0.5.0" }, @@ -3747,7 +3935,7 @@ "node": ">= 12" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-aria/tooltip": { @@ -3768,45 +3956,45 @@ } }, "node_modules/@react-aria/utils": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.24.1.tgz", - "integrity": "sha512-O3s9qhPMd6n42x9sKeJ3lhu5V1Tlnzhu6Yk8QOvDuXf7UGuUjXf9mzfHJt1dYzID4l9Fwm8toczBzPM9t0jc8Q==", + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.25.2.tgz", + "integrity": "sha512-GdIvG8GBJJZygB4L2QJP1Gabyn2mjFsha73I2wSe+o4DYeGWoJiMZRM06PyTIxLH4S7Sn7eVDtsSBfkc2VY/NA==", "dependencies": { - "@react-aria/ssr": "^3.9.4", - "@react-stately/utils": "^3.10.1", - "@react-types/shared": "^3.23.1", + "@react-aria/ssr": "^3.9.5", + "@react-stately/utils": "^3.10.3", + "@react-types/shared": "^3.24.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-aria/visually-hidden": { - "version": "3.8.12", - "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.12.tgz", - "integrity": "sha512-Bawm+2Cmw3Xrlr7ARzl2RLtKh0lNUdJ0eNqzWcyx4c0VHUAWtThmH5l+HRqFUGzzutFZVo89SAy40BAbd0gjVw==", + "version": "3.8.15", + "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.15.tgz", + "integrity": "sha512-l+sJ7xTdD5Sd6+rDNDaeJCSPnHOsI+BaJyApvb/YcVgHa7rB47lp6TXCWUCDItcPY4JqRGyeByRJVrtzBFTWCw==", "dependencies": { - "@react-aria/interactions": "^3.21.3", - "@react-aria/utils": "^3.24.1", - "@react-types/shared": "^3.23.1", + "@react-aria/interactions": "^3.22.2", + "@react-aria/utils": "^3.25.2", + "@react-types/shared": "^3.24.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-stately/overlays": { - "version": "3.6.7", - "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.7.tgz", - "integrity": "sha512-6zp8v/iNUm6YQap0loaFx6PlvN8C0DgWHNlrlzMtMmNuvjhjR0wYXVaTfNoUZBWj25tlDM81ukXOjpRXg9rLrw==", + "version": "3.6.10", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.10.tgz", + "integrity": "sha512-XxZ2qScT5JPwGk9qiVJE4dtVh3AXTcYwGRA5RsHzC26oyVVsegPqY2PmNJGblAh6Q57VyodoVUyebE0Eo5CzRw==", "dependencies": { - "@react-stately/utils": "^3.10.1", - "@react-types/overlays": "^3.8.7", + "@react-stately/utils": "^3.10.3", + "@react-types/overlays": "^3.8.9", "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-stately/tooltip": { @@ -3823,44 +4011,44 @@ } }, "node_modules/@react-stately/utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.1.tgz", - "integrity": "sha512-VS/EHRyicef25zDZcM/ClpzYMC5i2YGN6uegOeQawmgfGjb02yaCX0F0zR69Pod9m2Hr3wunTbtpgVXvYbZItg==", + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.3.tgz", + "integrity": "sha512-moClv7MlVSHpbYtQIkm0Cx+on8Pgt1XqtPx6fy9rQFb2DNc9u1G3AUVnqA17buOkH1vLxAtX4MedlxMWyRCYYA==", "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-types/button": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.9.4.tgz", - "integrity": "sha512-raeQBJUxBp0axNF74TXB8/H50GY8Q3eV6cEKMbZFP1+Dzr09Ngv0tJBeW0ewAxAguNH5DRoMUAUGIXtSXskVdA==", + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.9.6.tgz", + "integrity": "sha512-8lA+D5JLbNyQikf8M/cPP2cji91aVTcqjrGpDqI7sQnaLFikM8eFR6l1ZWGtZS5MCcbfooko77ha35SYplSQvw==", "dependencies": { - "@react-types/shared": "^3.23.1" + "@react-types/shared": "^3.24.1" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-types/overlays": { - "version": "3.8.7", - "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.7.tgz", - "integrity": "sha512-zCOYvI4at2DkhVpviIClJ7bRrLXYhSg3Z3v9xymuPH3mkiuuP/dm8mUCtkyY4UhVeUTHmrQh1bzaOP00A+SSQA==", + "version": "3.8.9", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.9.tgz", + "integrity": "sha512-9ni9upQgXPnR+K9cWmbYWvm3ll9gH8P/XsEZprqIV5zNLMF334jADK48h4jafb1X9RFnj0WbHo6BqcSObzjTig==", "dependencies": { - "@react-types/shared": "^3.23.1" + "@react-types/shared": "^3.24.1" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-types/shared": { - "version": "3.23.1", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.23.1.tgz", - "integrity": "sha512-5d+3HbFDxGZjhbMBeFHRQhexMFt4pUce3okyRtUVKbbedQFUrtXSBg9VszgF2RTeQDKDkMCIQDtz5ccP/Lk1gw==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.24.1.tgz", + "integrity": "sha512-AUQeGYEm/zDTN6zLzdXolDxz3Jk5dDL7f506F07U8tBwxNNI3WRdhU84G0/AaFikOZzDXhOZDr3MhQMzyE7Ydw==", "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, "node_modules/@react-types/tooltip": { @@ -4309,24 +4497,6 @@ "@types/ms": "*" } }, - "node_modules/@types/eslint": { - "version": "8.56.7", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.7.tgz", - "integrity": "sha512-SjDvI/x3zsZnOkYZ3lCt9lOZWZLB2jIlNKz+LBgCtDurK0JZcwucxYHn1w2BJkD34dgX9Tjnak0txtq4WTggEA==", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -4365,7 +4535,8 @@ "node_modules/@types/gtag.js": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", - "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" + "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==", + "license": "MIT" }, "node_modules/@types/hast": { "version": "3.0.4", @@ -4548,6 +4719,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -4790,10 +4962,10 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "peerDependencies": { "acorn": "^8" } @@ -4877,31 +5049,33 @@ } }, "node_modules/algoliasearch": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.3.tgz", - "integrity": "sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.23.3", - "@algolia/cache-common": "4.23.3", - "@algolia/cache-in-memory": "4.23.3", - "@algolia/client-account": "4.23.3", - "@algolia/client-analytics": "4.23.3", - "@algolia/client-common": "4.23.3", - "@algolia/client-personalization": "4.23.3", - "@algolia/client-search": "4.23.3", - "@algolia/logger-common": "4.23.3", - "@algolia/logger-console": "4.23.3", - "@algolia/recommend": "4.23.3", - "@algolia/requester-browser-xhr": "4.23.3", - "@algolia/requester-common": "4.23.3", - "@algolia/requester-node-http": "4.23.3", - "@algolia/transporter": "4.23.3" + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", + "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", + "license": "MIT", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-account": "4.24.0", + "@algolia/client-analytics": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-personalization": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/recommend": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.21.0.tgz", - "integrity": "sha512-hjVOrL15I3Y3K8xG0icwG1/tWE+MocqBrhW6uVBWpU+/kVEMK0BnM2xdssj6mZM61eJ4iRxHR0djEI3ENOpR8w==", + "version": "3.22.5", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.5.tgz", + "integrity": "sha512-lWvhdnc+aKOKx8jyA3bsdEgHzm/sglC4cYdMG4xSQyRiPLJVJtH/IVYZG3Hp6PkTEhQqhyVYkeP9z2IlcHJsWw==", + "license": "MIT", "dependencies": { "@algolia/events": "^4.0.1" }, @@ -4909,6 +5083,45 @@ "algoliasearch": ">= 3.1 < 6" } }, + "node_modules/algoliasearch/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/requester-browser-xhr": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", + "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/requester-node-http": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", + "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -4983,7 +5196,8 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", @@ -5039,9 +5253,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", - "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", "funding": [ { "type": "opencollective", @@ -5057,11 +5271,11 @@ } ], "dependencies": { - "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001599", + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -5211,9 +5425,9 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -5223,7 +5437,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -5310,9 +5524,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "funding": [ { "type": "opencollective", @@ -5328,10 +5542,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -5461,9 +5675,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001606", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz", - "integrity": "sha512-LPbwnW4vfpJId225pwjZJOgX1m9sGfbw/RKJvw/t0QhYOOaTXHvkjVGFGPpvwEzufrjvTlsULnVTxdy4/6cqkg==", + "version": "1.0.30001660", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", + "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", "funding": [ { "type": "opencollective", @@ -5742,6 +5956,7 @@ "version": "1.0.0-rc.12", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "license": "MIT", "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", @@ -5762,6 +5977,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", @@ -6197,6 +6413,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -6633,6 +6850,16 @@ "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", "dev": true }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -7058,9 +7285,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.729", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.729.tgz", - "integrity": "sha512-bx7+5Saea/qu14kmPTDHQxkp2UnziG3iajUQu3BxFvCOnpAJdDbMV4rSl+EqFDkkpNNVUFlR1kDfpL59xfy1HA==" + "version": "1.5.24", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.24.tgz", + "integrity": "sha512-0x0wLCmpdKFCi9ulhvYZebgcPmHTkFVUfU2wzDykadkslKwT4oAmDTHEKLnlrDsMGZe4B+ksn8quZfZjYsBetA==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -7090,9 +7317,9 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } @@ -7106,9 +7333,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", - "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -7453,36 +7680,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -7518,9 +7745,9 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", @@ -7614,6 +7841,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "license": "MIT", "dependencies": { "xml-js": "^1.6.11" }, @@ -7705,12 +7933,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -8759,6 +8987,7 @@ "url": "https://github.com/sponsors/fb55" } ], + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", @@ -8961,9 +9190,10 @@ } }, "node_modules/infima": { - "version": "0.2.0-alpha.43", - "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.43.tgz", - "integrity": "sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ==", + "version": "0.2.0-alpha.44", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.44.tgz", + "integrity": "sha512-tuRkUSO/lB3rEhLJk25atwAjgLuzq070+pOW8XcvpHky/YbENnRRdPd85IBkyeTgttmOy5ah+yHYsK1HhUd4lQ==", + "license": "MIT", "engines": { "node": ">=12" } @@ -10354,9 +10584,12 @@ "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -12051,11 +12284,11 @@ ] }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -12131,9 +12364,9 @@ } }, "node_modules/miniflare": { - "version": "3.20240605.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240605.0.tgz", - "integrity": "sha512-wE59RULU5zo6eYhL8j3wYdoOQ5istlkMruEr5pYvykL0LJecjKlFc8/cu4WJ5JdkdhutE1320Awi7WEICcolEw==", + "version": "3.20240909.2", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240909.2.tgz", + "integrity": "sha512-rZe7d0GkP02DnsgLD6qT+0K3O1azWCbDQIeHyH7WHJeyfkGPONS8U5FeNJEmus05z+2F6jcMI/Gc/Irc+UFTAA==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "0.8.1", @@ -12143,11 +12376,11 @@ "exit-hook": "^2.2.1", "glob-to-regexp": "^0.4.1", "stoppable": "^1.1.0", - "undici": "^5.28.2", - "workerd": "1.20240605.0", - "ws": "^8.11.0", + "undici": "^5.28.4", + "workerd": "1.20240909.0", + "ws": "^8.17.1", "youch": "^3.2.2", - "zod": "^3.20.6" + "zod": "^3.22.3" }, "bin": { "miniflare": "bootstrap.js" @@ -12157,9 +12390,9 @@ } }, "node_modules/miniflare/node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "engines": { "node": ">=10.0.0" @@ -12288,12 +12521,6 @@ "node": ">=18" } }, - "node_modules/node-fetch-native": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", - "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", - "dev": true - }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -12303,9 +12530,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -12337,7 +12564,8 @@ "node_modules/nprogress": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", - "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==", + "license": "MIT" }, "node_modules/nth-check": { "version": "2.1.1", @@ -12359,9 +12587,12 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12405,6 +12636,12 @@ "odiff": "bin/odiff" } }, + "node_modules/ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -12725,7 +12962,8 @@ "node_modules/parse-numeric-range": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", - "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==", + "license": "ISC" }, "node_modules/parse5": { "version": "7.1.2", @@ -12742,6 +12980,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "license": "MIT", "dependencies": { "domhandler": "^5.0.2", "parse5": "^7.0.0" @@ -12834,9 +13073,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -13582,9 +13821,9 @@ } }, "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -13635,6 +13874,7 @@ "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "license": "MIT", "engines": { "node": ">=6" } @@ -13909,11 +14149,11 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -14193,9 +14433,10 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-json-view-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.4.0.tgz", - "integrity": "sha512-wh6F6uJyYAmQ4fK0e8dSQMEWuvTs2Wr3el3sLD9bambX1+pSWUVXIz1RFaoy3TI1mZ0FqdpKq9YgbgTTgyrmXA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.5.0.tgz", + "integrity": "sha512-nWqA1E4jKPklL2jvHWs6s+7Na0qNgw9HCP6xehdQJeg6nPBTFZgGwyko9Q0oj+jQWKTTVRS30u0toM5wiuL3iw==", + "license": "MIT", "engines": { "node": ">=14" }, @@ -14340,7 +14581,8 @@ "node_modules/reading-time": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", - "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==", + "license": "MIT" }, "node_modules/rechoir": { "version": "0.6.2", @@ -14908,9 +15150,10 @@ "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==" }, "node_modules/rtlcss": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.1.1.tgz", - "integrity": "sha512-/oVHgBtnPNcggP2aVXQjSy6N1mMAfHg4GSag0QtZBlD5bdDgAHwr4pydqJGd+SUCu9260+Pjqbjwtvu7EMH1KQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", + "integrity": "sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==", + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0", @@ -14976,9 +15219,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass": { - "version": "1.77.5", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.5.tgz", - "integrity": "sha512-oDfX1mukIlxacPdQqNb6mV2tVCrnE+P3nVYioy72V5tlk56CPNcO4TCuFcaCRKKfJ1M3lH95CleRS+dVKL2qMg==", + "version": "1.78.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.78.0.tgz", + "integrity": "sha512-AaIqGSrjo5lA2Yg7RvFZrlXDBCp3nV4XP73GrLGvdRWWwk+8H3l0SDvq/5bA4eF+0RFPLuWUk3E+P1U/YqnpsQ==", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -15104,9 +15347,10 @@ } }, "node_modules/search-insights": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.14.0.tgz", - "integrity": "sha512-OLN6MsPMCghDOqlCtsIsYgtsC0pnwVTyT9Mu6A3ewOj1DxvzZF6COrn2g86E/c05xbktB0XN04m/t1Z+n+fTGw==", + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.2.tgz", + "integrity": "sha512-zFNpOpUO+tY2D85KrxJ+aqwnIfdEGi06UH2+xEb+Bp9Mwznmauqc9djbnBibJO5mpfUPPa8st6Sx65+vbeO45g==", + "license": "MIT", "peer": true }, "node_modules/section-matter": { @@ -15183,9 +15427,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -15218,6 +15462,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -15349,14 +15601,14 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -15486,6 +15738,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.2.tgz", "integrity": "sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw==", + "license": "MIT", "dependencies": { "@types/node": "^17.0.5", "@types/sax": "^1.2.1", @@ -15503,7 +15756,8 @@ "node_modules/sitemap/node_modules/@types/node": { "version": "17.0.45", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "license": "MIT" }, "node_modules/skin-tone": { "version": "2.0.0", @@ -15650,6 +15904,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -15796,6 +16051,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -16190,9 +16446,9 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16202,9 +16458,9 @@ } }, "node_modules/ufo": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", - "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", "dev": true }, "node_modules/undici": { @@ -16226,38 +16482,15 @@ }, "node_modules/unenv": { "name": "unenv-nightly", - "version": "1.10.0-1717606461.a117952", - "resolved": "https://registry.npmjs.org/unenv-nightly/-/unenv-nightly-1.10.0-1717606461.a117952.tgz", - "integrity": "sha512-u3TfBX02WzbHTpaEfWEKwDijDSFAHcgXkayUZ+MVDrjhLFvgAJzFGTSTmwlEhwWi2exyRQey23ah9wELMM6etg==", + "version": "2.0.0-1724863496.70db6f1", + "resolved": "https://registry.npmjs.org/unenv-nightly/-/unenv-nightly-2.0.0-1724863496.70db6f1.tgz", + "integrity": "sha512-r+VIl1gnsI4WQxluruSQhy8alpAf1AsLRLm4sEKp3otCyTIVD6I6wHEYzeQnwsyWgaD4+3BD4A/eqrgOpdTzhw==", "dev": true, "dependencies": { - "consola": "^3.2.3", "defu": "^6.1.4", - "mime": "^3.0.0", - "node-fetch-native": "^1.6.4", + "ohash": "^1.1.3", "pathe": "^1.1.2", - "ufo": "^1.5.3" - } - }, - "node_modules/unenv/node_modules/consola": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", - "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", - "dev": true, - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/unenv/node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" + "ufo": "^1.5.4" } }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -16453,9 +16686,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "funding": [ { "type": "opencollective", @@ -16471,8 +16704,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -16788,20 +17021,19 @@ } }, "node_modules/webpack": { - "version": "5.91.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", - "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dependencies": { - "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", "@webassemblyjs/wasm-edit": "^1.12.1", "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", + "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.16.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -17113,9 +17345,9 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" }, "node_modules/workerd": { - "version": "1.20240605.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20240605.0.tgz", - "integrity": "sha512-2yhzgaprAOFm7H988xlRFmU4rOLXhSsq24wh6ayucMB3ORfe/nYJ2ysFn1mzjB+UxEJVt5PhixgHkZLv1S8UPQ==", + "version": "1.20240909.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20240909.0.tgz", + "integrity": "sha512-NwuYh/Fgr/MK0H+Ht687sHl/f8tumwT5CWzYR0MZMHri8m3CIYu2IaY4tBFWoKE/tOU1Z5XjEXECa9zXY4+lwg==", "dev": true, "hasInstallScript": true, "bin": { @@ -17125,33 +17357,36 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20240605.0", - "@cloudflare/workerd-darwin-arm64": "1.20240605.0", - "@cloudflare/workerd-linux-64": "1.20240605.0", - "@cloudflare/workerd-linux-arm64": "1.20240605.0", - "@cloudflare/workerd-windows-64": "1.20240605.0" + "@cloudflare/workerd-darwin-64": "1.20240909.0", + "@cloudflare/workerd-darwin-arm64": "1.20240909.0", + "@cloudflare/workerd-linux-64": "1.20240909.0", + "@cloudflare/workerd-linux-arm64": "1.20240909.0", + "@cloudflare/workerd-windows-64": "1.20240909.0" } }, "node_modules/wrangler": { - "version": "3.60.2", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.60.2.tgz", - "integrity": "sha512-lGIuxzaVm8W0ddzwzwZtx3kL/0PUGMZfKBayUzcMq5wGk88aE9UA2lYeGF51EHVXX2yBbnw7Ltw2eXsx2ixNOQ==", + "version": "3.78.3", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.78.3.tgz", + "integrity": "sha512-IRQ0HCmaVGeQVsW+4kqJfYuA1uBIAtjSCu8/aLRBXzdpiQ+0VSSj/uQ54wBRS08n4twFXTLiPAsYiNVF1aHyyA==", "dev": true, "dependencies": { - "@cloudflare/kv-asset-handler": "0.3.2", + "@cloudflare/kv-asset-handler": "0.3.4", + "@cloudflare/workers-shared": "0.5.3", "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@esbuild-plugins/node-modules-polyfill": "^0.2.2", "blake3-wasm": "^2.1.5", "chokidar": "^3.5.3", + "date-fns": "^3.6.0", "esbuild": "0.17.19", - "miniflare": "3.20240605.0", + "miniflare": "3.20240909.2", "nanoid": "^3.3.3", - "path-to-regexp": "^6.2.0", + "path-to-regexp": "^6.3.0", "resolve": "^1.22.8", "resolve.exports": "^2.0.2", "selfsigned": "^2.0.1", - "source-map": "0.6.1", - "unenv": "npm:unenv-nightly@1.10.0-1717606461.a117952", + "source-map": "^0.6.1", + "unenv": "npm:unenv-nightly@2.0.0-1724863496.70db6f1", + "workerd": "1.20240909.0", "xxhash-wasm": "^1.0.1" }, "bin": { @@ -17165,7 +17400,7 @@ "fsevents": "~2.3.2" }, "peerDependencies": { - "@cloudflare/workers-types": "^4.20240605.0" + "@cloudflare/workers-types": "^4.20240909.0" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { @@ -17563,9 +17798,9 @@ } }, "node_modules/wrangler/node_modules/path-to-regexp": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "dev": true }, "node_modules/wrangler/node_modules/source-map": { @@ -17689,6 +17924,7 @@ "version": "1.6.11", "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", "dependencies": { "sax": "^1.2.4" }, diff --git a/package.json b/package.json index 561fd0b8b5..66ff3b6473 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,10 @@ "format": "prettier --write ." }, "dependencies": { - "@docusaurus/core": "^3.4.0", - "@docusaurus/preset-classic": "^3.4.0", + "@docusaurus/core": "^3.5.2", + "@docusaurus/preset-classic": "^3.5.2", "@mdx-js/react": "^3.0.0", - "@react-aria/overlays": "^3.22.1", + "@react-aria/overlays": "^3.23.2", "@react-aria/tooltip": "^3.7.4", "@react-aria/utils": "^3.24.1", "clsx": "^2.1.1", @@ -32,15 +32,15 @@ "remark-frontmatter": "^5.0.0", "remark-lint-no-dead-urls": "^1.1.0", "remark-mdx": "^3.0.1", - "sass": "^1.77.5" + "sass": "^1.78.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.4.0", - "@docusaurus/tsconfig": "^3.4.0", - "@docusaurus/types": "^3.4.0", - "prettier": "3.3.2", - "typescript": "~5.4.5", - "wrangler": "^3.60.2" + "@docusaurus/module-type-aliases": "^3.5.2", + "@docusaurus/tsconfig": "^3.5.2", + "@docusaurus/types": "^3.5.2", + "prettier": "3.3.3", + "typescript": "~5.5.4", + "wrangler": "^3.78.3" }, "browserslist": { "production": [ diff --git a/sidebars.ts b/sidebars.ts index 9499130022..44118253a9 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -320,6 +320,21 @@ const sidebars: SidebarsConfig = { }, platformCategory, ], + optimizeSidebar: [ + { + type: "category", + label: "Optimize", + collapsible: false, + collapsed: false, + link: { + type: "doc", + id: "optimize/index", + }, + className: "firstTitle", + items: [{ type: "autogenerated", dirName: "700-optimize" }], + }, + platformCategory, + ], platformSidebar: [platformCategory], aboutSidebar: [ { diff --git a/src/components/GettingStarted/index.tsx b/src/components/GettingStarted/index.tsx index e2235cdaa0..7599f86d6b 100644 --- a/src/components/GettingStarted/index.tsx +++ b/src/components/GettingStarted/index.tsx @@ -36,6 +36,21 @@ export const Bolt = ({ color, width, height }: any) => ( ); +export const Inspect = ({ color, width, height }: any) => ( + + + +); + export const SignalStream = ({ color, height, width }: any) => ( { color: "indigo", }, { - text: `Want to to enhance response times while reducing database load?`, + text: `Want to enhance response times while reducing database load?`, link: "https://pris.ly/sidebar-promo/enhance-response-times-reduce-load", color: "teal", }, @@ -71,6 +71,21 @@ export const Promo = () => { link: "https://pris.ly/sidebar-promo/sql-queries-in-orm", color: "teal", }, + { + text: `Tell us how Prisma ORM is working for you!`, + link: "https://pris.ly/orm-survey-5-18", + color: "indigo", + }, + { + text: `Need to improve app performance? Get tailored recommendations.`, + link: "https://pris.ly/sidebar-promo/tailored-recommendations", + color: "teal", + }, + { + text: `Your db queries could be faster? Let Optimize figure out why. `, + link: "https://pris.ly/sidebar-promo/faster-db-queries", + color: "teal", + }, ]; let promo = promoOptions[Math.floor(Math.random() * promoOptions.length)]; diff --git a/src/css/admonition.css b/src/css/admonition.css index 1415bed0e3..b917d7108d 100644 --- a/src/css/admonition.css +++ b/src/css/admonition.css @@ -23,7 +23,7 @@ border-left: 10px solid var(--ifm-alert-border-color); } .alert a { - text-decoration-color: var(--link-color); + text-decoration-color: var(--ifm-link-color); } .alert a:hover { color: var(--ifm-link-hover-color) !important; @@ -118,3 +118,7 @@ .alert > div:last-child > p { margin-top: 8px; } + +.theme-admonition { + margin: 1rem 0; +} diff --git a/src/css/all.css b/src/css/all.css index a552f676da..4c09f29c31 100644 --- a/src/css/all.css +++ b/src/css/all.css @@ -761,6 +761,14 @@ content: "\e473"; } +.fa-magnifying-glass-chart::before { + content: "\e522"; +} + +.fa-message-bot::before { + content: "\e3b8"; +} + .fa-chevron-down::before { content: "\f078"; } diff --git a/src/css/custom.css b/src/css/custom.css index c966dfd8bf..2dd83da4a1 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -16,13 +16,13 @@ header { } } -details:has(summary)>div>div { +details:has(summary) > div > div { margin-top: 0 !important; padding-top: 0 !important; border-top: none !important; } -details>summary::before { +details > summary::before { --docusaurus-details-decoration-color: var(--ifm-alert-border-color) !important; } @@ -102,7 +102,7 @@ pre { background: none; } -.theme-doc-sidebar-item-category-level-1>.menu__list { +.theme-doc-sidebar-item-category-level-1 > .menu__list { border-left: none; padding-left: 0; } @@ -112,7 +112,7 @@ pre { margin-bottom: 0.75rem; } -.theme-doc-sidebar-item-category-level-2>.menu__list-item-collapsible>.menu__link { +.theme-doc-sidebar-item-category-level-2 > .menu__list-item-collapsible > .menu__link { font-weight: bold; font-size: 0.75rem; line-height: 0.875rem; @@ -123,12 +123,12 @@ pre { margin-top: 8px; } -.theme-doc-sidebar-item-category-level-2>ul { +.theme-doc-sidebar-item-category-level-2 > ul { border-left: none; } -.menu__list-item-collapsible>a:not([href]), -.firstTitle>div>a { +.menu__list-item-collapsible > a:not([href]), +.firstTitle > div > a { font-size: 1.125rem; font-weight: 600; letter-spacing: -0.01em; @@ -171,7 +171,7 @@ pre { position: relative; } -.theme-doc-toc-mobile>button::after { +.theme-doc-toc-mobile > button::after { background-position: center; background-repeat: no-repeat; background-size: contain; @@ -202,7 +202,11 @@ pre { background-color: transparent; } -.theme-doc-sidebar-item-category-level-1>ul>.menu__list-item>.menu__list-item-collapsible>a::before { +.theme-doc-sidebar-item-category-level-1 + > ul + > .menu__list-item + > .menu__list-item-collapsible + > a::before { content: none; } @@ -252,10 +256,10 @@ pre { } a { - color: var(--link-color); + color: var(--ifm-link-color); } -.theme-doc-markdown>*:not(.top-section) a { +.theme-doc-markdown > *:not(.top-section) a { text-decoration: underline; } @@ -408,6 +412,7 @@ table { table code { color: var(--main-font-color); line-height: 24px; + word-break: break-word; } table * { @@ -440,6 +445,7 @@ table td { border-right: none; border-left: none; padding: 12px; + line-height: 24px; vertical-align: top; } @@ -527,13 +533,13 @@ hr { position: relative; } - .navbar__items--right> :last-child { + .navbar__items--right > :last-child { left: 0; z-index: 1; top: calc(100% + 24px); } - .navbar__items--right> :last-child>* { + .navbar__items--right > :last-child > * { width: 100%; } @@ -561,7 +567,6 @@ hr { } @media (max-width: 996px) { - /* .logo-link { top: -60px; left: 119px; @@ -656,11 +661,11 @@ hr { color: rgb(113, 128, 150) !important; } -.breadcrumbs__item>.breadcrumbs__link:hover { +.breadcrumbs__item > .breadcrumbs__link:hover { background: none; } -.breadcrumbs__item--active>.breadcrumbs__link { +.breadcrumbs__item--active > .breadcrumbs__link { background: none; padding: 0; } @@ -691,14 +696,14 @@ hr { filter: none; } -.breadcrumbs__item[itemscope]>.breadcrumbs__link:hover { +.breadcrumbs__item[itemscope] > .breadcrumbs__link:hover { text-decoration: underline; background: none; cursor: pointer; color: rgb(74, 85, 104) !important; } -.breadcrumbs__link>svg { +.breadcrumbs__link > svg { top: 4px; } @@ -734,7 +739,11 @@ hr { } } -.internal>i { +.footer__item .fa-brands { + font-size: 24px !important; +} + +.internal > i { display: none; } @@ -748,60 +757,6 @@ hr { height: 28px; } -.footer__col:last-child { - position: absolute; - height: var(--footer-bottom-height); - display: flex; - align-items: center; - justify-content: flex-end; - padding: 0; - width: auto; - top: calc(100% + 100px); - left: 0; -} - -@media (min-width: 520px) { - .footer__col:last-child { - top: calc(100% + 20px); - right: 0; - left: unset; - } -} - -@media (min-width: 768px) { - .footer__col:last-child { - top: calc(100% + 80px); - } -} - -@media (min-width: 1040px) { - .footer__col:last-child { - top: calc(100% + 120px); - } -} - -.footer__col:last-child>.footer__title { - display: none; -} - -.footer__col:last-child>ul { - display: flex; - gap: 20px; - font-size: 1.375rem; - color: white; -} - -.footer__col:last-child .footer__item a { - font-size: 1.375rem; - color: white; -} - -.footer__col:last-child, -.footer__item a:hover { - color: var(--indigo-link-color); - text-decoration: none; -} - .footer__copyright { text-align: left; font-size: 1.125rem; @@ -880,10 +835,11 @@ hr { /* TABS */ .tabs-container { width: fit-content; + margin: 1rem 0; max-width: 100%; } -.tabs-container>div { +.tabs-container > div { padding: 32px; margin-top: 0 !important; background-color: var(--main-bgd-color); @@ -901,15 +857,14 @@ hr { width: auto; } -.tabs-container>div:has(.code-children) { +.tabs-container > div:has(.code-children) { padding: 0; } -:root[data-theme="light"] .tabs-container>div { +:root[data-theme="light"] .tabs-container > div { border-color: #e2e8f0; } - .tabs-container p { margin: 0; } @@ -928,6 +883,7 @@ hr { -webkit-box-align: center; align-items: center; display: flex; + --ifm-tabs-color-active: #fff; } .tabs__item:hover { @@ -955,7 +911,7 @@ hr { line-height: 0; } -.table-of-contents>li { +.table-of-contents > li { padding-top: 1.25rem; } @@ -999,7 +955,7 @@ hr { .table-of-contents__link { text-decoration: none; - color: rgb(113, 128, 150); + color: var(--table-of-contents-link); font-size: 0.875rem; line-height: 1rem; display: inline; @@ -1009,12 +965,6 @@ hr { transition: background-size 0.7s ease 0s; } -@media (prefers-color-scheme: dark) { - .table-of-contents__link { - color: rgb(160, 174, 192); - } -} - .table-of-contents__link--active { background-size: 100% 2px; } @@ -1040,7 +990,7 @@ hr { color: var(--ifm-color-content); } -.theme-doc-markdown>p { +.theme-doc-markdown > p { color: var(--ifm-color-content); } @@ -1052,13 +1002,13 @@ hr { } @media (max-width: 996px) { - .navbar-sidebar__brand>.margin-right--md { + .navbar-sidebar__brand > .margin-right--md { margin-left: auto; } } @media (max-width: 996px) { - .navbar-sidebar__brand>.navbar-sidebar__close { + .navbar-sidebar__brand > .navbar-sidebar__close { margin-left: unset; } } @@ -1085,21 +1035,32 @@ hr { color: white !important; } -:root[data-theme="light"] .table-of-contents__link:hover, -:root[data-theme="light"] .table-of-contents__link:hover code { +:root[data-theme="light"] .table-of-contents__link:hover { color: rgb(26, 32, 44) !important; } -:root[data-theme="dark"] .table-of-contents__link:hover, -:root[data-theme="dark"] .table-of-contents__link:hover code { +:root[data-theme="dark"] .table-of-contents__link:hover { color: #f7fafc !important; } -.table-of-contents__link--active code { +.table-of-contents__link.table-of-contents__link--active code { + color: white; + background: var(--dark-color); +} + +.table-of-contents__link.table-of-contents__link--active:hover code { color: white; background: var(--dark-color); } +.table-of-contents__link:hover code { + color: var(--menu-link-code); +} + +.table-of-contents__link code { + color: var(--menu-link-code); +} + .pagination-nav__label { color: var(--main-font-color); } @@ -1145,6 +1106,7 @@ hr { justify-content: space-between; align-items: start; flex-direction: column; + margin-bottom: 2rem; } @media (min-width: 996px) { @@ -1153,8 +1115,8 @@ hr { } } -.theme-doc-markdown>h1, -.theme-doc-markdown>header>h1 { +.theme-doc-markdown > h1, +.theme-doc-markdown > header > h1 { font-family: Barlow, system-ui, Arial, sans-serif; font-style: normal; font-weight: bold; @@ -1290,12 +1252,12 @@ hr { } } -.DocSearch .DocSearch-HitsFooter>a { +.DocSearch .DocSearch-HitsFooter > a { display: none; } .select-container { - >div:first-child { + > div:first-child { height: 38px; border-color: #e2e8f0; border-radius: 5px; @@ -1324,13 +1286,13 @@ article h6 { position: relative; } -[data-collapsed]>* { +[data-collapsed] > * { padding-left: 2rem !important; color: var(--ifm-alert-color); font-weight: 600; } -[data-collapsed]>summary::before { +[data-collapsed] > summary::before { left: 16px !important; top: 0.25rem !important; } @@ -1345,22 +1307,17 @@ article h6 { border-radius: 5px; } -.language-terminal code>* { +.language-terminal code > * { position: relative; - margin-left: 16px; width: fit-content; } -.language-terminal code>*::before { +.language-terminal code > *::before { position: absolute; content: "$"; left: var(--ifm-pre-padding); } -.language-terminal code .token { - margin-left: var(--ifm-pre-padding); -} - code { font-variant: no-common-ligatures no-discretionary-ligatures no-historical-ligatures no-contextual; vertical-align: baseline; @@ -1419,7 +1376,8 @@ code { font-weight: 600; } - .navbar-sidebar__items:not(.navbar-sidebar__items--show-secondary) .menu__link:not(.menu__link--active) { + .navbar-sidebar__items:not(.navbar-sidebar__items--show-secondary) + .menu__link:not(.menu__link--active) { font-family: Inter; font-size: 14px; font-weight: 600; @@ -1437,7 +1395,7 @@ code { font-size: 16px !important; } - .navbar-sidebar__items>.menu:first-child .menu__link { + .navbar-sidebar__items > .menu:first-child .menu__link { padding: 8px; } @@ -1449,8 +1407,8 @@ code { margin-top: 0 !important; } - .menu__list-item-collapsible>a:not([href]), - .firstTitle>div>a { + .menu__list-item-collapsible > a:not([href]), + .firstTitle > div > a { font-size: 20px !important; } @@ -1547,4 +1505,4 @@ code { border-color: #c3dafe; color: #c3dafe; } -} \ No newline at end of file +} diff --git a/src/css/docsearch.css b/src/css/docsearch.css index 79a2f4611c..552436c0f8 100644 --- a/src/css/docsearch.css +++ b/src/css/docsearch.css @@ -14,6 +14,11 @@ color: rgb(49, 130, 206) !important; } +.DocSearch-Cancel { + --docsearch-highlight-color: var(--ifm-font-color-base); + margin: auto 0; +} + .DocSearch-HitsFooter > a { display: none; } @@ -91,7 +96,7 @@ html[data-theme="dark"] { /* Modal */ --docsearch-modal-background: #090a15; /* Search box */ - --docsearch-searchbox-background: var(--ifm-background-color); + --docsearch-searchbox-background: var(--gray-900) !important; --docsearch-searchbox-focus-background: var(--gray-800) !important; /* Hit */ --docsearch-hit-color: var(--ifm-font-color-base); @@ -116,7 +121,7 @@ html[data-theme="dark"] { --docsearch-footer-shadow: 0px -4px 8px 0px #00000033, 0px 1px 0px 0px #494c6a80 inset; --docsearch-modal-shadow: 0px 3px 8px 0px #000309, 1px 1px 0px 0px #2c2e40 inset; --docsearch-muted-color: var(--gray-500); - --docsearch-searchbox-background: var(--ifm-background-color); + --docsearch-searchbox-background: var(--gray-900) !important; --docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 0 2px 2px 0 rgba(3, 4, 9, 0.3); diff --git a/src/css/prism.css b/src/css/prism.css index f4f00fb984..9b4eb1194c 100644 --- a/src/css/prism.css +++ b/src/css/prism.css @@ -48,7 +48,6 @@ pre[class*="language-"].is-terminal ::selection { } @media (prefers-color-scheme: dark) { - code[class*="language-"].is-terminal, pre[class*="language-"].is-terminal, pre[class*="language-"].is-terminal code { @@ -72,17 +71,17 @@ pre[class*="language-"] { overflow: auto; } -pre[class*="language-"]>code { +pre[class*="language-"] > code { padding-bottom: 1em; } -:not(pre)>code[class*="language-"], +:not(pre) > code[class*="language-"], pre[class*="language-"] { background: var(--code-bgd-color) !important; } /* Inline code */ -:not(pre)>code[class*="language-"] { +:not(pre) > code[class*="language-"] { padding: 0.1em; border-radius: 0.3em; white-space: normal; @@ -165,4 +164,4 @@ pre[class*="language-"] { .token.annotation { color: var(--code-token3-color) !important; -} \ No newline at end of file +} diff --git a/src/css/theming.css b/src/css/theming.css index 183d967593..413c315fc5 100644 --- a/src/css/theming.css +++ b/src/css/theming.css @@ -5,6 +5,8 @@ } :root { + --docsearch-searchbox-background: var(--ifm-color-secondary); + --table-of-contents-link: rgb(113, 128, 150); --docsearch-modal-width: 1248px; --ifm-color-primary: #2e8555; --ifm-color-primary-dark: #29784c; @@ -48,7 +50,6 @@ --docusaurus-details-decoration-color: transparent; --ifm-table-stripe-background: transparent; - --ifm-btn-border-color-active: #718096; --ifm-btn-border-color: #e2e8f0; @@ -70,13 +71,14 @@ --community-bgd-color: var(--gray-100); --shadow-card-bg: #fff; --badge-bg-color: rgb(237, 242, 247); - --badge-color: rgb(160, 174, 192); + --badge-color: #4a5568; --main-bgd-color: #f7fafc; --header-bg-color: #ffffff; --selection-bgd-color: #0c344b; --white-color: #ffffff; - --link-color: #3182ce; + --ifm-link-color: #3182ce; + --ifm-menu-color-active: #3182ce; --border-color: #e2e8f0; --code-bgd-color: #f6f8fa; --code-inline-bgd-color: #edf2f7; @@ -91,7 +93,7 @@ --brand-primary: rgb(90, 103, 216); --ifm-hover-overlay: var(--indigo-700); /* Code blocks */ - --code-inner-color: #718096; + --code-inner-color: #a0aec0; --code-token1-color: #d5408c; --code-token2-color: #805ad5; --code-token3-color: #319795; @@ -124,6 +126,7 @@ background-color: var(--white-color); --homepage-header-bg: rgb(247, 250, 252); + --menu-link-code: #4a5568; /* Colors */ --indigo-100: #ebf4ff; --indigo-200: #c3dafe; @@ -160,6 +163,8 @@ /* For readability concerns, you should choose a lighter palette in dark mode. */ /* PRIMITES WITH THEME DEFINED BY TOGGLER */ html[data-theme="dark"] { + --docsearch-searchbox-background: var(--gray-900) !important; + --table-of-contents-link: #a0aec0; --ifm-blockquote-border-color: transparent; --ifm-color-primary: #25c2a0; --ifm-color-primary-dark: #21af90; @@ -194,7 +199,7 @@ html[data-theme="dark"] { --orm-card-bg: var(--gray-900); --grid-border-color: var(--gray-700); --community-bgd-color: var(--gray-900); - --shadow-card-bg: var(--gray-900); + --shadow-card-bg: var(--gray-1000); --badge-color: rgb(247, 250, 252); --badge-bg-color: rgb(45, 55, 72); --ifm-card-background-color: var(--gray-900); @@ -206,8 +211,8 @@ html[data-theme="dark"] { --header-bg-color: #1a202c; --selection-bgd-color: #0c344b; --white-color: #ffffff; - --link-color: #3182ce; - --code-bgd-color: #2d3748; + --ifm-link-color: #43baec; + --code-bgd-color: #1a202c; --code-inline-bgd-color: #2d3748; --list-bullet-color: #a0aec0; --search-highlight-bg-color: #ebf8ff; @@ -222,7 +227,7 @@ html[data-theme="dark"] { --ifm-navbar-background-color: var(--gray-1000); --ifm-navbar-link-color: #e2e8f0; /* Code blocks */ - --code-inner-color: #718096; + --code-inner-color: #4a5568; --code-token1-color: #d5408c; --code-token2-color: #805ad5; --code-token3-color: #319795; @@ -246,13 +251,15 @@ html[data-theme="dark"] { --grey-bg-color: #8fa6b2; --dark-color: rgb(12, 52, 75); --homepage-header-bg: var(--gray-900); + --menu-link-code: #e2e8f0; } /* PRIMITES WITH THEME DEFINED */ @media (prefers-color-scheme: dark) { - /* Theme: Dark OS + Light docs = Light docs */ :root[data-theme="light"] { + --docsearch-searchbox-background: var(--ifm-color-secondary); + --table-of-contents-link: rgb(113, 128, 150); --ifm-color-primary: #2e8555; --ifm-background-color: #fff; --ifm-color-primary-dark: #29784c; @@ -302,13 +309,14 @@ html[data-theme="dark"] { --community-bgd-color: var(--gray-100); --shadow-card-bg: #fff; --badge-bg-color: rgb(237, 242, 247); - --badge-color: rgb(160, 174, 192); + --badge-color: #4a5568; --main-bgd-color: #f7fafc; --header-bg-color: #ffffff; --selection-bgd-color: #0c344b; --white-color: #ffffff; - --link-color: #3182ce; + --ifm-link-color: #3182ce; + --ifm-menu-color-active: #3182ce; --border-color: #e2e8f0; --code-bgd-color: #f6f8fa; --code-inline-bgd-color: #edf2f7; @@ -324,7 +332,7 @@ html[data-theme="dark"] { --brand-primary: rgb(90, 103, 216); --ifm-hover-overlay: var(--indigo-700); /* Code blocks */ - --code-inner-color: #718096; + --code-inner-color: #a0aec0; --code-token1-color: #d5408c; --code-token2-color: #805ad5; --code-token3-color: #319795; @@ -356,6 +364,7 @@ html[data-theme="dark"] { color: var(--main-font-color); background-color: var(--white-color); --homepage-header-bg: rgb(247, 250, 252); + --menu-link-code: #4a5568; /* Colors */ --indigo-100: #ebf4ff; --indigo-200: #c3dafe; @@ -379,6 +388,8 @@ html[data-theme="dark"] { } :root[data-theme="dark"] { + --docsearch-searchbox-background: var(--gray-900) !important; + --table-of-contents-link: #a0aec0; --ifm-color-primary: #25c2a0; --ifm-color-primary-dark: #21af90; --ifm-color-primary-darker: #1fa588; @@ -412,7 +423,7 @@ html[data-theme="dark"] { --orm-card-bg: var(--gray-900); --grid-border-color: var(--gray-700); --community-bgd-color: var(--gray-900); - --shadow-card-bg: var(--gray-900); + --shadow-card-bg: var(--gray-1000); --badge-color: rgb(247, 250, 252); --badge-bg-color: rgb(45, 55, 72); --code-bg: #1a202c; @@ -423,9 +434,10 @@ html[data-theme="dark"] { --header-bg-color: #1a202c; --selection-bgd-color: #0c344b; --white-color: #ffffff; - --link-color: #3182ce; + --ifm-link-color: #43baec; + --ifm-menu-color-active: #43baec; --ifm-link-hover-color: #5196d7; - --code-bgd-color: #2d3748; + --code-bgd-color: #1a202c; --code-inline-bgd-color: #2d3748; --list-bullet-color: #a0aec0; --search-highlight-bg-color: #ebf8ff; @@ -440,7 +452,7 @@ html[data-theme="dark"] { --ifm-navbar-background-color: var(--gray-1000); --ifm-navbar-link-color: #e2e8f0; /* Code blocks */ - --code-inner-color: #718096; + --code-inner-color: #4a5568; --code-token1-color: #d5408c; --code-token2-color: #805ad5; --code-token3-color: #319795; @@ -465,6 +477,7 @@ html[data-theme="dark"] { --dark-color: rgb(12, 52, 75); --homepage-header-bg: var(--gray-900); + --menu-link-code: #e2e8f0; } } @@ -473,4 +486,8 @@ html[data-theme="dark"] { --main-bgd-color: #1a202c; --border-color: #2d3748; --white-color: white; -} \ No newline at end of file +} + +html[data-theme="dark"] .external-link { + fill: pink; +} diff --git a/src/data/indexData.ts b/src/data/indexData.ts index ef62203f13..74922a8d3c 100644 --- a/src/data/indexData.ts +++ b/src/data/indexData.ts @@ -1,34 +1,45 @@ export const ProductLinkData = { porm: { - title: "Build with Prisma ORM", - icon: "database", + title: "Start building with Prisma ORM", + //eyebrow: "Build", description: - "Open source Node.js and TypeScript ORM with an intuitive data model, automated migrations, type-safety, and auto-completion.", + "Node.js and TypeScript ORM with an intuitive data model, automated migrations, type-safety, and auto-completion.

Combine it with Prisma Studio to explore and manipulate your data.", links: [ { - url: "/getting-started", - title: "Getting started", + url: "/orm", + title: "ORM", }, { - url: "https://github.com/prisma/prisma-examples", - title: "Example projects", - external: true, + url: "/orm/tools/prisma-studio", + title: "Studio", + }, + ], + }, + poptimize: { + title: "Optimize your database queries", + //eyebrow: "Fortify", + description: + "Use Prisma Optimize to generate insights and get recommendations to improve your database queries, making your application run faster.", + links: [ + { + url: "/optimize", + title: "Optimize", }, ], }, pdp: { - title: "Grow as your app evolves", - icon: "triangle", + title: "Grow and evolve your application", + //eyebrow: "Grow", description: - "Expand your application capabilities with global database caching, connection pooling, and real-time database subscriptions.", + "Scale your database connections and cache your database results at the edge with Prisma Accelerate.

Add Prisma Pulse to your app to react to database changes with type-safe model subscriptions.", links: [ { - url: "/accelerate/what-is-accelerate", - title: "Prisma Accelerate", + url: "/accelerate", + title: "Accelerate", }, { - url: "/pulse/what-is-pulse", - title: "Prisma Pulse", + url: "/pulse", + title: "Pulse", }, ], }, @@ -36,7 +47,7 @@ export const ProductLinkData = { export const ORMCardLinkData = { components: { - title: "ORM Components", + title: "ORM Components and Reference", description: "Learn about the building blocks of Prisma ORM.", links: [ { @@ -44,52 +55,58 @@ export const ORMCardLinkData = { title: "Prisma Schema", }, { - url: "/orm/tools/prisma-cli", - title: "Prisma CLI", + url: "/orm/reference/prisma-schema-reference", + title: "Schema reference", }, { url: "/orm/prisma-client", title: "Prisma Client", }, { - url: "/orm/tools/prisma-studio", - title: "Prisma Studio", + url: "/orm/reference/prisma-client-reference", + title: "Client API reference", + }, + { + url: "/orm/tools/prisma-cli", + title: "Prisma CLI", + }, + { + url: "/orm/reference/prisma-cli-reference", + title: "Prisma CLI reference", }, { url: "/orm/prisma-migrate", title: "Prisma Migrate", }, + { + url: "/orm/reference/error-reference", + title: "Error message reference", + }, ], }, reference: { - title: "Reference", - description: "Understand the usage and API surface of our products.", + title: "Platform Reference", + description: + "Understand the usage and API surface of our platform products built on top of Prisma ORM.", links: [ - { - url: "/orm/reference/prisma-client-reference", - title: "Client API reference", - }, - { - url: "/orm/reference/prisma-cli-reference", - title: "Prisma CLI reference", - }, - { - url: "/orm/reference/prisma-schema-reference", - title: "Schema reference", - }, { url: "/accelerate/api-reference", title: "Accelerate API reference", }, - { - url: "/orm/reference/error-reference", - title: "Error message reference", - }, + { url: "/pulse/api-reference", title: "Pulse API reference", }, + { + url: "/platform", + title: "Platform", + }, + { + url: "/platform/platform-cli/commands", + title: "Platform CLI commands", + }, ], }, }; @@ -102,11 +119,33 @@ export const ORMGeneralLinkData = [ icon: "fa-solid fa-arrow-right-arrow-left", }, { - title: `Prisma ORM in your stack`, + title: `Adopting Prisma ORM`, + description: "Migrate to Prisma ORM from other ORMs.", + url: "/orm/more/migrating-to-prisma", + icon: "fa-solid fa-download", + }, + { + title: `Deployment guides`, + description: + "Deploy Node.js applications with Prisma Client to platforms like Vercel, AWS Lambda, Netlify and Heroku.", + url: "/orm/prisma-client/deployment", + icon: "fa-solid fa-book", + }, + { + title: `Platform CLI commands`, description: - "Use Prisma ORM to build a GraphQL or REST API, or as part of a fullstack application.", - url: "/orm/overview/prisma-in-your-stack", - icon: "fa-solid fa-server", + "Learn how to access the Platform using the integrated commands in the Prisma CLI.", + url: "/platform/platform-cli/commands", + icon: "fa-solid fa-terminal", + }, +]; + +export const GeneralLinks_Build = [ + { + title: `CRUD`, + description: "How to perform CRUD operations with your generated Prisma Client API. ", + url: "/orm/prisma-client/queries/crud", + icon: "fa-solid fa-arrow-right-arrow-left", }, { title: `Adopting Prisma ORM`, @@ -121,31 +160,50 @@ export const ORMGeneralLinkData = [ url: "/orm/prisma-client/deployment", icon: "fa-solid fa-book", }, +]; + +export const GeneralLinks_Fortify = [ { - title: `Accelerate`, - description: "Set up connection pooling and global caching in your app with Accelerate.", - url: "/accelerate/getting-started", - icon: "fa-solid fa-bolt", + title: `Set up Optimize`, + description: "Start analyzing your queries and generate insights to improve your queries.", + url: "/optimize/getting-started", + icon: "fa-solid fa-magnifying-glass-chart", }, { - title: `Pulse`, - description: "React to changes in your database with Pulse.", - url: "/pulse/getting-started", - icon: "fa-solid fa-signal-stream", + title: `Recommendations`, + description: + "Explore the different recommendations such as indexing issues, excessive data retrieval, and inefficient query patterns.", + url: "/optimize/recommendations", + icon: "fa-solid fa-chart-simple", + }, + { + title: `Prisma AI`, + description: "Understand the recommendations easier by asking our AI follow-up questions.", + url: "/optimize/prisma-ai", + icon: "fa-solid fa-message-bot", }, +]; + +export const GeneralLinks_Grow = [ { - title: `Platform`, + title: `Connection pooling`, description: - "Explore how to use the Platform to easily manage your projects and collaborate within your team.", - url: "/platform/about", - icon: "fa-solid fa-chart-simple", + "Adjust pool size, configure timeouts, and enable autoscaling to improve performance.", + url: "/accelerate/connection-pooling", + icon: "fa-solid fa-bolt", }, { - title: `Platform CLI commands`, + title: `Database caching`, description: - "Learn how to access the Platform using the integrated commands in the Prisma CLI.", - url: "/platform/platform-cli/commands", - icon: "fa-solid fa-terminal", + "How to improve query performance by configuring cache behavior using TTL and SWR.", + url: "/accelerate/caching", + icon: "fa-solid fa-bolt", + }, + { + title: `React to database changes`, + description: "Use Pulse to stream database events to your app in real-time. ", + url: "/pulse/getting-started", + icon: "fa-solid fa-signal-stream", }, ]; @@ -153,49 +211,49 @@ export const DatabaseData = [ { title: "PostgreSQL", icon: "/img/technologies/postgresqlsimple.svg", - darkIcon: "postgresqldark", + darkIcon: "/img/technologies/postgresqldark.svg", url: "/orm/overview/databases/postgresql", }, { title: "MySQL", icon: "/img/technologies/mysqlsimple.svg", - darkIcon: "mysqlsimple", + darkIcon: "/img/technologies/mysqlsimple.svg", url: "/orm/overview/databases/mysql", }, { title: "SQL Server", icon: "/img/technologies/sqlserver.svg", - darkIcon: "sqlserver", + darkIcon: "/img/technologies/sqlserver.svg", url: "/orm/overview/databases/sql-server", }, { title: "SQLite", icon: "/img/technologies/sqlite.svg", - darkIcon: "sqlite", + darkIcon: "/img/technologies/sqlite.svg", url: "/orm/overview/databases/sqlite", }, { title: "MongoDB", icon: "/img/technologies/mongodbsimple.svg", - darkIcon: "mongodbsimple", + darkIcon: "/img/technologies/mongodbsimple.svg", url: "/orm/overview/databases/mongodb", }, { title: "CockroachDB", icon: "/img/technologies/cockroachdb.svg", - darkIcon: "cockroachdbdark", + darkIcon: "/img/technologies/cockroachdbdark.svg", url: "/orm/overview/databases/cockroachdb", }, { title: "PlanetScale", icon: "/img/technologies/planetscale.svg", - darkIcon: "planetscaledark", + darkIcon: "/img/technologies/planetscaledark.svg", url: "/orm/overview/databases/planetscale", }, { title: "MariaDB", icon: "/img/technologies/mariadb.svg", - darkIcon: "mariadbdark", + darkIcon: "/img/technologies/mariadbdark.svg", url: "/orm/overview/databases/mysql", }, ]; diff --git a/src/pages/index.module.scss b/src/pages/index.module.scss index 5c400ceb3d..adbc9152fe 100644 --- a/src/pages/index.module.scss +++ b/src/pages/index.module.scss @@ -106,12 +106,15 @@ } .homepageTopSection { - padding: 64px 12px; background: #f7fafc; display: flex; flex-wrap: wrap; gap: 40px; background: var(--homepage-header-bg); + padding: 64px 12px; + @media (min-width: 768px) { + padding: 24px 12px 64px; + } } .linkGrid { @@ -121,6 +124,7 @@ width: 100%; flex-wrap: wrap; justify-content: space-between; + height: fit-content; a, button { @@ -148,15 +152,31 @@ .productCardsWrapper { max-width: 1240px; width: 100%; - gap: 40px; + gap: 24px; margin: 0 auto; - display: flex; flex-wrap: wrap; + display: grid; + @media (min-width: 768px) { + grid-template-columns: repeat(3, 1fr); + } +} + +h5.eyebrow { + //styleName: HEADINGS/H5; + font-family: "Barlow"; + font-size: 18px; + font-weight: 700; + line-height: 110%; + margin: 0; + text-transform: uppercase; + color: var(--secondary-font-color); + letter-spacing: 0.1em; + text-align: left; } %productCard { display: grid; - grid-template-rows: auto 1fr auto; + grid-template-rows: auto auto 1fr auto; padding: 32px; width: 100%; border-radius: 8px; @@ -173,11 +193,7 @@ } .body { - margin-bottom: 16px; - } - - @media (min-width: 768px) { - width: calc(50% - 20px); + margin-bottom: 32px; } } @@ -210,17 +226,19 @@ } .ormLinkSectionWrapper { - max-width: 1272px; + max-width: 1240px; + width: 100%; + gap: 24px; margin: 0 auto; - padding: 60px 16px 24px; - - h4 { - color: var(--main-font-color); - margin-bottom: 40px; + flex-wrap: wrap; + display: grid; + @media (min-width: 768px) { + grid-template-columns: repeat(3, 1fr); } - - > div { - display: grid; + .ormLinkCol { + display: flex; + justify-content: space-between; + flex-direction: column; gap: 40px; grid-template-columns: 100%; @@ -228,7 +246,7 @@ grid-template-columns: 1fr 1fr; grid-gap: 40px; grid-auto-flow: column; - grid-template-rows: repeat(4, auto); + grid-template-rows: repeat(5, auto); } } } @@ -272,7 +290,7 @@ } .icon { - background: #f7fafc; + background: #fff; } &:hover { @@ -315,7 +333,7 @@ a, button { - color: var(--link-color); + color: var(--ifm-link-color); } } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 5f413bd71f..092f37302c 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -12,11 +12,15 @@ import { ORMGeneralLinkData, ORMCardLinkData, ProductLinkData, + GeneralLinks_Build, + GeneralLinks_Fortify, + GeneralLinks_Grow, } from "@site/src/data/indexData"; import styles from "./index.module.scss"; import useBaseUrl from "@docusaurus/useBaseUrl"; import clsx from "clsx"; +import DarkImg from "../theme/DarkImg"; function HomepageCard({ className, @@ -44,14 +48,19 @@ function HomepageProductCards() {
{Object.keys(ProductLinkData).map((e: keyof typeof ProductLinkData) => { const cardHeader = ( - -
- -
- {ProductLinkData[e].title} -
+ <> +
{ProductLinkData[e].eyebrow}
+ + {ProductLinkData[e].title} + + + ); + const cardBody = ( +
); - const cardBody =
{ProductLinkData[e].description}
; const cardLinks = ProductLinkData[e].links.map((link) => ( {link.title} {link.external ? <>↗ : <>→} @@ -67,6 +76,53 @@ function HomepageProductCards() { ); })}
+
+
+ {GeneralLinks_Build.map((link, index) => ( + +
+ +
+
+
+ {link.title} +
+

{link.description}

+
+ + ))} +
+
+ {GeneralLinks_Fortify.map((link, index) => ( + +
+ +
+
+
+ {link.title} +
+

{link.description}

+
+ + ))} +
+
+ {GeneralLinks_Grow.map((link, index) => ( + +
+ +
+
+
+ {link.title} +
+

{link.description}

+
+ + ))} +
+
); } @@ -145,8 +201,9 @@ function HomepageDatabasesSection() { {DatabaseData.map((e) => (
-
- + {/* */} diff --git a/src/theme/CodeBlock/Line/styles.module.scss b/src/theme/CodeBlock/Line/styles.module.scss index c7780abe70..a4646f4546 100644 --- a/src/theme/CodeBlock/Line/styles.module.scss +++ b/src/theme/CodeBlock/Line/styles.module.scss @@ -45,6 +45,27 @@ the background in custom CSS file due bug https://github.com/facebook/docusaurus position: relative; } +:global(.theme-code-block-stronger-line.theme-code-block-highlighted-line) { + background-color: rgba(0, 0, 0, 0.15); + display: block; + position: relative; +} +:global(.theme-code-block-stronger-line.theme-code-block-added-line) { + background-color: rgba(71, 187, 120, 0.3); + display: block; + position: relative; +} +:global(.theme-code-block-stronger-line.theme-code-block-deleted-line) { + background-color: rgba(229, 62, 62, 0.3); + display: block; + position: relative; +} +:global(.theme-code-block-stronger-line.theme-code-block-edited-line) { + background-color: rgba(10, 104, 255, 0.35); + display: block; + position: relative; +} + .codeLine { display: table-row; counter-increment: line-count; @@ -55,8 +76,8 @@ the background in custom CSS file due bug https://github.com/facebook/docusaurus margin: 0 -16px 0 0; } -.noLineNumbers:not(.code-highlight) { - padding: 0 0 0 calc(var(--ifm-pre-padding)) !important; +.noLineNumbers { + padding: 0 0 0 calc(var(--ifm-pre-padding)); margin: 0; } @@ -84,6 +105,6 @@ the background in custom CSS file due bug https://github.com/facebook/docusaurus .highlightedNumbers { margin: 0 !important; .codeHighlighted { - margin-left: var(--ifm-pre-padding); + margin-left: calc(var(--ifm-pre-padding) + 8.41px); } } diff --git a/src/theme/DarkImg/DarkImg.tsx b/src/theme/DarkImg/DarkImg.tsx new file mode 100644 index 0000000000..866c187058 --- /dev/null +++ b/src/theme/DarkImg/DarkImg.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import styles from "./darkimg.module.scss"; +import clsx from "clsx"; + +export default function DarkImg(props) { + return ( + <> + + + + ); +} diff --git a/src/theme/DarkImg/darkimg.module.scss b/src/theme/DarkImg/darkimg.module.scss new file mode 100644 index 0000000000..13aae3b7fa --- /dev/null +++ b/src/theme/DarkImg/darkimg.module.scss @@ -0,0 +1,16 @@ +[data-theme="light"] { + .lightImg { + display: block; + } + .darkImg { + display: none; + } +} +[data-theme="dark"] { + .lightImg { + display: none; + } + .darkImg { + display: block; + } +} diff --git a/src/theme/DarkImg/index.tsx b/src/theme/DarkImg/index.tsx new file mode 100644 index 0000000000..6ec2e50ab1 --- /dev/null +++ b/src/theme/DarkImg/index.tsx @@ -0,0 +1,3 @@ +import DarkImg from "./DarkImg"; + +export default DarkImg; diff --git a/src/theme/DocBreadcrumbs/index.tsx b/src/theme/DocBreadcrumbs/index.tsx index 925ba9ca68..093c252db7 100644 --- a/src/theme/DocBreadcrumbs/index.tsx +++ b/src/theme/DocBreadcrumbs/index.tsx @@ -1,7 +1,8 @@ import React, { useEffect, useState } from "react"; import clsx from "clsx"; import { ThemeClassNames } from "@docusaurus/theme-common"; -import { useSidebarBreadcrumbs, useHomePageRoute } from "@docusaurus/theme-common/internal"; +import { useHomePageRoute } from "@docusaurus/theme-common/internal"; +import { useSidebarBreadcrumbs } from "@docusaurus/plugin-content-docs/client"; import Link from "@docusaurus/Link"; import { translate } from "@docusaurus/Translate"; import HomeBreadcrumbItem from "@theme/DocBreadcrumbs/Items/Home"; diff --git a/src/theme/DocCard/index.tsx b/src/theme/DocCard/index.tsx index de1ad6c5d6..26afe0fc9f 100644 --- a/src/theme/DocCard/index.tsx +++ b/src/theme/DocCard/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import clsx from "clsx"; import Link from "@docusaurus/Link"; -import { findFirstSidebarItemLink, useDocById } from "@docusaurus/theme-common/internal"; +import { findFirstSidebarItemLink, useDocById } from "@docusaurus/plugin-content-docs/client"; import isInternalUrl from "@docusaurus/isInternalUrl"; import { translate } from "@docusaurus/Translate"; import Heading from "@theme/Heading"; diff --git a/src/theme/DocItem/Content/index.js b/src/theme/DocItem/Content/index.js index ad6bcc8a2b..a8ca055c5d 100644 --- a/src/theme/DocItem/Content/index.js +++ b/src/theme/DocItem/Content/index.js @@ -1,7 +1,7 @@ import React from "react"; import clsx from "clsx"; import { ThemeClassNames } from "@docusaurus/theme-common"; -import { useDoc } from "@docusaurus/theme-common/internal"; +import { useDoc } from "@docusaurus/plugin-content-docs/client"; import Heading from "@theme/Heading"; import MDXContent from "@theme/MDXContent"; import TopSection from "@site/src/components/topSection"; diff --git a/src/theme/DocItem/Metadata/index.tsx b/src/theme/DocItem/Metadata/index.tsx index c8dac95f56..e2ecb866f3 100644 --- a/src/theme/DocItem/Metadata/index.tsx +++ b/src/theme/DocItem/Metadata/index.tsx @@ -1,6 +1,6 @@ import React from "react"; import { PageMetadata } from "@docusaurus/theme-common"; -import { useDoc } from "@docusaurus/theme-common/internal"; +import { useDoc } from "@docusaurus/plugin-content-docs/client"; import type { DocFrontMatter } from "@docusaurus/plugin-content-docs"; @@ -12,12 +12,16 @@ type PrismaDocFrontMatter = DocFrontMatter & { export default function DocItemMetadata(): JSX.Element { const { metadata, frontMatter, assets } = useDoc(); const prismaFrontMatter = frontMatter as PrismaDocFrontMatter; + + const title = prismaFrontMatter.metaTitle ?? prismaFrontMatter.title ?? metadata.title; + const description = prismaFrontMatter.metaDescription ?? metadata.description; + const keywords = prismaFrontMatter.keywords; + const image = assets.image ?? prismaFrontMatter.image; + return ( - + + + + ); } diff --git a/src/theme/DocSidebarItem/Category/index.tsx b/src/theme/DocSidebarItem/Category/index.tsx index d2121d4f9d..a03c805f6b 100644 --- a/src/theme/DocSidebarItem/Category/index.tsx +++ b/src/theme/DocSidebarItem/Category/index.tsx @@ -1,5 +1,10 @@ import React, { useEffect, useMemo, useState } from "react"; import clsx from "clsx"; +import { + isActiveSidebarItem, + findFirstSidebarItemLink, + useDocSidebarItemsExpandedState, +} from "@docusaurus/plugin-content-docs/client"; import { ThemeClassNames, useThemeConfig, @@ -7,12 +12,7 @@ import { Collapsible, useCollapsible, } from "@docusaurus/theme-common"; -import { - isActiveSidebarItem, - findFirstSidebarItemLink, - useDocSidebarItemsExpandedState, - isSamePath, -} from "@docusaurus/theme-common/internal"; +import { isSamePath } from "@docusaurus/theme-common/internal"; import Link from "@docusaurus/Link"; import { translate } from "@docusaurus/Translate"; import useIsBrowser from "@docusaurus/useIsBrowser"; @@ -168,7 +168,7 @@ export default function DocSidebarItemCategory({ } aria-current={isCurrentPage ? "page" : undefined} aria-expanded={collapsible ? !collapsed : undefined} - href={collapsible ? hrefWithSSRFallback ?? "#" : hrefWithSSRFallback} + href={collapsible ? (hrefWithSSRFallback ?? "#") : hrefWithSSRFallback} {...props} > {label} diff --git a/src/theme/DocSidebarItem/Link/index.tsx b/src/theme/DocSidebarItem/Link/index.tsx index 60504ab3b4..9e81e8d221 100644 --- a/src/theme/DocSidebarItem/Link/index.tsx +++ b/src/theme/DocSidebarItem/Link/index.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from "react"; import clsx from "clsx"; +import { isActiveSidebarItem } from "@docusaurus/plugin-content-docs/client"; import { ThemeClassNames } from "@docusaurus/theme-common"; -import { isActiveSidebarItem } from "@docusaurus/theme-common/internal"; import Link from "@docusaurus/Link"; import isInternalUrl from "@docusaurus/isInternalUrl"; import styles from "./styles.module.css"; diff --git a/src/theme/DocSidebarItem/Link/styles.module.css b/src/theme/DocSidebarItem/Link/styles.module.css index b710c75f8b..258abc8477 100644 --- a/src/theme/DocSidebarItem/Link/styles.module.css +++ b/src/theme/DocSidebarItem/Link/styles.module.css @@ -16,7 +16,6 @@ .active { font-weight: 700; - color: rgb(49, 130, 206) !important; } [data-theme="light"] .active:hover { diff --git a/src/theme/Footer/Layout/index.tsx b/src/theme/Footer/Layout/index.tsx index 19efcc5d03..064231f01f 100644 --- a/src/theme/Footer/Layout/index.tsx +++ b/src/theme/Footer/Layout/index.tsx @@ -1,4 +1,4 @@ -import { FooterNewsletterForm } from "@site/src/components/newsletter/FooterNewsletterForm"; +import useBaseUrl from "@docusaurus/useBaseUrl"; import clsx from "clsx"; import React from "react"; @@ -8,18 +8,50 @@ export default function FooterLayout({ style, links, logo, copyright }) { return (