diff --git a/content/800-guides/160-tanstack-start.mdx b/content/800-guides/160-tanstack-start.mdx index 719d3de79e..8906546a7e 100644 --- a/content/800-guides/160-tanstack-start.mdx +++ b/content/800-guides/160-tanstack-start.mdx @@ -4,7 +4,7 @@ metaTitle: 'How to use Prisma ORM and Prisma Postgres with TanStack Start' description: 'Learn how to use Prisma ORM in a TanStack Start app' sidebar_label: 'TanStack Start' image: '/img/guides/prisma-tanstack-start-cover.png' -completion_time: '10 min' +completion_time: '5 min' community_section: true --- @@ -15,329 +15,50 @@ Prisma ORM simplifies database interactions, and [TanStack Start](https://tansta This guide will walk you through integrating Prisma ORM with a Prisma Postgres database in a TanStack Start project from scratch. ## Prerequisites -- [Node.js 18+](https://nodejs.org) +- [Node.js 20+](https://nodejs.org) ## 1. Set up your project To begin, create a new TanStack Start project. -:::note - -For the purpose of this guide, we're using the same setup instructions that you can find in the [TanStart Start docs](https://tanstack.com/start/latest/docs/framework/react/build-from-scratch). - -::: - -In the directory where you'd like to create your project, run the following commands: - -```terminal -mkdir tanstack-start-prisma -cd tanstack-start-prisma -npm init -y -``` - -This will create a new folder called `tanstack-start-prisma`, navigate into it, and initialize a new Node.js project. - -Open the directory in your IDE and create a `tsconfig.json` file with the following configuration: - -```json file=tsconfig.json -{ - "compilerOptions": { - "jsx": "react-jsx", - "moduleResolution": "Bundler", - "module": "ESNext", - "target": "ES2022", - "skipLibCheck": true, - "strictNullChecks": true - } -} -``` - -We also need a `.gitignore` file, so let's set that up now: - -```txt file=.gitignore -node_modules -.env -app/generated -``` - -Next, install TanStack Router and Vinxi, as TanStack Start currently requires them: - -```terminal -npm install @tanstack/react-start @tanstack/react-router vinxi -``` - -We also need React, the Vite React plugin, and TypeScript: - -```terminal -npm install react react-dom -npm install --save-dev @vitejs/plugin-react vite-tsconfig-paths -npm install --save-dev typescript @types/react @types/react-dom -``` - -Update your `package.json` to use Vinxi's CLI. Add `"type": "module"` and modify the scripts to use Vinxi's CLI: - -```json file=package.json -{ - "name": "tanstack-start-prisma", - "version": "1.0.0", - "main": "index.js", - // add-start - "type": "module", - "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" - }, - // add-end - "keywords": [], - "author": "", - "license": "ISC", - "description": "", - "dependencies": { - "@tanstack/react-router": "^1.119.0", - "@tanstack/react-start": "^1.119.0", - "react": "^19.1.0", - "react-dom": "^19.1.0", - "vinxi": "^0.5.6" - }, - "devDependencies": { - "@types/react": "^19.1.2", - "@types/react-dom": "^19.1.3", - "@vitejs/plugin-react": "^4.4.1", - "typescript": "^5.8.3", - "vite-tsconfig-paths": "^5.1.4" - } -} -``` - -Then, create and configure TanStack Start's `app.config.ts` file: - -```typescript file=app.config.ts -import { defineConfig } from '@tanstack/react-start/config' -import tsConfigPaths from 'vite-tsconfig-paths' - -export default defineConfig({ - vite: { - plugins: [ - tsConfigPaths({ - projects: ['./tsconfig.json'], - }), - ], - }, -}) -``` - -For TanStack Start to function, we need 5 files in `~/app/`: - -- `router.tsx` (The router configuration) -- `ssr.tsx` (The server entry point) -- `client.tsx` (The client entry point) -- `routes/__root.tsx` (The root of the app) -- `routes/index.tsx` (The home page) - -You can create them with these commands: - ```terminal -mkdir app -touch app/router.tsx -touch app/ssr.tsx -touch app/client.tsx -mkdir app/routes -touch app/routes/__root.tsx -touch app/routes/index.tsx -``` - -`router.tsx` configures the application's main router with route definitions and settings: - -```typescript file=app/router.tsx -import { createRouter as createTanStackRouter } from '@tanstack/react-router' -import { routeTree } from './routeTree.gen' - -export function createRouter() { - const router = createTanStackRouter({ - routeTree, - scrollRestoration: true, - }) - - return router -} - -declare module '@tanstack/react-router' { - interface Register { - router: ReturnType - } -} -``` - -:::note - -You should be seeing an error about `routeTree.gen.ts` not existing. This is expected. It will be generated when you run TanStack Start for the first time. - -::: - -`ssr.tsx` allows us to know what routes and loaders we need to execute when the user hits a given route: - -```typescript file=app/ssr.tsx -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) -``` - -`client.tsx` initializes the client-side logic to handle routes in the browser: - -```typescript file=app/client.tsx -import { hydrateRoot } from "react-dom/client"; -import { StartClient } from "@tanstack/react-start/client"; -import { createRouter } from "./router"; - -const router = createRouter(); - -hydrateRoot(document, ); -``` - -`routes/__root.tsx` defines the root route and global HTML layout for the entire application: - -```typescript file=app/routes/__root.tsx -import type { ReactNode } from "react"; -import { - Outlet, - createRootRoute, - HeadContent, - Scripts, -} from "@tanstack/react-router"; - -export const Route = createRootRoute({ - head: () => ({ - meta: [ - { - charSet: "utf-8", - }, - { - name: "viewport", - content: "width=device-width, initial-scale=1", - }, - { - title: "Prisma TanStack Start Demo", - }, - ], - }), - component: RootComponent, -}); - -function RootComponent() { - return ( - - - - ); -} - -function RootDocument({ children }: Readonly<{ children: ReactNode }>) { - return ( - - - - - - {children} - - - - ); -} -``` - -`routes/index.tsx` is the home page of the application: - -```typescript file=app/routes/index.tsx -import { createFileRoute } from "@tanstack/react-router"; - -export const Route = createFileRoute("/")({ - component: Home, -}); - -function Home() { - return ( -
-

Posts

-
- ); -} -``` - -Now, run: - -```terminal -npm run dev -``` - -This will generate the `routeTree.gen.ts` file and resolve any routing errors. - -Your file tree should look like this (without `node_modules`): - -``` -. -├── app -│ ├── client.tsx -│ ├── routeTree.gen.ts -│ ├── router.tsx -│ ├── routes -│ │ ├── __root.tsx -│ │ └── index.tsx -│ └── ssr.tsx -├── app.config.ts -├── package-lock.json -├── package.json -└── tsconfig.json -``` - -## 2. Install and Configure Prisma - -### 2.1. Install dependencies - -To get started with Prisma, you'll need to install a few dependencies: - -```terminal -npm install prisma tsx @types/pg --save-dev -npm install @prisma/client @prisma/adapter-pg dotenv pg +npm create @tanstack/start@latest ``` :::info - -If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of `@prisma/adapter-pg`. For more information, see [Database drivers](/orm/overview/databases/database-drivers). - +- *What would you like to name your project?* tanstack-start-prisma +- *Would you like to use Tailwind CSS?* No +- *Select Toolchain* None +- *Select deployment adapter* Nitro +- *What add-ons would you like for your project?* Prisma +- *Would you like any examples?* No +- *Prisma: Database Provider* Prisma PostgresSQL ::: -Once installed, initialize Prisma in your project: +This will create a new folder called `tanstack-start-prisma` and create a new Prisma Postgres +Database for you. The final database connection string will be printed out. -```terminal -npx prisma init --db --output ../app/generated/prisma +```shell +● Database Connection +│ +│ Connection String: +│ +│ postgresql://b4889..... +│ ``` -:::info -You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My __________ Project" -::: +Copy this connection string and set the `DATABASE_URL` variable in `.env.local`: -This will create: +``` +# Database URL for PostgreSQL +DATABASE_URL="postgresql://b4889....." +``` -- A `prisma` directory with a `schema.prisma` file. -- A `prisma.config.ts` file for configuring Prisma -- A Prisma Postgres database. -- A `.env` file containing the `DATABASE_URL` at the project root. -- An `output` directory for the generated Prisma Client as `app/generated/prisma`. +## 2. Configure Prisma -### 2.2. Define your Prisma Schema +### 2.1. Define your Prisma Schema -In `schema.prisma`, create a model for our posts and change the generator to use the [`prisma-client`](/orm/prisma-schema/overview/generators#prisma-client) provider: +In `schema.prisma`, the model for our todos is defined below the generator and datasource blocks: ```prisma file=prisma/schema.prisma generator client { @@ -349,205 +70,94 @@ datasource db { provider = "postgresql" } -//add-start -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] -} - -model Post { - id Int @id @default(autoincrement()) +model Todo { + id Int @id @default(autoincrement()) title String - content String? - published Boolean @default(false) - authorId Int - author User @relation(fields: [authorId], references: [id]) + createdAt DateTime @default(now()) } -//add-end ``` -This creates two models: `User` and `Post`, with a one-to-many relationship between them. - -### 2.3 Add `dotenv` to `prisma.config.ts` - -To get access to the variables in the `.env` file, they can either be loaded by your runtime, or by using `dotenv`. -Include an import for `dotenv` at the top of the `prisma.config.ts` - -```ts -//add-start -import 'dotenv/config' -//add-end -import { defineConfig, env } from 'prisma/config'; -export default defineConfig({ - schema: 'prisma/schema.prisma', - migrations: { - path: 'prisma/migrations', - }, - datasource: { - url: env('DATABASE_URL'), - }, -}); -``` +This creates a `Todo` model that will be pushed to the database -### 2.4. Configure the Prisma Client generator +### 2.2. Configure the Prisma Client generator -Now, run the following command to create the database tables and generate the Prisma Client: +Now, run the following command to create the database tables: ```terminal -npx prisma migrate dev --name init -npx prisma generate +npm run db:seed -- --name init ``` -### 2.5. Seed the database +### 2.3. Seed the database -Let's add some seed data to populate the database with sample users and posts. +Generate the Prisma Client needed for the project; -Create a new file called `seed.ts` in the `prisma/` directory: - -```typescript file=prisma/seed.ts -import { PrismaClient, Prisma } from "../app/generated/prisma/client.js"; -import { PrismaPg } from "@prisma/adapter-pg"; - -const adapter = new PrismaPg({ - connectionString: process.env.DATABASE_URL!, -}); - -const prisma = new PrismaClient({ - adapter, -}); - -const userData: Prisma.UserCreateInput[] = [ - { - name: "Alice", - email: "alice@prisma.io", - posts: { - create: [ - { - title: "Join the Prisma Discord", - content: "https://pris.ly/discord", - published: true, - }, - { - title: "Prisma on YouTube", - content: "https://pris.ly/youtube", - }, - ], - }, - }, - { - name: "Bob", - email: "bob@prisma.io", - posts: { - create: [ - { - title: "Follow Prisma on Twitter", - content: "https://www.twitter.com/prisma", - published: true, - }, - ], - }, - }, -]; -export async function main() { - for (const u of userData) { - await prisma.user.create({ data: u }); - } -} -main(); -``` - -Now, tell Prisma how to run this script by updating your `prisma.config.ts`: - -```ts file=prisma.config.ts -import 'dotenv/config' -import { defineConfig, env } from 'prisma/config'; -export default defineConfig({ - schema: 'prisma/schema.prisma', - migrations: { - path: 'prisma/migrations', -//add-start - seed: `tsx prisma/seed.ts`, -//add-end - }, - datasource: { - url: env('DATABASE_URL'), - }, -}); +```terminal +npm run db:generate ``` -Run the seed script: +Then seed the project with the `seed.ts` file in the `prisma/` directory: ```terminal -npx prisma db seed +npm run db:seed ``` And open Prisma Studio to inspect your data: ```terminal -npx prisma studio +npm run db:studio ``` ## 3. Integrate Prisma into TanStack Start -### 3.1 Create a Prisma Client - -Instead of creating a new Prisma Client instance in each file, create a single instance in a shared file to be used globally. +### 3.1 The Prisma Client -Create a `/lib` directory and a `prisma.ts` file inside it. This file will be used to create and export your Prisma Client instance. +Instead of creating a new Prisma Client instance in each file, TanStack Start has a `db.ts` that +creates a single instance that can be shared globally -Set up the Prisma client like this: +```tsx file=src/db.ts +import { PrismaClient } from './generated/prisma/client.js' -```tsx file=src/lib/prisma.ts -import { PrismaClient } from "../generated/prisma/client.js"; -import { PrismaPg } from "@prisma/adapter-pg"; +import { PrismaPg } from '@prisma/adapter-pg' const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL!, -}); +}) -const prisma = new PrismaClient({ - adapter, -}); +declare global { + var __prisma: PrismaClient | undefined +} -export default prisma; -``` +export const prisma = globalThis.__prisma || new PrismaClient({ adapter }) -:::warning -We recommend using a connection pooler (like [Prisma Accelerate](https://www.prisma.io/accelerate)) to manage database connections efficiently. +if (process.env.NODE_ENV !== 'production') { + globalThis.__prisma = prisma +} +``` -If you choose not to use one, **avoid** instantiating `PrismaClient` globally in long-lived environments. Instead, create and dispose of the client per request to prevent exhausting your database connections. -::: -### 3.2 Fetch users and posts on load +### 3.2 Fetch data on load -First, import the necessary modules. Then, create a server function using the [`createServerFn`](https://tanstack.com/start/latest/docs/framework/react/guide/server-functions) function. This function will fetch the users from the database using the `.findMany()` method. Use the [`include`](/orm/prisma-client/queries/relation-queries#include-a-relation) option to fetch the related posts: +First, import the necessary modules. Then, create a server function using the [`createServerFn`](https://tanstack.com/start/latest/docs/framework/react/guide/server-functions) function. This function will fetch the data from the database using the `.findMany()` method -```typescript file=app/routes/index.tsx +```typescript file=src/routes/index.tsx +import { createFileRoute } from "@tanstack/react-router"; // add-start -import { prisma } from "../lib/prisma"; import { createServerFn } from "@tanstack/react-start"; +import { prisma } from '../db'; // add-end -import { createFileRoute } from "@tanstack/react-router"; export const Route = createFileRoute("/")({ component: Home, }); // add-start -const getUsers = createServerFn({ method: "GET" }).handler(async () => { - return prisma.user.findMany({ - include: { - posts: true, - }, - }); +const getTodos = createServerFn({ method: "GET" }).handler(async () => { + return prisma.todo.findMany(); }); // add-end function Home() { return (
-

Posts

); } @@ -556,31 +166,27 @@ function Home() { TanStack Start allows functions to run on load with loader functions in the [`createFileRoute`](https://tanstack.com/router/latest/docs/framework/react/api/router/createFileRouteFunction) function. Fetch the users and their posts on load with this code: ```typescript file=app/routes/index.tsx -import { prisma } from "../lib/prisma"; -import { createServerFn } from "@tanstack/react-start"; -import { createFileRoute } from "@tanstack/react-router"; +import { createFileRoute } from '@tanstack/react-router'; +import { createServerFn } from '@tanstack/react-start'; +import { prisma } from '../db'; export const Route = createFileRoute("/")({ component: Home, // add-start loader: () => { - return getUsers(); + return getTodos(); }, // add-end }); -const getUsers = createServerFn({ method: "GET" }).handler(async () => { - return prisma.user.findMany({ - include: { - posts: true, - }, - }); +const getTodos = createServerFn({ method: "GET" }).handler(async () => { + return prisma.todo.findMany(); }); function Home() { return (
-

Posts

+

Todos

); } @@ -589,90 +195,70 @@ function Home() { Store the response from the loader in the main component using [`Route.useLoaderData()`](https://tanstack.com/router/latest/docs/framework/react/api/router/useLoaderDataHook): ```typescript file=app/routes/index.tsx -import { prisma } from "../lib/prisma"; import { createServerFn } from "@tanstack/react-start"; import { createFileRoute } from "@tanstack/react-router"; +import { prisma } from '../db'; export const Route = createFileRoute("/")({ component: Home, loader: () => { - return getUsers(); + return getTodos(); }, }); -const getUsers = createServerFn({ method: "GET" }).handler(async () => { - return prisma.user.findMany({ - include: { - posts: true, - }, - }); +const getTodos = createServerFn({ method: "GET" }).handler(async () => { + return prisma.todo.findMany(); }); function Home() { // add-start - const users = Route.useLoaderData(); + const todos = Route.useLoaderData(); // add-end return (
-

Posts

+

Todos

); } ``` -### 3.3 Display the users and posts +### 3.3 Display the todos -Next, you'll update the home page to display the users and posts retrieved from your database. +Next, you'll update the home page to display the data retrieved from your database. -Map over the `users` and display them in a list along with their `posts`: +Map over the `todos` and display them in a list: ```typescript file=app/routes/index.tsx -import { createFileRoute } from "@tanstack/react-router"; -import { createServerFn } from "@tanstack/react-start"; -import prisma from "../../lib/prisma"; +import { createFileRoute } from '@tanstack/react-router'; +import { createServerFn } from '@tanstack/react-start'; +import { prisma } from '../db'; -export const Route = createFileRoute("/")({ - component: Home, - loader: () => { - return getUsers(); - }, +export const Route = createFileRoute('/')({ + component: App, + loader: () => getTodos(), }); -const getUsers = createServerFn({ method: "GET" }).handler(async () => { - return prisma.user.findMany({ - include: { - posts: true, - }, - }); +const getTodos = createServerFn({ method: 'GET' }).handler(async () => { + return prisma.todo.findMany(); }); -function Home() { - const users = Route.useLoaderData(); - +function App() { + const todos = Route.useLoaderData(); + return (
-

Posts

- // add-start
    - {users.map((user) => ( -
  • - {user.name} -
      - {user.posts.map((post) => ( -
    • {post.title}
    • - ))} -
    -
  • + {todos.map(todo => ( +
  • {todo.title}
  • ))}
- // add-end
); } ``` -This setup will display the posts on your page, fetched directly from your database. +This setup will display the todos on your page, fetched directly from your database. ## Next steps @@ -686,4 +272,4 @@ You've successfully integrated Prisma ORM with TanStack Start, creating a seamle ## More info - [Prisma ORM Documentation](/orm/overview/introduction) -- [TanStack Start Documentation](https://tanstack.com/start/latest/docs/framework/react/overview) +- [TanStack Start Documentation](https://tanstack.com/start/latest/docs/framework/react/overview) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 687dafc3fe..128d01fdb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -248,7 +248,6 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.40.0.tgz", "integrity": "sha512-nlr/MMgoLNUHcfWC5Ns2ENrzKx9x51orPc6wJ8Ignv1DsrUmKm0LUih+Tj3J+kxYofzqQIQRU495d4xn3ozMbg==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/client-common": "5.40.0", "@algolia/requester-browser-xhr": "5.40.0", @@ -374,7 +373,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -2315,7 +2313,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2338,7 +2335,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2448,7 +2444,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2870,7 +2865,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3553,7 +3547,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.1.tgz", "integrity": "sha512-FWDk1LIGD5UR5Zmm9rCrXRoxZUgbwuP6FBA7rc50DVfzqDOMkeMe3NyJhOsA2dF0zBE3VbHEIMmTjKwTZJwbaA==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/babel": "3.9.1", "@docusaurus/bundler": "3.9.1", @@ -3630,7 +3623,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/faster/-/faster-3.9.1.tgz", "integrity": "sha512-zJIrIv+R/IN5TTLV9L+SvO3hwz62L6pO/L16k+b2nC3to3Gn01cnEGHL6doTGAezuPwTSmteJl+kzaoOf+znzg==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/types": "3.9.1", "@rspack/core": "^1.5.0", @@ -3759,7 +3751,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.1.tgz", "integrity": "sha512-DyLk9BIA6I9gPIuia8XIL+XIEbNnExam6AHzRsfrEq4zJr7k/DsWW7oi4aJMepDnL7jMRhpVcdsCxdjb0/A9xg==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/core": "3.9.1", "@docusaurus/logger": "3.9.1", @@ -5540,7 +5531,6 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", - "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -6761,7 +6751,6 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -6866,7 +6855,6 @@ "integrity": "sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ==", "hasInstallScript": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.24" @@ -7556,7 +7544,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -7916,7 +7903,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -8002,7 +7988,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -8048,7 +8033,6 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.40.0.tgz", "integrity": "sha512-a9aIL2E3Z7uYUPMCmjMFFd5MWhn+ccTubEvnMy7rOTZCB62dXBJtz0R5BZ/TPuX3R9ocBsgWuAbGWQ+Ph4Fmlg==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/abtesting": "1.6.0", "@algolia/client-abtesting": "5.40.0", @@ -8560,7 +8544,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -9593,7 +9576,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -11162,7 +11144,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -16336,7 +16317,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -17017,7 +16997,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -17921,7 +17900,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -18758,7 +18736,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -18768,7 +18745,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -18824,7 +18800,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/react": "*" }, @@ -18853,7 +18828,6 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -19651,7 +19625,6 @@ "resolved": "https://registry.npmjs.org/sass/-/sass-1.93.2.tgz", "integrity": "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==", "license": "MIT", - "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -20964,8 +20937,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/type-fest": { "version": "2.19.0", @@ -21028,7 +21000,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -21065,7 +21036,6 @@ "integrity": "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.7", @@ -21445,7 +21415,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -21667,7 +21636,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz", "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -22095,7 +22063,6 @@ "dev": true, "hasInstallScript": true, "license": "Apache-2.0", - "peer": true, "bin": { "workerd": "bin/workerd" }, @@ -22362,7 +22329,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" }