diff --git a/.env.schema b/.env.schema index 8772d81..510bfb6 100644 --- a/.env.schema +++ b/.env.schema @@ -27,9 +27,7 @@ GITHUB_CLIENT_SECRET=bitwarden("2bd1b17c-d6bb-44c8-8c8a-b421009ee0d6") # @sensitive @type=string BETTER_AUTH_SECRET=bitwarden("34439671-d4dc-40eb-892a-b421009f3af2") -# PostgreSQL connection string (Neon) — Drizzle ORM, Better Auth adapter, and `db:*` scripts via `varlock run`. -# Use the *pooled* host (`ep-…-pooler.…aws.neon.tech`) for app/runtime. Prefer `sslmode=verify-full`. -# Optional: `&connect_timeout=30` if cold starts still ETIMEDOUT during `next build`. +# Legacy Neon PostgreSQL URL — retained in Bitwarden; unused by app after Turso cutover (Drizzle / Better Auth use TURSO_*). # @docs(https://neon.tech/docs/connect/connection-pooling) # @docs(https://neon.tech/docs/connect/connect-from-any-app) # @sensitive @@ -39,3 +37,15 @@ DATABASE_URL=bitwarden("a33af111-73f0-49a6-9579-b421009ead1e") # @docs("Next.js metadataBase", https://nextjs.org/docs/app/api-reference/functions/generate-metadata#metadatabase) # @type=url(noTrailingSlash=true) NEXT_PUBLIC_SITE_URL="http://localhost:3000" + +# Turso (libSQL) auth token — drizzle-kit / @libsql/client `authToken`. Keep server-only. +# @docs(https://docs.turso.tech/cli/db/tokens/create) +# @docs(https://orm.drizzle.team/docs/connect-turso) +# @sensitive +TURSO_DATABASE_AUTH=bitwarden("50b36813-35ae-4b68-bcfb-b4900011b5aa") + +# Turso database URL (`libsql://…`) — Drizzle ORM, Better Auth adapter, and `db:*` scripts via `varlock run`. +# @docs(https://docs.turso.tech/quickstart) +# @docs(https://orm.drizzle.team/docs/connect-turso) +# @sensitive +TURSO_DATABASE_URL=bitwarden("c71a565f-a617-4dda-a3a1-b49000113ac5") \ No newline at end of file diff --git a/.fallowrc.json b/.fallowrc.json index 8d602ea..8fa5742 100644 --- a/.fallowrc.json +++ b/.fallowrc.json @@ -8,12 +8,7 @@ }, "ignorePatterns": ["doctor.config.ts"], "ignoreDependencies": [ - "@varlock/bitwarden-plugin", - "babel-plugin-react-compiler", "next-devtools-mcp", - "@pandacss/preset-panda", - "@pandacss/types", - "react-doctor", "@styled-system/css", "@styled-system/patterns", "@styled-system/recipes" diff --git a/.gitignore b/.gitignore index 8e3b6ac..55ed96b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ node_modules .vercel .fallow .agents +fallow-viz.html # TypeScript tsconfig.tsbuildinfo diff --git a/README.md b/README.md index 869204d..8cea02e 100644 --- a/README.md +++ b/README.md @@ -4,23 +4,23 @@ A modern web application for browsing and discovering 3D models, built with Next ## 🛠️ Tech Stack -![Next.js](https://img.shields.io/badge/Next.js-16.3.0--canary.90-black?logo=next.js) +![Next.js](https://img.shields.io/badge/Next.js-16.3.0--canary.95-black?logo=next.js) ![React](https://img.shields.io/badge/React-19.3_canary-61DAFB?logo=react) ![TypeScript](https://img.shields.io/badge/TypeScript-7.0.2-3178C6?logo=typescript) -![Panda CSS](https://img.shields.io/badge/Panda_CSS-2.0.0--beta.8-000000) -![Drizzle ORM](https://img.shields.io/badge/Drizzle-1.0.0--rc.4-FFE66D?logo=postgresql) +![Panda CSS](https://img.shields.io/badge/Panda_CSS-2.0.0--beta.10-000000) +![Drizzle ORM](https://img.shields.io/badge/Drizzle-1.0.0--rc.4-FFE66D?logo=sqlite) [![Better Auth](https://img.shields.io/badge/Better%20Auth-1.7.0--rc.1-000000?logo=better-auth&logoColor=white)](https://better-auth.com/) ![Biome](https://img.shields.io/badge/Biome-2.5.3-60A5FA?logo=biome) [![Ultracite](https://img.shields.io/badge/Ultracite-7.9.4-000000?logo=biome&logoColor=60A5FA)](https://github.com/ultracite/ultracite) [![Formatted with Biome](https://img.shields.io/badge/Formatted_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev/) [![Linted with Biome](https://img.shields.io/badge/Linted_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev) -- **Framework**: Next.js 16.3.0-canary.90 with App Router, Cache Components, React Compiler, and typed routes (`typedRoutes`) +- **Framework**: Next.js 16.3.0-canary.95 with App Router, Cache Components, React Compiler, and typed routes (`typedRoutes`) - **Language**: TypeScript 7.0.2 with React 19.3 canary -- **Styling**: Panda CSS 2.0.0-beta.8 (`@pandacss/dev`, `@pandacss/preset-base`, `@pandacss/preset-panda`, `panda.config.ts`, vendored typography preset in `panda-presets/typography.ts`); generated `styled-system/` from `panda build` (gitignored; run via `bun install` / `prepare`); imports use the `@styled-system/*` path alias (`tsconfig.json`); global view transitions and `@layer` rules in `src/app/index.css`; -- **Database**: Neon (PostgreSQL) with Drizzle ORM 1.0.0-rc.4; `pg` pool uses 120s connection/idle timeouts for Neon cold starts -- **Authentication**: Better Auth 1.7.0-rc.1 with email/password and GitHub OAuth, cookie caching enabled, ElysiaJS API backend; Drizzle adapter uses `relations-v2` with experimental joins -- **Search Params**: nuqs 2.9.0 for type-safe URL state (`query`, `page`, `limit`, `sort`); `NuqsAdapterBoundary` scopes the adapter to listing routes inside `Suspense` (not model detail); listing canonical URLs use `nuqs/server` loaders/serializers (`features/pagination/listing-canonical.ts`) with `clearOnDefault` for SEO metadata +- **Styling**: Panda CSS 2.0.0-beta.10 (`@pandacss/dev`, `@pandacss/preset-base`, `@pandacss/preset-panda`, `@pandacss/preset-typography`, `panda.config.ts`); generated `styled-system/` from `panda build` (gitignored; run via `bun install` / `prepare`); imports use the `@styled-system/*` path alias (`tsconfig.json`); `@layer` stack in `src/app/index.css`; view-transition animations colocated via Panda helpers / `ViewTransition` in components +- **Database**: Turso (libSQL / SQLite) with Drizzle ORM 1.0.0-rc.4 (`dialect: "turso"`, `@libsql/client`); legacy Neon `DATABASE_URL` kept in `.env.schema` but unused by the app +- **Authentication**: Better Auth 1.7.0-rc.1 with email/password and GitHub OAuth, cookie caching enabled, ElysiaJS API backend; Drizzle adapter uses `relations-v2` with experimental joins (`provider: "sqlite"`) +- **Search Params**: nuqs 2.9.1 for type-safe URL state (`query`, `page`, `limit`, `sort`); `NuqsAdapterBoundary` scopes the adapter to listing routes inside `Suspense` (not model detail); listing canonical URLs use `nuqs/server` loaders/serializers (`features/pagination/listing-canonical.ts`) with `clearOnDefault` for SEO metadata - **Linting & Formatting**: Biome 2.5.3 with Ultracite 7.9.4 presets (`ultracite/biome/core`, `react`, `next`); [React Doctor](https://github.com/millionco/react-doctor) on PRs and pushes to `main` (`.github/workflows/react-doctor.yml`, pinned actions, `doctor.config.ts`) and on staged TS/TSX via Husky + lint-staged (`type`, `react-doctor:staged`) - **Type Checking**: TypeScript 7 via `tsc` (`bun run type` / `typegen`); Next build uses project-local `tsc` (`experimental.useTypeScriptCli` in `next.config.ts`) because TS 7 has no JS compiler API - **Package Manager**: Bun (install, tests, Drizzle scripts, `prepare`) @@ -46,7 +46,7 @@ A modern web application for browsing and discovering 3D models, built with Next ## 📁 Project Structure -Static assets are served from `public/` at the **repository root** (not under `src/`), including logos, hero images, and `public/img/models/*.jpg` thumbnails referenced by seed data. Supplemental docs live in `docs/` (for example `AUTH_SETUP.md`, `VARLOCK.md`, `PSEUDO_CLASS_TRANSITIONS.md`, `PERFORMANCE_IMPROVEMENTS.md`, `REACT_STINKY.md`). **Panda CSS** writes generated files to **`styled-system/`** at the repo root (`panda.config.ts` → `outdir`); that folder is gitignored—run `bun install` (or `bunx panda build`) so imports like `@styled-system/css` resolve. Root tooling includes `panda-presets/` (vendored typography preset), `doctor.config.ts`, and `.github/workflows/react-doctor.yml` for PR diagnostics. +Static assets are served from `public/` at the **repository root** (not under `src/`), including logos, hero images, and `public/img/models/*.jpg` thumbnails referenced by seed data. Supplemental docs live in `docs/` (for example `AUTH_SETUP.md`, `VARLOCK.md`, `PSEUDO_CLASS_TRANSITIONS.md`, `PERFORMANCE_IMPROVEMENTS.md`, `REACT_STINKY.md`). **Panda CSS** writes generated files to **`styled-system/`** at the repo root (`panda.config.ts` → `outdir`); that folder is gitignored—run `bun install` (or `bunx panda build`) so imports like `@styled-system/css` resolve. Root tooling includes `doctor.config.ts` and `.github/workflows/react-doctor.yml` for PR diagnostics. ``` src/ @@ -91,7 +91,7 @@ src/ │ │ └── [[...slugs]]/ │ │ ├── better-auth-openapi.ts # Better Auth OpenAPI spec for Elysia docs │ │ └── route.ts # ElysiaJS handler mounting Better Auth (`basePath` /api/auth) -│ ├── index.css # Global @layer stack, view-transition animations +│ ├── index.css # Global `@layer` stack (reset → utilities) │ ├── styles.ts # Shared Panda `css` / pattern exports for app shells │ ├── icon.png # App icon (metadata) │ ├── layout.tsx # Root layout @@ -203,6 +203,7 @@ src/ │ ├── form/ │ │ ├── field-errors.tsx │ │ ├── form-error.tsx +│ │ ├── form-field.tsx # Shared labeled field + errors (auth ViewTransitions) │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── reset-button.tsx @@ -235,7 +236,7 @@ src/ │ ├── schema/ │ │ ├── auth.ts │ │ ├── likes.ts -│ │ ├── models.ts # categories + models tables; category_slug pgEnum +│ │ ├── models.ts # categories + models tables (sqlite text enum for category slug) │ │ ├── relations.ts │ │ └── index.ts │ ├── migrations/ # Drizzle SQL migrations (drizzle-kit generate) @@ -248,7 +249,8 @@ src/ │ └── index.ts ├── lib/ │ ├── api.ts -│ ├── auth.ts +│ ├── auth.cli.config.ts # CLI-only Better Auth config for `auth:generate` (no secrets) +│ ├── auth.ts # Runtime Better Auth (`server-only`; secrets + plugins) │ ├── auth-client.ts │ ├── date.ts │ └── hero-image.ts @@ -257,7 +259,10 @@ src/ ├── utils/ │ ├── cache-invalidation.ts │ ├── sanitise-name.ts -│ ├── to-action-state.ts +│ ├── to-action-state/ # Server action result helpers +│ │ ├── form-data-to-safe-payload.ts # Safe FormData → client payload (#38) +│ │ ├── to-action-state.ts +│ │ └── types.ts │ └── try-catch.ts ├── global.d.ts └── proxy.ts @@ -280,7 +285,7 @@ The project follows a feature-based architecture where related functionality is - **`_` prefix**: Private folders that are not part of Next.js routing - **`features/`**: Feature-based modules with their own components and queries - **`components/`**: Shared/generic components used across features -- **`db/categories.ts`**: Source-of-truth category list; drives PostgreSQL `category_slug` enum and Valibot branded slugs in `db/brands.ts` +- **`db/categories.ts`**: Source-of-truth category list; drives SQLite category slug enum values and Valibot branded slugs in `db/brands.ts` - **`db/seed-data/`**: Model seed data only (`models.ts`) ### Performance Optimizations @@ -300,7 +305,7 @@ The project follows a feature-based architecture where related functionality is - [Bun](https://bun.sh/) for package management, tests, and database scripts - A current **Node.js** LTS (used by `next build` / `next start` until `bun --bun` is re-enabled for those scripts) -- Neon database account (or any PostgreSQL database) +- Turso database (`TURSO_DATABASE_URL` + `TURSO_DATABASE_AUTH`); legacy Neon `DATABASE_URL` may remain in Bitwarden unused - Optional: [Bitwarden Secrets Manager](https://bitwarden.com/products/secrets-manager/) machine account token if you use `bitwarden()` resolvers in `.env.schema` (see `docs/VARLOCK.md`) ### Installation @@ -332,7 +337,9 @@ The project follows a feature-based architecture where related functionality is GITHUB_CLIENT_ID="your-github-oauth-client-id" GITHUB_CLIENT_SECRET="your-github-oauth-client-secret" - DATABASE_URL="your-neon-database-connection-string" + DATABASE_URL="legacy-neon-url-unused-by-app" + TURSO_DATABASE_URL="libsql://your-db.turso.io" + TURSO_DATABASE_AUTH="your-turso-auth-token" ``` Run **`bun run env:typegen`** after changing `.env.schema` to refresh **`src/env.d.ts`**. Typed access uses **`import { ENV } from "varlock/env"`**. See **`docs/VARLOCK.md`** and **`docs/AUTH_SETUP.md`** for Bitwarden, Bun, and Vercel notes. @@ -367,7 +374,7 @@ The project follows a feature-based architecture where related functionality is ### Categories Table - `id`: Primary key (auto-increment) - `displayName`: Human-readable category name -- `slug`: PostgreSQL `category_slug` enum (unique); values defined in `src/db/categories.ts` +- `slug`: Category slug text enum (unique); values defined in `src/db/categories.ts` ### Models Table - `slug`: Primary key (text, auto-generated from name) @@ -396,6 +403,7 @@ The project follows a feature-based architecture where related functionality is ### Available Scripts +- `bun run auth:generate` — Regenerate Better Auth Drizzle schema (`src/db/schema/auth.ts` from `src/lib/auth.cli.config.ts`) - `bun run db:generate` — Generate migrations (`varlock run -- bun x drizzle-kit generate`) - `bun run db:migrate` — Run migrations (`varlock run -- bun x drizzle-kit migrate`) - `bun run db:push` — Push schema (`varlock run -- bun x drizzle-kit push --force`) @@ -411,12 +419,12 @@ The application uses Drizzle ORM 1.0.0-rc.4 with `defineRelations` for type-safe ### Query Builder (RQBv2) The application uses Drizzle ORM's Relational Query Builder v2 (RQBv2) for type-safe relational queries: -- **Read queries**: All read queries use RQBv2 syntax (`db.query.tableName.findMany()`, `db.query.tableName.findFirst()`) with object-based `where` clauses, including complex conditions with `OR: []`, `AND: []`, `NOT: {}`, and column filters like `{ column: { eq: value, ilike: pattern } }` for better type safety and developer experience -- **Count queries**: Count queries use `db.$count()` (RQBv2), with where conditions passed using SQL builder syntax (`and()`, `or()`, `ilike()`, etc.) since `$count` accepts SQL builder conditions +- **Read queries**: All read queries use RQBv2 syntax (`db.query.tableName.findMany()`, `db.query.tableName.findFirst()`) with object-based `where` clauses +- **Count / filter queries**: Listing search uses SQL builder (`and()`, `or()`, `like()` + `COLLATE NOCASE`) since SQLite has no `ilike` - **Mutations**: Insert, update, and delete operations use the SQL builder syntax (mutations not yet available in RQBv2) - **Hybrid approach**: The codebase uses a hybrid strategy - RQBv2 object syntax for all read queries (including complex conditions with `AND`/`OR` arrays), SQL builder for count where conditions and mutations - **Query organization**: Model queries are split into focused functions (`get-models-list.ts` for listing with RQBv2, `get-models-count.ts` for counting with SQL builder, `build-models-where.ts` for shared filter conditions) and composed in higher-level DAL functions (`get-models.ts`, `search-models.ts`). Both helpers support optional `searchPattern` and `category` parameters; list ordering comes from `features/models/sort/order-for-sort.ts` via the `sort` search param -- **Better Auth adapter**: Uses `@better-auth/drizzle-adapter/relations-v2` with experimental joins enabled (`lib/auth.ts`); mounted on ElysiaJS at `/api/[[...slugs]]/route.ts` with `basePath` `/api/auth`; OpenAPI documentation includes auth routes via `better-auth-openapi.ts` +- **Better Auth adapter**: Uses `@better-auth/drizzle-adapter/relations-v2` with experimental joins (`lib/auth.ts` runtime, `lib/auth.cli.config.ts` for generate); `provider: "sqlite"`; mounted on ElysiaJS at `/api/[[...slugs]]/route.ts` with `basePath` `/api/auth`; OpenAPI via `better-auth-openapi.ts` ### Cache Components The application uses Next.js Cache Components for optimal performance: @@ -442,9 +450,10 @@ The application uses Next.js Cache Components with granular cache tags for effic ## 🎨 Styling & Components ### Design System -- **Tokens & utilities**: Panda CSS 2 semantic tokens and preset utilities (`panda.config.ts`, `@pandacss/preset-base`, `@pandacss/preset-panda`, typography preset in `panda-presets/typography.ts`); orange accent and shared patterns (e.g., `navLink`) live in config +- **Tokens & utilities**: Panda CSS 2 semantic tokens and preset utilities (`panda.config.ts`, `@pandacss/preset-base`, `@pandacss/preset-panda`, `@pandacss/preset-typography`); orange accent and shared patterns (e.g., `navLink`) live in config; `treeshakeDesignSystem` enabled - **Typography**: Albert Sans + Montserrat Alternates via `next/font` in root layout; heading font applied in Panda `globalCss` - **Layout & spacing**: Panda `css()` / layout patterns (e.g., `grid` for model grids in `src/app/styles.ts`) +- **View transitions**: Colocated with components via React `ViewTransition` + Panda view-transition helpers (global VT CSS removed from `index.css`) - **Responsive**: Mobile-first breakpoints via Panda conditions and component styles ### Key Components @@ -504,6 +513,7 @@ The application uses Next.js Cache Components with granular cache tags for effic - `components/button` - Shared button styled with Panda variants - `components/form/input` - Text input with consistent field styling - `components/form/label` - Accessible labels for form fields +- `components/form/form-field` - Shared labeled field shell with field errors and shared ViewTransition names for auth forms - `components/form/submit-button` - Submit control wired for pending state - `components/form/reset-button` - Reset control for forms - `components/form/field-errors` - Field-level error display component with ViewTransition support @@ -517,14 +527,15 @@ The application uses Next.js Cache Components with granular cache tags for effic - `components/generic-component` - Generic wrapper for collections #### Authentication & Data Access -- `lib/auth` - Better Auth configuration with email/password and GitHub OAuth +- `lib/auth.cli.config` - CLI-only Better Auth config for schema generate (no secrets) +- `lib/auth` - Runtime Better Auth (`server-only`; secrets, OAuth, cookies, OpenAPI) - `lib/auth-client` - Better Auth client instance for client-side usage - `features/auth/actions` - Sign-in, sign-up, and sign-out server actions with Valibot validation - `features/auth/components/has-auth` - Renders `children(auth)` with `UserAuthState`; `HasAuthSuspense` wraps in `Suspend` - `features/auth/constants` - Validation constants (password length, email length, name length limits) - `features/auth/queries/get-user` - User query with `React.cache()` (returns `UserAuthState` from session) - `features/auth/components/sign-in-button` - GitHub OAuth sign-in button -- `utils/to-action-state` - Action state utilities for consistent server action responses +- `utils/to-action-state` - Action state helpers (`to-action-state.ts`, `types.ts`, `form-data-to-safe-payload.ts` for allowlisted FormData → client) - `components/form/field-errors` - Reusable field error component used in auth forms - `components/form/form-error` - Reusable form-level error component used in auth forms @@ -558,13 +569,14 @@ The application uses Next.js Cache Components with granular cache tags for effic - `bun run type` - Run `tsc` type checking - `bun run typegen` - Generate Next.js routes and run `tsc` (noEmit) - `bun run env:typegen` - Regenerate `src/env.d.ts` from `.env.schema` (Varlock) +- `bun run auth:generate` - Regenerate Better Auth Drizzle schema from `auth.cli.config.ts` - `bun run db:generate` - Generate Drizzle migrations - `bun run db:migrate` - Run Drizzle migrations - `bun run db:push` - Push schema directly to database - `bun run db:studio` - Open Drizzle Studio - `bun run db:seed` - Seed database with initial data - `bun run db:drop` - Drop all tables (development reset) -- `bun run fix` - Fix linting issues with Ultracite/Biome +- `bun run fix` - Fix linting/formatting issues with Ultracite/Biome - `bun run check` - Check linting rules with Ultracite/Biome - `bun run doctor` - Run Ultracite doctor diagnostics - `bun run ultracite:upgrade` - Upgrade Ultracite configuration @@ -592,7 +604,7 @@ The project follows a consistent coding style with: ### Environment Variables -Mirror **`.env.schema`**: `NEXT_PUBLIC_SITE_URL`, `BETTER_AUTH_SECRET`, `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`, `DATABASE_URL`, and **`BITWARDEN_ACCESS_TOKEN`** when using **`bitwarden()`** resolvers. Varlock validates at runtime; types live in **`src/env.d.ts`**. See **`docs/VARLOCK.md`** for Vercel and Bitwarden. +Mirror **`.env.schema`**: `NEXT_PUBLIC_SITE_URL`, `BETTER_AUTH_SECRET`, `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`, `TURSO_DATABASE_URL`, `TURSO_DATABASE_AUTH`, legacy `DATABASE_URL` (unused), and **`BITWARDEN_ACCESS_TOKEN`** when using **`bitwarden()`** resolvers. Varlock validates at runtime; types live in **`src/env.d.ts`**. See **`docs/VARLOCK.md`** for Vercel and Bitwarden. ## 📝 Data Management @@ -603,7 +615,7 @@ Mirror **`.env.schema`**: `NEXT_PUBLIC_SITE_URL`, `BETTER_AUTH_SECRET`, `GITHUB_ ### Adding New Categories -1. Add the category to `src/db/categories.ts` (updates the PostgreSQL enum source of truth) +1. Add the category to `src/db/categories.ts` (updates the category slug enum source of truth) 2. Run `bun run db:generate` then `bun run db:migrate` (or `bun run db:push` in development) 3. Run `bun run db:seed` to update the database diff --git a/biome.json b/biome.json index ae1f0de..d0d5529 100644 --- a/biome.json +++ b/biome.json @@ -39,7 +39,8 @@ "!!**/*.lock", "!!**/*.svg", "!**/drizzle", - "!**/src/env.d.ts" + "!**/src/env.d.ts", + "!fallow-viz.html" ] } } diff --git a/bun.lock b/bun.lock index d8789d0..bea1180 100644 --- a/bun.lock +++ b/bun.lock @@ -8,18 +8,17 @@ "@better-auth/drizzle-adapter": "1.7.0-rc.1", "@elysiajs/cors": "^1.4.2", "@elysiajs/openapi": "^1.4.15", + "@libsql/client": "^0.17.4", "@rsc-boundary/next": "^0.3.2", "@varlock/bitwarden-plugin": "^2.0.0", - "@vercel/functions": "^3.7.5", "babel-plugin-react-compiler": "^1.0.0", "better-auth": "1.7.0-rc.1", "drizzle-orm": "1.0.0-rc.4", "elysia": "^1.4.29", - "next": "16.3.0-canary.90", - "nuqs": "^2.9.0", - "pg": "^8.22.0", - "react": "19.3.0-canary-e92ecef2-20260618", - "react-dom": "19.3.0-canary-e92ecef2-20260618", + "next": "16.3.0-canary.95", + "nuqs": "^2.9.1", + "react": "19.3.0-canary-172742b4-20260716", + "react-dom": "19.3.0-canary-172742b4-20260716", "react-icons": "^5.7.0", "slugify": "^1.6.9", "valibot": "^1.4.2", @@ -27,24 +26,24 @@ }, "devDependencies": { "@biomejs/biome": "2.5.3", - "@happy-dom/global-registrator": "^20.10.6", - "@pandacss/dev": "^2.0.0-beta.8", - "@pandacss/preset-base": "2.0.0-beta.8", - "@pandacss/preset-panda": "2.0.0-beta.8", + "@happy-dom/global-registrator": "^20.11.0", + "@pandacss/dev": "^2.0.0-beta.10", + "@pandacss/preset-base": "2.0.0-beta.10", + "@pandacss/preset-panda": "2.0.0-beta.10", + "@pandacss/preset-typography": "2.0.0-beta.10", "@playwright/test": "^1.61.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@types/bun": "^1.3.14", - "@types/pg": "^8.20.0", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@varlock/nextjs-integration": "^1.1.6", "drizzle-kit": "1.0.0-rc.4", - "happy-dom": "^20.10.6", + "happy-dom": "^20.11.0", "husky": "^9.1.7", - "lint-staged": "^17.0.8", + "lint-staged": "^17.1.0", "next-devtools-mcp": "^0.4.0", - "react-doctor": "^0.7.8", + "react-doctor": "^0.8.1", "typescript": "^7.0.2", "typescript-plugin-directives": "^0.0.3", "ultracite": "7.9.4", @@ -216,7 +215,7 @@ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.1", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ=="], - "@happy-dom/global-registrator": ["@happy-dom/global-registrator@20.10.6", "", { "dependencies": { "@types/node": ">=20.0.0", "happy-dom": "^20.10.6" } }, "sha512-Nu/IjRkkNxmeG2ywWsyJSO4d1BrWTqVzxCPL+gXj0b97klhmjd6wLzt6Bx/laNpkZ3WLW7zNCqmtMIbIlahqug=="], + "@happy-dom/global-registrator": ["@happy-dom/global-registrator@20.11.0", "", { "dependencies": { "@types/node": ">=20.0.0", "happy-dom": "^20.11.0" } }, "sha512-rHb/2dOy3APuHKNU4aqPQt+HbEt6BkulTTyCks89z5a+EipJecnFFd+3cz3meaFfCOXWsoxplPTLrGjFIEhd0A=="], "@hono/node-server": ["@hono/node-server@1.19.14", "", { "peerDependencies": { "hono": "^4" } }, "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw=="], @@ -232,55 +231,59 @@ "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], - "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="], + "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], - "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.2" }, "os": "darwin", "cpu": "arm64" }, "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg=="], - "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.3.2" }, "os": "darwin", "cpu": "x64" }, "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w=="], - "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], + "@img/sharp-freebsd-wasm32": ["@img/sharp-freebsd-wasm32@0.35.3", "", { "dependencies": { "@img/sharp-wasm32": "0.35.3" }, "os": "freebsd" }, "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg=="], - "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg=="], - "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw=="], - "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.3.2", "", { "os": "linux", "cpu": "arm" }, "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ=="], - "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="], + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA=="], - "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="], + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.3.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw=="], - "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="], + "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.3.2", "", { "os": "linux", "cpu": "none" }, "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w=="], - "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.3.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ=="], - "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w=="], - "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw=="], - "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ=="], - "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.3.2" }, "os": "linux", "cpu": "arm" }, "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA=="], - "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="], + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ=="], - "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="], + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.3.2" }, "os": "linux", "cpu": "ppc64" }, "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA=="], - "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="], + "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.3.2" }, "os": "linux", "cpu": "none" }, "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ=="], - "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.3.2" }, "os": "linux", "cpu": "s390x" }, "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw=="], - "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA=="], - "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w=="], - "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="], + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg=="], - "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.35.3", "", { "dependencies": { "@emnapi/runtime": "^1.11.1" } }, "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w=="], - "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="], + "@img/sharp-webcontainers-wasm32": ["@img/sharp-webcontainers-wasm32@0.35.3", "", { "dependencies": { "@img/sharp-wasm32": "0.35.3" }, "cpu": "none" }, "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q=="], - "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.35.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.35.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.35.3", "", { "os": "win32", "cpu": "x64" }, "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA=="], "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], @@ -294,17 +297,45 @@ "@js-temporal/polyfill": ["@js-temporal/polyfill@0.5.1", "", { "dependencies": { "jsbi": "^4.3.0" } }, "sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ=="], + "@libsql/client": ["@libsql/client@0.17.4", "", { "dependencies": { "@libsql/core": "^0.17.4", "@libsql/hrana-client": "^0.10.0", "js-base64": "^3.7.5", "libsql": "^0.5.28", "promise-limit": "^2.7.0" } }, "sha512-lYayFWasDV78A+TjlEhr6ubb3odBV6OHjb+wdp8VQcyWWAEIjuwbCHaraEUS4m4yWoo0BvZo96It4VdzZRmRWw=="], + + "@libsql/core": ["@libsql/core@0.17.4", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-LqF9gIvnJ38nmAH1y/ChizHqDO/MO1wLgA96XrraulEEbqXxLjleSH92YWTolbuJKgPUmGu4aJk9W3UnAcxLOQ=="], + + "@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.29", "", { "os": "darwin", "cpu": "arm64" }, "sha512-K+2RIB1OGFPYQbfay48GakLhqf3ArcbHqPFu7EZiaUcRgFcdw8RoltsMyvbj5ix2fY0HV3Q3Ioa/ByvQdaSM0A=="], + + "@libsql/darwin-x64": ["@libsql/darwin-x64@0.5.29", "", { "os": "darwin", "cpu": "x64" }, "sha512-OtT+KFHsKFy1R5FVadr8FJ2Bb1mghtXTyJkxv0trocq7NuHntSki1eUbxpO5ezJesDvBlqFjnWaYYY516QNLhQ=="], + + "@libsql/hrana-client": ["@libsql/hrana-client@0.10.0", "", { "dependencies": { "@libsql/isomorphic-ws": "^0.1.5", "js-base64": "^3.7.5" } }, "sha512-OoA4EMqRAC7kn7V2P6EQqRcpZf2W+AjsNIyCizBg339Tq/aMC7sRnzs3SklderhmQWAqEzvv8A2vhxVmWpkVvw=="], + + "@libsql/isomorphic-ws": ["@libsql/isomorphic-ws@0.1.5", "", { "dependencies": { "@types/ws": "^8.5.4", "ws": "^8.13.0" } }, "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg=="], + + "@libsql/linux-arm-gnueabihf": ["@libsql/linux-arm-gnueabihf@0.5.29", "", { "os": "linux", "cpu": "arm" }, "sha512-CD4n4zj7SJTHso4nf5cuMoWoMSS7asn5hHygsDuhRl8jjjCTT3yE+xdUvI4J7zsyb53VO5ISh4cwwOtf6k2UhQ=="], + + "@libsql/linux-arm-musleabihf": ["@libsql/linux-arm-musleabihf@0.5.29", "", { "os": "linux", "cpu": "arm" }, "sha512-2Z9qBVpEJV7OeflzIR3+l5yAd4uTOLxklScYTwpZnkm2vDSGlC1PRlueLaufc4EFITkLKXK2MWBpexuNJfMVcg=="], + + "@libsql/linux-arm64-gnu": ["@libsql/linux-arm64-gnu@0.5.29", "", { "os": "linux", "cpu": "arm64" }, "sha512-gURBqaiXIGGwFNEaUj8Ldk7Hps4STtG+31aEidCk5evMMdtsdfL3HPCpvys+ZF/tkOs2MWlRWoSq7SOuCE9k3w=="], + + "@libsql/linux-arm64-musl": ["@libsql/linux-arm64-musl@0.5.29", "", { "os": "linux", "cpu": "arm64" }, "sha512-fwgYZ0H8mUkyVqXZHF3mT/92iIh1N94Owi/f66cPVNsk9BdGKq5gVpoKO+7UxaNzuEH1roJp2QEwsCZMvBLpqg=="], + + "@libsql/linux-x64-gnu": ["@libsql/linux-x64-gnu@0.5.29", "", { "os": "linux", "cpu": "x64" }, "sha512-y14V0vY0nmMC6G0pHeJcEarcnGU2H6cm21ZceRkacWHvQAEhAG0latQkCtoS2njFOXiYIg+JYPfAoWKbi82rkg=="], + + "@libsql/linux-x64-musl": ["@libsql/linux-x64-musl@0.5.29", "", { "os": "linux", "cpu": "x64" }, "sha512-gquqwA/39tH4pFl+J9n3SOMSymjX+6kZ3kWgY3b94nXFTwac9bnFNMffIomgvlFaC4ArVqMnOZD3nuJ3H3VO1w=="], + + "@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.5.29", "", { "os": "win32", "cpu": "x64" }, "sha512-4/0CvEdhi6+KjMxMaVbFM2n2Z44escBRoEYpR+gZg64DdetzGnYm8mcNLcoySaDJZNaBd6wz5DNdgRmcI4hXcg=="], + "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="], "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="], + "@neon-rs/load": ["@neon-rs/load@0.0.4", "", {}, "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw=="], + "@neondatabase/serverless": ["@neondatabase/serverless@1.1.0", "", {}, "sha512-r3ZZhRjEcfEdKIZnoB1RusNgvHuaBRqfCzV4Gi+5A9yUX0S4HTws/ASWqt13wL4y4I+0rqsWGdA2w7EQXHi3+Q=="], "@next/env": ["@varlock/nextjs-integration@1.1.6", "", { "peerDependencies": { "next": ">=14", "varlock": "^1.11.0" } }, "sha512-nbMyAokJeKovKGoG7vFsELbnp2C8YkPaSRB2BhV3JXBcWlfTXKgIN7uP/EelusPEEvgaJVPr83j4sujHPki8sg=="], - "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.3.0-canary.90", "", { "os": "linux", "cpu": "x64" }, "sha512-e8cR+SpcOM4XW8fzmklSlXiFMP6lGd50kZFxhHkAKGpskcPQINTvCFEk3aF4Pl0e/wsXuCnGDy9bBQFOSOm04Q=="], + "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.3.0-canary.95", "", { "os": "linux", "cpu": "x64" }, "sha512-P55XoZxitAC3oWSANEqr9IRM/bUPqjlxuk4P09DI3Xrd8DCccBXI1ji+KbWlz7z+1AsTG81TWQvd9HxTsYp2GQ=="], - "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.3.0-canary.90", "", { "os": "linux", "cpu": "x64" }, "sha512-LDiNTQKABDGuxbHoG9Ka/2dB33ZbhbY3WPPqtHmBqUO2BrLKUmbGR5BjRk/IjfT5jGZ0pjPBDDEkvsEQvRlyZg=="], + "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.3.0-canary.95", "", { "os": "linux", "cpu": "x64" }, "sha512-bCyDs8BhMgHYsIw95sjlA27plaUI68MNOOya3kcmb8HkyPUOBlyKqQMkoGP/XAWpQNn6OZIarjEHEmk5q4Zd0Q=="], "@noble/ciphers": ["@noble/ciphers@2.2.0", "", {}, "sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA=="], @@ -448,41 +479,43 @@ "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.66.0", "", { "os": "win32", "cpu": "x64" }, "sha512-/DbBvw8UFBhja6PqudUjV4UtfsJr0Oa7jUjWVKB0g86lj/VwnPrkngn0sFql3c9RDA0O16dh7ozsXb6GjNAzBQ=="], - "@pandacss/cli": ["@pandacss/cli@2.0.0-beta.8", "", { "dependencies": { "@pandacss/compiler": "2.0.0-beta.8", "@pandacss/compiler-shared": "2.0.0-beta.8", "@pandacss/config": "2.0.0-beta.8", "@parcel/watcher": "2.5.1", "citty": "0.1.6", "zod": "^4.0.0" }, "bin": { "panda": "bin.js", "pandacss": "bin.js" } }, "sha512-mBdjj2Nenx4MYWQl2RNyRNyMePSrymNYZAJ87wvEH1vBOXMn7FvntXDOLusibLqQ1w+ZMHbaBAuo7oorYpjfHQ=="], + "@pandacss/cli": ["@pandacss/cli@2.0.0-beta.10", "", { "dependencies": { "@clack/prompts": "1.7.0", "@pandacss/compiler": "2.0.0-beta.10", "@pandacss/compiler-shared": "2.0.0-beta.10", "@pandacss/config": "2.0.0-beta.10", "@pandacss/types": "2.0.0-beta.10", "@parcel/watcher": "2.5.1", "citty": "0.1.6", "picocolors": "1.1.1", "string-width": "7.2.0" }, "bin": { "panda": "bin.js", "pandacss": "bin.js" } }, "sha512-JahEmeb6BN8+gjbkRYy5nDEl1Jyuv0QRtxLK/fzfjrqohuBSZCgkqPP3sRFFf82iwqQyV33H3PqdusGwzLdY2g=="], - "@pandacss/compiler": ["@pandacss/compiler@2.0.0-beta.8", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.6", "@pandacss/compiler-shared": "2.0.0-beta.8", "@pandacss/config": "2.0.0-beta.8" }, "optionalDependencies": { "@pandacss/compiler-darwin-arm64": "2.0.0-beta.8", "@pandacss/compiler-darwin-x64": "2.0.0-beta.8", "@pandacss/compiler-linux-arm64-gnu": "2.0.0-beta.8", "@pandacss/compiler-linux-arm64-musl": "2.0.0-beta.8", "@pandacss/compiler-linux-x64-gnu": "2.0.0-beta.8", "@pandacss/compiler-linux-x64-musl": "2.0.0-beta.8", "@pandacss/compiler-wasm32-wasi": "2.0.0-beta.8", "@pandacss/compiler-win32-arm64-msvc": "2.0.0-beta.8", "@pandacss/compiler-win32-x64-msvc": "2.0.0-beta.8" } }, "sha512-rbgLgkqnBewXFB1+e87GEq5Q9R09+kWzCpu+Bl9IaIR/HBsZ/lWmgUxsN9EOe0wrlkDuG7/2BO6mZYFASfnrPA=="], + "@pandacss/compiler": ["@pandacss/compiler@2.0.0-beta.10", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.6", "@pandacss/compiler-shared": "2.0.0-beta.10", "@pandacss/config": "2.0.0-beta.10", "@pandacss/types": "2.0.0-beta.10" }, "optionalDependencies": { "@pandacss/compiler-darwin-arm64": "2.0.0-beta.10", "@pandacss/compiler-darwin-x64": "2.0.0-beta.10", "@pandacss/compiler-linux-arm64-gnu": "2.0.0-beta.10", "@pandacss/compiler-linux-arm64-musl": "2.0.0-beta.10", "@pandacss/compiler-linux-x64-gnu": "2.0.0-beta.10", "@pandacss/compiler-linux-x64-musl": "2.0.0-beta.10", "@pandacss/compiler-wasm32-wasi": "2.0.0-beta.10", "@pandacss/compiler-win32-arm64-msvc": "2.0.0-beta.10", "@pandacss/compiler-win32-x64-msvc": "2.0.0-beta.10" } }, "sha512-gbKFf2kCDx71Ci+IpxflNbWtKeyoGzAXZ07KhurWYwsY6Li42o+qdtA/s1CSyhauBec6tfCa5jwH7hX0uVABIg=="], - "@pandacss/compiler-darwin-arm64": ["@pandacss/compiler-darwin-arm64@2.0.0-beta.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-IhiIHjq8N936EvD+L6UvmMgyMTO9GRDomUy+2YTJ5gbk7YD4KqcXjWJqGzdMyQE0PNCBtjl1Rc6kYgQY+JQsSA=="], + "@pandacss/compiler-darwin-arm64": ["@pandacss/compiler-darwin-arm64@2.0.0-beta.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-PoEcXPXNs5NFYToF67R0cnnpWsqA2sPKpzQ+ZAfEh3dkR4RkkBe8Vr7DMpcZrPs1hQwp0xoaHHJ3xjKJxoZSXQ=="], - "@pandacss/compiler-darwin-x64": ["@pandacss/compiler-darwin-x64@2.0.0-beta.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-0n0LSBai35dbu6KJ7ZKmx+Ga6PeSqohByvod9vpccZ1FilX+bRJ7AjIMvmA/Q/c4BnnTtUbVIqLXBFB3VYu1MA=="], + "@pandacss/compiler-darwin-x64": ["@pandacss/compiler-darwin-x64@2.0.0-beta.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-ub6Le59BUC5zDFaEfLtiOrEMiT6V7xJdDqqwqPuzDWzYt3gPkWm9/JtLV0DywpEHbpQV5VXeLbjQZN8oOTEpuA=="], - "@pandacss/compiler-linux-arm64-gnu": ["@pandacss/compiler-linux-arm64-gnu@2.0.0-beta.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-StjVp5egXyb4NzCKM0fyT5sz7/QeWkNjRgnl9agkjSH4lG1p7v2STYqA6EiZg1iboFksh2qLTPKwueHdnXQMFA=="], + "@pandacss/compiler-linux-arm64-gnu": ["@pandacss/compiler-linux-arm64-gnu@2.0.0-beta.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-B0kLP0RU6i/910YsgU/yFsOl7w+s3PvIvFLzpJ8+RAJ9j5Ff+nM+Kb5a6TkTI8c2K6lmoMLGuslY5HyM849ntg=="], - "@pandacss/compiler-linux-arm64-musl": ["@pandacss/compiler-linux-arm64-musl@2.0.0-beta.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-L2tTnGyC7UPTMNdPpSEd1mbuoV8uEJYzSpwqmeXtQ1VjMJygzkE/1IuivOhZ29M7AOU+QCx6lZ352xO6DUlESw=="], + "@pandacss/compiler-linux-arm64-musl": ["@pandacss/compiler-linux-arm64-musl@2.0.0-beta.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-bTW0xjkOmgz/QDnEkd4sNnk+SGBAbHXFgQUvHMsUUTzkzf1MAl6s9MA9KF4WL7nHv19hNHf1TkFgxLYxAUIxEQ=="], - "@pandacss/compiler-linux-x64-gnu": ["@pandacss/compiler-linux-x64-gnu@2.0.0-beta.8", "", { "os": "linux", "cpu": "x64" }, "sha512-6dncPh0ZTIAn+ziEOWozVtt1Elqw6gXcklWezzU6S3kKqCc4DMr+daasEiaWnAUnp43poFs2BZpjCm78VdRv9w=="], + "@pandacss/compiler-linux-x64-gnu": ["@pandacss/compiler-linux-x64-gnu@2.0.0-beta.10", "", { "os": "linux", "cpu": "x64" }, "sha512-A7w3li+SKnr76i9Nkp+u7hVKAMJRV8LusukY+vR/b4846xy0LCOdJOfVWXUVbtc5Lt16luPIQo8rZNYzZV0PTA=="], - "@pandacss/compiler-linux-x64-musl": ["@pandacss/compiler-linux-x64-musl@2.0.0-beta.8", "", { "os": "linux", "cpu": "x64" }, "sha512-pj1PZuNR8oLBshKoae/ZNX3ib5HpI9HKnsZ3O4WHfuY2qHEvYGOY3Pv2sOJB8hnxiLquysZsjSYdYGI/owNYKA=="], + "@pandacss/compiler-linux-x64-musl": ["@pandacss/compiler-linux-x64-musl@2.0.0-beta.10", "", { "os": "linux", "cpu": "x64" }, "sha512-Z9qVQVzzVpvQr9/loXzTwjNj+hGk+tdCKzVvyq2ztvrh8W5XPjYicdmI5M8ArjiDpB/xllcL3zSN3aOGS3li+Q=="], - "@pandacss/compiler-shared": ["@pandacss/compiler-shared@2.0.0-beta.8", "", {}, "sha512-XnMRQ2uZJoMdA53dK/bhf8Hoxfp6WBpYUt5HTrv1QVrqaSzW/tb5B2fTqG8t8OlZoZtbpMh4jfTQBa2/s8Cdrg=="], + "@pandacss/compiler-shared": ["@pandacss/compiler-shared@2.0.0-beta.10", "", { "dependencies": { "@pandacss/types": "2.0.0-beta.10" } }, "sha512-h3CDNUNNfeir4V+T2TDaszzUJhQ1O7AnWfJQg1gDW3AA8q8kZFPg5uc+RnZhrzzfE1KvuxkJpNgbPdBsDvXxcQ=="], - "@pandacss/compiler-wasm32-wasi": ["@pandacss/compiler-wasm32-wasi@2.0.0-beta.8", "", { "dependencies": { "@emnapi/core": "1.11.1", "@emnapi/runtime": "1.11.1", "@napi-rs/wasm-runtime": "^1.1.6" }, "cpu": "none" }, "sha512-KXeiOAQ9N7jaK5hqncUTJYL39plKeF6sg8Gs/UAW5s+7AW73LBz2al89AptGmmUufE+z5SAdH1r2wSdv+vZdzg=="], + "@pandacss/compiler-wasm32-wasi": ["@pandacss/compiler-wasm32-wasi@2.0.0-beta.10", "", { "dependencies": { "@emnapi/core": "1.11.1", "@emnapi/runtime": "1.11.1", "@napi-rs/wasm-runtime": "^1.1.6" }, "cpu": "none" }, "sha512-eWUkFsHs1qTSbHSb/G5PpIoUEaUQREzqMHQv6CW4LHTpfUbt9Hvkx7jArUjrw6TN9OgWBrzNYLabwv4ORS9fXQ=="], - "@pandacss/compiler-win32-arm64-msvc": ["@pandacss/compiler-win32-arm64-msvc@2.0.0-beta.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-YR5icpMbvUtjWga2qSxD+v/URbRo5Y4hFUsB9h3HS2OG/gheL6JM3oOOPDRxo6+N9/5u/f89Hl8g0/Ru8pCusw=="], + "@pandacss/compiler-win32-arm64-msvc": ["@pandacss/compiler-win32-arm64-msvc@2.0.0-beta.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-u06+jsROgv4QI4yhOELZnYwBEwW5jME/Ie09tMA2kKfCW/cYqj8NtvDmNW02TCIVcIz7sJqp2wrFL8NST7SacQ=="], - "@pandacss/compiler-win32-x64-msvc": ["@pandacss/compiler-win32-x64-msvc@2.0.0-beta.8", "", { "os": "win32", "cpu": "x64" }, "sha512-uVWwL4hbbzFdmvCBvkZXjXPKakuy0SdtyLIykuOV0Ss25BoL6tO40doOng8q3F2QtIRaKCMLBDxOY9C0F7+REA=="], + "@pandacss/compiler-win32-x64-msvc": ["@pandacss/compiler-win32-x64-msvc@2.0.0-beta.10", "", { "os": "win32", "cpu": "x64" }, "sha512-e+sY45XUtAfuEzyRX9JRTsPX8GNsqdvNmLeHLDBufmtme7Qvpd93wxYAGasNgREfc8vyV/+IFLUqroLJNTv5lQ=="], - "@pandacss/config": ["@pandacss/config@2.0.0-beta.8", "", { "dependencies": { "@pandacss/compiler-shared": "2.0.0-beta.8", "@pandacss/types": "2.0.0-beta.8", "acorn": "^8.17.0", "acorn-walk": "^8.3.5", "javascript-stringify": "2.1.0", "magic-string": "^0.30.21", "microdiff": "1.5.0", "rolldown": "1.0.0-rc.17" } }, "sha512-DWaFkmC7Oh4Mi9OYPaonX0KdV7V0vw2CqB2gKx/55sx0Em6G1fZP57WTWGEoz4aAm+hHBrK7Yvzp8gHXw8vTAw=="], + "@pandacss/config": ["@pandacss/config@2.0.0-beta.10", "", { "dependencies": { "@pandacss/compiler-shared": "2.0.0-beta.10", "@pandacss/types": "2.0.0-beta.10", "acorn": "^8.17.0", "acorn-walk": "^8.3.5", "javascript-stringify": "2.1.0", "magic-string": "^0.30.21", "microdiff": "1.5.0", "rolldown": "1.0.0-rc.17" } }, "sha512-HMdnZ6zImyud7/KNfj7hKQqY5LDbkvZTiEPUFg+ELXkZUDpGcVZx41e6MBYVQ/xt7O1GgAnKihACQ2ckfw8Tng=="], - "@pandacss/dev": ["@pandacss/dev@2.0.0-beta.8", "", { "dependencies": { "@pandacss/cli": "2.0.0-beta.8", "@pandacss/compiler": "2.0.0-beta.8", "@pandacss/config": "2.0.0-beta.8", "@pandacss/postcss": "2.0.0-beta.8", "@pandacss/types": "2.0.0-beta.8" }, "peerDependencies": { "postcss": ">=8" }, "optionalPeers": ["postcss"], "bin": { "panda": "bin.js", "pandacss": "bin.js" } }, "sha512-qOweOqmTKhhn81oQJ6vcNjC1CqKKNJrHEhlvgAWgNigRgyCLCZgcXh750I0uKVLCCrqheSuouzOzsWa1m/NbNQ=="], + "@pandacss/dev": ["@pandacss/dev@2.0.0-beta.10", "", { "dependencies": { "@pandacss/cli": "2.0.0-beta.10", "@pandacss/compiler": "2.0.0-beta.10", "@pandacss/config": "2.0.0-beta.10", "@pandacss/postcss": "2.0.0-beta.10", "@pandacss/types": "2.0.0-beta.10" }, "peerDependencies": { "postcss": ">=8" }, "optionalPeers": ["postcss"], "bin": { "panda": "bin.js", "pandacss": "bin.js" } }, "sha512-lOhra+Hx8bABSN14JWrBjJSNiS/CHi/OcioObuExGfJ+bT/mYluoF3jxIYxiZgPm9Qp53sTKP4Oy21m8aKw5Yw=="], - "@pandacss/postcss": ["@pandacss/postcss@2.0.0-beta.8", "", { "dependencies": { "@pandacss/compiler": "2.0.0-beta.8", "@pandacss/compiler-shared": "2.0.0-beta.8" }, "peerDependencies": { "postcss": ">=8" } }, "sha512-qrMk7X/lzWBvitzKqYME+cUHZZFpajrwYEUjWL0TzejZ95nIvON4/ijftCfow/2068nclEGqpPq/OURVXECs/w=="], + "@pandacss/postcss": ["@pandacss/postcss@2.0.0-beta.10", "", { "dependencies": { "@pandacss/compiler": "2.0.0-beta.10", "@pandacss/compiler-shared": "2.0.0-beta.10" }, "peerDependencies": { "postcss": ">=8" } }, "sha512-KZ2MwBETz2FCj0tLKM64vS05mWkFTZaKMx/bMCqzrvVBCz8yUEQNpqdcdOXs2tggVj7h9vczVvj/uSeax9hQBw=="], - "@pandacss/preset-base": ["@pandacss/preset-base@2.0.0-beta.8", "", { "dependencies": { "@pandacss/types": "2.0.0-beta.8" } }, "sha512-7GJQzHMPIVu+UNd2eR2YOm2US6fBxab+zKYQumdiDWks0qRXDog1skyxBIUWQazfqCV5F9iiWM6rOtdR2Am/Qg=="], + "@pandacss/preset-base": ["@pandacss/preset-base@2.0.0-beta.10", "", { "dependencies": { "@pandacss/types": "2.0.0-beta.10" } }, "sha512-FkDPZNq3ABvKjgoT/GXjTuATr23pwRukIFirjpOGtM3sV4BTJQYvqFFjDrtkRs3ew0rxJinnrkbaR89PiMbDSA=="], - "@pandacss/preset-panda": ["@pandacss/preset-panda@2.0.0-beta.8", "", { "dependencies": { "@pandacss/types": "2.0.0-beta.8" } }, "sha512-ks1ZoR/zgmbhREROL6hmoPG+hvWiYfAYqlvvrL4c6O3AojQ+9b6rI9endJo7FUa8Qrntlt9RfU2805rlrXJGwQ=="], + "@pandacss/preset-panda": ["@pandacss/preset-panda@2.0.0-beta.10", "", { "dependencies": { "@pandacss/types": "2.0.0-beta.10" } }, "sha512-tjMLdvF8HHA7/K4g1TOuwICcmDqwVgVkCcifjrOJ4I4F9Hh91/q1/bGFisAjWegofz1dP5eld+0rHlRnO9sy0w=="], - "@pandacss/types": ["@pandacss/types@2.0.0-beta.8", "", {}, "sha512-hgzi5uY+NWwGpyxKT+i1FM+cG9uwLaDyRbSNir8Idpo8Pmi4Amb8xtQ3sC0D7ie50SVGSlPw8MfCTURP7tw0UQ=="], + "@pandacss/preset-typography": ["@pandacss/preset-typography@2.0.0-beta.10", "", { "dependencies": { "@pandacss/types": "2.0.0-beta.10" } }, "sha512-WAy8JFrs7MqE3+JBhHJje0iUhjUiUt35BKB1pEXCXbCF/wv/clbOPCUXuEIij2nQYSc/kHZD9c3hI5tMJuXL6Q=="], + + "@pandacss/types": ["@pandacss/types@2.0.0-beta.10", "", {}, "sha512-JtSSNbWtAoOaDB2KJtKtQ8jP8c6Nks5/EkYWLbtEvYhMFghrNZAbPbVpAsiKrU9WlKdGOET2QSKa+ltZpuN1gQ=="], "@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="], @@ -564,7 +597,7 @@ "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], - "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], @@ -660,14 +693,6 @@ "@varlock/nextjs-integration": ["@varlock/nextjs-integration@1.1.6", "", { "peerDependencies": { "next": ">=14", "varlock": "^1.11.0" } }, "sha512-nbMyAokJeKovKGoG7vFsELbnp2C8YkPaSRB2BhV3JXBcWlfTXKgIN7uP/EelusPEEvgaJVPr83j4sujHPki8sg=="], - "@vercel/cli-config": ["@vercel/cli-config@0.2.0", "", { "dependencies": { "xdg-app-paths": "5", "zod": "4.1.11" } }, "sha512-fJRRRB7734BDuXZ89yBEaA2ncYhH7bWX30mk04W80J6VAfQc+4iB8lyzAdaGpFV3/vNlkt9VZt+/uoQoWX6UsQ=="], - - "@vercel/cli-exec": ["@vercel/cli-exec@1.0.0", "", { "dependencies": { "execa": "5.1.1" } }, "sha512-kQF8LGie/Hbdq9/psJxLE7owRTcqMQMhgybU04gCeR7cbQAr5t8OrjefDNColJv1QSSucFt4pLwRiARVmlOnug=="], - - "@vercel/functions": ["@vercel/functions@3.7.5", "", { "dependencies": { "@vercel/oidc": "3.8.0" }, "peerDependencies": { "@aws-sdk/credential-provider-web-identity": "*", "ws": ">=8" }, "optionalPeers": ["@aws-sdk/credential-provider-web-identity", "ws"] }, "sha512-ESf8BbeDebqRUyMi09JwRbQqpLn4g6fjcVVHPsHB56j2dSqRrSHO4h3X4aaxJf6iQQjzhAtDGI2xCWQ27JE8PA=="], - - "@vercel/oidc": ["@vercel/oidc@3.8.0", "", { "dependencies": { "@vercel/cli-config": "0.2.0", "@vercel/cli-exec": "1.0.0", "jose": "^5.9.6" } }, "sha512-r00laGW6Pv778RoR6M2NxX91ycSj+PBwVo+fOb9Bif+F0IyUKt25zrvBzfEzQpeAzbqOgPZyQibEWDdDFApd+A=="], - "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], "acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="], @@ -684,8 +709,6 @@ "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], - "ansi-escapes": ["ansi-escapes@7.1.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-YdhtCd19sKRKfAAUsrcC1wzm4JuzJoiX4pOJqIoW2qmKj5WzG/dL8uUJ0361zaXtHqK7gEhOwtAtz7t3Yq3X5g=="], - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], @@ -730,10 +753,6 @@ "cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="], - "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], - - "cli-truncate": ["cli-truncate@5.2.0", "", { "dependencies": { "slice-ansi": "^8.0.0", "string-width": "^8.2.0" } }, "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw=="], - "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], @@ -778,9 +797,9 @@ "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], - "deslop-js": ["deslop-js@0.7.8", "", { "dependencies": { "@oxc-project/types": "^0.138.0", "fast-glob": "^3.3.3", "minimatch": "^10.2.5", "oxc-parser": "^0.138.0", "oxc-resolver": "^11.23.0", "typescript": ">=5.0.4 <6" } }, "sha512-QMmb3Z/ARvYZmZneudb8cnY/4mVvZTdhUyA9TC2skwOcm7KvY9zyOdn0TApQc4rL0VM2TffFkmo3ky/lJZX7qw=="], + "deslop-js": ["deslop-js@0.8.1", "", { "dependencies": { "@oxc-project/types": "^0.138.0", "fast-glob": "^3.3.3", "minimatch": "^10.2.5", "oxc-parser": "^0.138.0", "oxc-resolver": "^11.23.0", "typescript": ">=5.0.4 <6" } }, "sha512-a8wpwOPo6HsYyRndn17C88mNzeQD6t17yhZ8qpyFWTxj5jQeWtXDj+zJfnuT8++5A4LaNeNAnKs1edVWuadNdQ=="], - "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], "dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], @@ -798,7 +817,7 @@ "elysia": ["elysia@1.4.29", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-GwMRGGwSdjfPt+w3LA0fqTuYJtS8uVRJicvoar98/HrO5qdFKDc9CwjIb6Kja+v39lkY+58hr2JvdR9jQzlUuA=="], - "emoji-regex": ["emoji-regex@10.5.0", "", {}, "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg=="], + "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], @@ -806,8 +825,6 @@ "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], - "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], - "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], @@ -842,8 +859,6 @@ "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], - "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], - "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="], "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="], @@ -906,7 +921,7 @@ "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], - "get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="], + "get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="], "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], @@ -922,7 +937,7 @@ "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], - "happy-dom": ["happy-dom@20.10.6", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "buffer-image-size": "^0.6.4", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.21.0" } }, "sha512-6QD0ilzDDt93tX44y8tbmZdAcdTRYDhUP+Asgi6pC8Pp5IA3cvaZGyoVN/EGtlq9ziT65iPuBBn3ASLr6hCgVw=="], + "happy-dom": ["happy-dom@20.11.0", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "buffer-image-size": "^0.6.4", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.21.0" } }, "sha512-XogN4asPd1a56di9prVG6bZxteNcXsZxxKmAvcEfc5Px5Ca2hMyMgk8wvqK2K1V8zXg40j9VANXsDaJYh9DeNA=="], "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], @@ -960,8 +975,6 @@ "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - "is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], @@ -982,6 +995,8 @@ "jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="], + "js-base64": ["js-base64@3.9.1", "", {}, "sha512-U73qptcvf/HIOauFOmqT3a0mDUp0MYlfd15oqoe9kqZt5XhiXVb+HG09sLvI9PQ9tZIBFS4nlErai8zbWazP0g=="], + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "jsbi": ["jsbi@4.3.2", "", {}, "sha512-9fqMSQbhJykSeii05nxKl4m6Eqn2P6rOlYiS+C5Dr/HPIU/7yZxu5qzbs40tgaFORiw2Amd0mirjxatXYMkIew=="], @@ -1008,14 +1023,12 @@ "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - "lint-staged": ["lint-staged@17.0.8", "", { "dependencies": { "listr2": "^10.2.1", "picomatch": "^4.0.4", "string-argv": "^0.3.2", "tinyexec": "^1.2.4" }, "optionalDependencies": { "yaml": "^2.9.0" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-B2P/d+jVW0UXOQ0MVMLrB/9ydA1P+zz6jYfdrbbEd9ur3S2rcbduFWKiUCC02Sm5hbC8nrm7y24WuYMG54HfxA=="], + "libsql": ["libsql@0.5.29", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.29", "@libsql/darwin-x64": "0.5.29", "@libsql/linux-arm-gnueabihf": "0.5.29", "@libsql/linux-arm-musleabihf": "0.5.29", "@libsql/linux-arm64-gnu": "0.5.29", "@libsql/linux-arm64-musl": "0.5.29", "@libsql/linux-x64-gnu": "0.5.29", "@libsql/linux-x64-musl": "0.5.29", "@libsql/win32-x64-msvc": "0.5.29" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "arm", "x64", "arm64", ] }, "sha512-8lMP8iMgiBzzoNbAPQ59qdVcj6UaE/Vnm+fiwX4doX4Narook0a4GPKWBEv+CR8a1OwbfkgL18uBfBjWdF0Fzg=="], - "listr2": ["listr2@10.2.1", "", { "dependencies": { "cli-truncate": "^5.2.0", "eventemitter3": "^5.0.4", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^10.0.0" } }, "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q=="], + "lint-staged": ["lint-staged@17.1.0", "", { "dependencies": { "picomatch": "^4.0.5", "string-argv": "^0.3.2", "tinyexec": "^1.2.4" }, "optionalDependencies": { "yaml": "^2.9.0" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-d7UQRu/9ZPgfu4+hu/k0wny5GEaIxo+2jb2LJqQDkE7cHRTm1HGqNUDq5UOwsGPpjpaNAFmgAsYo3TR+i9cSJw=="], "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], - "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="], - "loglevel": ["loglevel@1.9.2", "", {}, "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg=="], "lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="], @@ -1034,8 +1047,6 @@ "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="], - "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], "microdiff": ["microdiff@1.5.0", "", {}, "sha512-Drq+/THMvDdzRYrK0oxJmOKiC24ayUV8ahrt8l3oRK51PWt6gdtrIGrlIH3pT/lFh1z93FbAcidtsHcWbnRz8Q=="], @@ -1046,8 +1057,6 @@ "mime-types": ["mime-types@3.0.1", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA=="], - "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], - "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], @@ -1066,7 +1075,7 @@ "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], - "next": ["next@16.3.0-canary.90", "", { "dependencies": { "@next/env": "16.3.0-canary.90", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.5.10", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.3.0-canary.90", "@next/swc-darwin-x64": "16.3.0-canary.90", "@next/swc-linux-arm64-gnu": "16.3.0-canary.90", "@next/swc-linux-arm64-musl": "16.3.0-canary.90", "@next/swc-linux-x64-gnu": "16.3.0-canary.90", "@next/swc-linux-x64-musl": "16.3.0-canary.90", "@next/swc-win32-arm64-msvc": "16.3.0-canary.90", "@next/swc-win32-x64-msvc": "16.3.0-canary.90", "sharp": "^0.34.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-tnu3Axp/KEbM2iVMcuV/41F3DjT+PPQiXEzwz6ZpGU0C3Sz7g6awAbCWmJb/r8ghtGEnBiPc8WZZaQAj03gImg=="], + "next": ["next@16.3.0-canary.95", "", { "dependencies": { "@next/env": "16.3.0-canary.95", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.5.10", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.3.0-canary.95", "@next/swc-darwin-x64": "16.3.0-canary.95", "@next/swc-linux-arm64-gnu": "16.3.0-canary.95", "@next/swc-linux-arm64-musl": "16.3.0-canary.95", "@next/swc-linux-x64-gnu": "16.3.0-canary.95", "@next/swc-linux-x64-musl": "16.3.0-canary.95", "@next/swc-win32-arm64-msvc": "16.3.0-canary.95", "@next/swc-win32-x64-msvc": "16.3.0-canary.95", "sharp": "^0.35.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-mn1khWEWLRxO+CD7HSRHvBAS/WBw0+av4cvyIPCOW+tjKS9Pg8PpJIhw+F+7cQshVa6DIQMg2uz/59CEOT8B5A=="], "next-devtools-mcp": ["next-devtools-mcp@0.4.0", "", { "dependencies": { "@modelcontextprotocol/sdk": "1.25.2", "find-process": "2.0.0", "pid-port": "2.0.0", "undici": "^7.18.2", "zod": "3.25.76" }, "bin": { "next-devtools-mcp": "dist/index.js" } }, "sha512-PTIoi+TihyztSTPkl+YIesL81wU3pRDo6QCg1wgjvLGfBlXv3yamvQyoI8j/I2t7gqDStXoa7jtn/YUdvcBQuw=="], @@ -1076,7 +1085,7 @@ "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="], - "nuqs": ["nuqs@2.9.0", "", { "dependencies": { "@standard-schema/spec": "1.0.0" }, "peerDependencies": { "@remix-run/react": ">=2", "@tanstack/react-router": "^1", "next": ">=14.2.0", "react": ">=18.2.0 || ^19.0.0-0", "react-router": "^5 || ^6 || ^7 || ^8", "react-router-dom": "^5 || ^6 || ^7" }, "optionalPeers": ["@remix-run/react", "@tanstack/react-router", "next", "react-router", "react-router-dom"] }, "sha512-1ckQBhVHaQYjLZ3kWhhH40A32lPJ7TNTQMa2T+SUvl5azyVt7swCQfUXt9xOXJV3YidWq8VHIHcMzVAJ0knRsw=="], + "nuqs": ["nuqs@2.9.1", "", { "dependencies": { "@standard-schema/spec": "1.1.0" }, "peerDependencies": { "@remix-run/react": ">=2", "@tanstack/react-router": "^1", "next": ">=14.2.0", "react": ">=18.2.0 || ^19.0.0-0", "react-router": "^5 || ^6 || ^7 || ^8", "react-router-dom": "^5 || ^6 || ^7" }, "optionalPeers": ["@remix-run/react", "@tanstack/react-router", "next", "react-router", "react-router-dom"] }, "sha512-xctOTExJ/M2lV9NBXTkLMb3vnGBLk/eMuZyiXSbj0jA24H6ie2d7/LJiaA0C30p5XCIWaDTZl5DEF/N2Yo1LCw=="], "nypm": ["nypm@0.6.6", "", { "dependencies": { "citty": "^0.2.2", "pathe": "^2.0.3", "tinyexec": "^1.1.1" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-vRyr0r4cbBapw07Xw8xrj9Teq3o7MUD35rSaTcanDbW+aK2XHDgJFiU6ZTj2GBw7Q12ysdsyFss+Vdz4hQ0Y6Q=="], @@ -1088,21 +1097,17 @@ "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], - "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], - "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], - "os-paths": ["os-paths@4.4.0", "", {}, "sha512-wrAwOeXp1RRMFfQY8Sy7VaGVmPocaLwSFOYCGKSyo8qmJ+/yaafCl5BCA1IQZWqFSRBrKDYFeR9d/VyQzfH/jg=="], - "oxc-parser": ["oxc-parser@0.138.0", "", { "dependencies": { "@oxc-project/types": "^0.138.0" }, "optionalDependencies": { "@oxc-parser/binding-android-arm-eabi": "0.138.0", "@oxc-parser/binding-android-arm64": "0.138.0", "@oxc-parser/binding-darwin-arm64": "0.138.0", "@oxc-parser/binding-darwin-x64": "0.138.0", "@oxc-parser/binding-freebsd-x64": "0.138.0", "@oxc-parser/binding-linux-arm-gnueabihf": "0.138.0", "@oxc-parser/binding-linux-arm-musleabihf": "0.138.0", "@oxc-parser/binding-linux-arm64-gnu": "0.138.0", "@oxc-parser/binding-linux-arm64-musl": "0.138.0", "@oxc-parser/binding-linux-ppc64-gnu": "0.138.0", "@oxc-parser/binding-linux-riscv64-gnu": "0.138.0", "@oxc-parser/binding-linux-riscv64-musl": "0.138.0", "@oxc-parser/binding-linux-s390x-gnu": "0.138.0", "@oxc-parser/binding-linux-x64-gnu": "0.138.0", "@oxc-parser/binding-linux-x64-musl": "0.138.0", "@oxc-parser/binding-openharmony-arm64": "0.138.0", "@oxc-parser/binding-wasm32-wasi": "0.138.0", "@oxc-parser/binding-win32-arm64-msvc": "0.138.0", "@oxc-parser/binding-win32-ia32-msvc": "0.138.0", "@oxc-parser/binding-win32-x64-msvc": "0.138.0" } }, "sha512-c25lvfpZ2+WY1yk6NkP0X0RTQg0ZxgSVaZHDa7lt6fEe1jwZjPWkRWvTyZ1xyaM7roVJMdtRCfbhUj/d4ims3Q=="], "oxc-resolver": ["oxc-resolver@11.24.2", "", { "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.24.2", "@oxc-resolver/binding-android-arm64": "11.24.2", "@oxc-resolver/binding-darwin-arm64": "11.24.2", "@oxc-resolver/binding-darwin-x64": "11.24.2", "@oxc-resolver/binding-freebsd-x64": "11.24.2", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.24.2", "@oxc-resolver/binding-linux-arm-musleabihf": "11.24.2", "@oxc-resolver/binding-linux-arm64-gnu": "11.24.2", "@oxc-resolver/binding-linux-arm64-musl": "11.24.2", "@oxc-resolver/binding-linux-ppc64-gnu": "11.24.2", "@oxc-resolver/binding-linux-riscv64-gnu": "11.24.2", "@oxc-resolver/binding-linux-riscv64-musl": "11.24.2", "@oxc-resolver/binding-linux-s390x-gnu": "11.24.2", "@oxc-resolver/binding-linux-x64-gnu": "11.24.2", "@oxc-resolver/binding-linux-x64-musl": "11.24.2", "@oxc-resolver/binding-openharmony-arm64": "11.24.2", "@oxc-resolver/binding-wasm32-wasi": "11.24.2", "@oxc-resolver/binding-win32-arm64-msvc": "11.24.2", "@oxc-resolver/binding-win32-x64-msvc": "11.24.2" } }, "sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw=="], "oxlint": ["oxlint@1.66.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.66.0", "@oxlint/binding-android-arm64": "1.66.0", "@oxlint/binding-darwin-arm64": "1.66.0", "@oxlint/binding-darwin-x64": "1.66.0", "@oxlint/binding-freebsd-x64": "1.66.0", "@oxlint/binding-linux-arm-gnueabihf": "1.66.0", "@oxlint/binding-linux-arm-musleabihf": "1.66.0", "@oxlint/binding-linux-arm64-gnu": "1.66.0", "@oxlint/binding-linux-arm64-musl": "1.66.0", "@oxlint/binding-linux-ppc64-gnu": "1.66.0", "@oxlint/binding-linux-riscv64-gnu": "1.66.0", "@oxlint/binding-linux-riscv64-musl": "1.66.0", "@oxlint/binding-linux-s390x-gnu": "1.66.0", "@oxlint/binding-linux-x64-gnu": "1.66.0", "@oxlint/binding-linux-x64-musl": "1.66.0", "@oxlint/binding-openharmony-arm64": "1.66.0", "@oxlint/binding-win32-arm64-msvc": "1.66.0", "@oxlint/binding-win32-ia32-msvc": "1.66.0", "@oxlint/binding-win32-x64-msvc": "1.66.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.22.1" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-N4LLxYLd94KEBqXDMDM5f+2PUpItTjDLreXe2Gn5KhjhCK4Qp2YUXaBi8Yu325ryOgKwt22m45fpD7nPOn69Yw=="], - "oxlint-plugin-react-doctor": ["oxlint-plugin-react-doctor@0.7.8", "", { "dependencies": { "@typescript-eslint/types": "^8.59.3", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "oxc-parser": "^0.138.0" } }, "sha512-3f9/jFLIC/KRLPYqxiXSk20cq47luGy9Oz5Ru7nK7w0EI9B9zuMvAU92bK9jFiwFE7Lc9PA8ER6Y+naYaGFQGw=="], + "oxlint-plugin-react-doctor": ["oxlint-plugin-react-doctor@0.8.1", "", { "dependencies": { "@typescript-eslint/types": "^8.59.3", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "oxc-parser": "^0.138.0" } }, "sha512-ETjgoKrY0EYpK51BsbvgpWySkWaLgJ6z7yB/BfOosi+TUY4+GiDmhWfjJCeul+tpDJEFKR5MnpENjlUrmtZ5Dw=="], "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], @@ -1140,7 +1145,7 @@ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], + "picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], "pid-port": ["pid-port@2.0.0", "", { "dependencies": { "execa": "^9.6.0" } }, "sha512-EDmfRxLl6lkhPjDI+19l5pkII89xVsiCP3aGjS808f7M16DyCKSXEWthD/hjyDLn5I4gKqTVw7hSgdvdXRJDTw=="], @@ -1166,6 +1171,8 @@ "pretty-ms": ["pretty-ms@9.3.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ=="], + "promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="], + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], @@ -1180,11 +1187,11 @@ "raw-body": ["raw-body@3.0.1", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.7.0", "unpipe": "1.0.0" } }, "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA=="], - "react": ["react@19.3.0-canary-e92ecef2-20260618", "", {}, "sha512-fjuMHXWsq/Rq58hQE6BwJGLUX3y+VByekEzN2GA88ScNqocMqeu+ATU/PwSmS3h58ekpPyFZht/TP6bxfumdKg=="], + "react": ["react@19.3.0-canary-172742b4-20260716", "", {}, "sha512-afqEHgpZtxeMgojThLzvSq0y6O5FLjJHFv+o32+U1dKWYCUau2H0H2BjvDubte+GR4lcuJZXUa6aJNl2ZmhrRg=="], - "react-doctor": ["react-doctor@0.7.8", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@sentry/node": "^10.54.0", "agent-install": "0.0.5", "conf": "^15.1.0", "confbox": "^0.2.4", "deslop-js": "0.7.8", "eslint-plugin-react-hooks": "^7.1.1", "jiti": "^2.7.0", "magicast": "^0.5.3", "oxlint": ">=1.66.0 <1.67.0", "oxlint-plugin-react-doctor": "0.7.8", "prompts": "^2.4.2", "typescript": ">=5.0.4 <6", "vscode-languageserver": "^9.0.1", "vscode-languageserver-textdocument": "^1.0.12", "vscode-uri": "^3.1.0", "yaml": "^2.9.0" }, "bin": { "react-doctor": "bin/react-doctor.js" } }, "sha512-G3spmtZJE/gWWPRJ3rpgUWTPRDJpEmdRja7iNZ7RAXlfpEO+NWVzPTca/cPI9hLwPo2Aq5/BZggo5JDBrwGrlA=="], + "react-doctor": ["react-doctor@0.8.1", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@sentry/node": "^10.54.0", "agent-install": "0.0.5", "conf": "^15.1.0", "confbox": "^0.2.4", "deslop-js": "0.8.1", "eslint-plugin-react-hooks": "^7.1.1", "jiti": "^2.7.0", "magicast": "^0.5.3", "oxlint": ">=1.66.0 <1.67.0", "oxlint-plugin-react-doctor": "0.8.1", "prompts": "^2.4.2", "typescript": ">=5.0.4 <6", "vscode-languageserver": "^9.0.1", "vscode-languageserver-textdocument": "^1.0.12", "vscode-uri": "^3.1.0", "yaml": "^2.9.0" }, "bin": { "react-doctor": "bin/react-doctor.js" } }, "sha512-lP/MaS7dDMeVFpWBjh8qYp6NYcb/1TmsAwSixqkqOI50fea9kfh89fyn+UUAC3vb53FGIqwvDPZIjlJR6BgGAQ=="], - "react-dom": ["react-dom@19.3.0-canary-e92ecef2-20260618", "", { "dependencies": { "scheduler": "0.28.0-canary-e92ecef2-20260618" }, "peerDependencies": { "react": "19.3.0-canary-e92ecef2-20260618" } }, "sha512-usTeNj9is1bqa2fiBccMoZsELEoirmSOcxk3sahW4NzZ5koxB/H0p+KD0kOr4TF/OoH0FLo3XueWyOlFrQhcAg=="], + "react-dom": ["react-dom@19.3.0-canary-172742b4-20260716", "", { "dependencies": { "scheduler": "0.28.0-canary-172742b4-20260716" }, "peerDependencies": { "react": "19.3.0-canary-172742b4-20260716" } }, "sha512-ci1PDujiNFn+k+ElxM0rTUqsPL08/XG5gnNBopY6lyGxEP64QVpUUgdHYZ5ABEjollk9iPZwV8hnbidA/G5UAw=="], "react-icons": ["react-icons@5.7.0", "", { "peerDependencies": { "react": "*" } }, "sha512-LBLy340Rzqy6+/yVhZKT3B/QpP1BZaesGqasf09HPOBzRarcDIFH0WwXlXQfE7q7ipxK4MSiC5DIBWURCny6fw=="], @@ -1196,12 +1203,8 @@ "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], - "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], - "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - "rolldown": ["rolldown@1.0.0-rc.17", "", { "dependencies": { "@oxc-project/types": "=0.127.0", "@rolldown/pluginutils": "1.0.0-rc.17" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-arm64": "1.0.0-rc.17", "@rolldown/binding-darwin-x64": "1.0.0-rc.17", "@rolldown/binding-freebsd-x64": "1.0.0-rc.17", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA=="], "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="], @@ -1214,7 +1217,7 @@ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], - "scheduler": ["scheduler@0.28.0-canary-e92ecef2-20260618", "", {}, "sha512-BaTh9NgTqsrqt75sdZUPilK4EWMRaXNt7G86uyQefyXc4eGiJBqJyBJU3Y7b+DedO6zyFq4KFzAsV+8HrqFarg=="], + "scheduler": ["scheduler@0.28.0-canary-172742b4-20260716", "", {}, "sha512-Yq6JvoECOViPRlc2Ks5E6XpSNOJcG+Msou/iFQmmHMZ4o7siBc+PSNWoJRULEnv/jaMw9So+BHRjalje994Xhg=="], "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], @@ -1226,7 +1229,7 @@ "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], - "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], + "sharp": ["sharp@0.35.3", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.5" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.3", "@img/sharp-darwin-x64": "0.35.3", "@img/sharp-freebsd-wasm32": "0.35.3", "@img/sharp-libvips-darwin-arm64": "1.3.2", "@img/sharp-libvips-darwin-x64": "1.3.2", "@img/sharp-libvips-linux-arm": "1.3.2", "@img/sharp-libvips-linux-arm64": "1.3.2", "@img/sharp-libvips-linux-ppc64": "1.3.2", "@img/sharp-libvips-linux-riscv64": "1.3.2", "@img/sharp-libvips-linux-s390x": "1.3.2", "@img/sharp-libvips-linux-x64": "1.3.2", "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", "@img/sharp-libvips-linuxmusl-x64": "1.3.2", "@img/sharp-linux-arm": "0.35.3", "@img/sharp-linux-arm64": "0.35.3", "@img/sharp-linux-ppc64": "0.35.3", "@img/sharp-linux-riscv64": "0.35.3", "@img/sharp-linux-s390x": "0.35.3", "@img/sharp-linux-x64": "0.35.3", "@img/sharp-linuxmusl-arm64": "0.35.3", "@img/sharp-linuxmusl-x64": "0.35.3", "@img/sharp-webcontainers-wasm32": "0.35.3", "@img/sharp-win32-arm64": "0.35.3", "@img/sharp-win32-ia32": "0.35.3", "@img/sharp-win32-x64": "0.35.3" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], @@ -1244,8 +1247,6 @@ "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], - "slice-ansi": ["slice-ansi@8.0.0", "", { "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" } }, "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg=="], - "slugify": ["slugify@1.6.9", "", {}, "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], @@ -1256,9 +1257,9 @@ "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], - "string-width": ["string-width@8.2.1", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA=="], + "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], - "strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], @@ -1340,16 +1341,10 @@ "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], - "wrap-ansi": ["wrap-ansi@10.0.0", "", { "dependencies": { "ansi-styles": "^6.2.3", "string-width": "^8.2.0", "strip-ansi": "^7.1.2" } }, "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ=="], - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], - "xdg-app-paths": ["xdg-app-paths@5.5.1", "", { "dependencies": { "os-paths": "^4.0.1", "xdg-portable": "^7.2.0" } }, "sha512-hI3flOB4PLZIy5prbtTpirobtPE2ZtZ52szO+2mM9Efp6ErM398La+C1lIpNWDfNoQk+6Lsi6nMcCwVB7pxeMQ=="], - - "xdg-portable": ["xdg-portable@7.3.0", "", { "dependencies": { "os-paths": "^4.0.1" } }, "sha512-sqMMuL1rc0FmMBOzCpd0yuy9trqF2yTTVe+E9ogwCSWQCdDEtQUwrZPT6AxqtsFGRNxycgncbP/xmOOSPw5ZUw=="], - "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], @@ -1398,13 +1393,11 @@ "@better-auth/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.41.1", "", {}, "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA=="], - "@better-auth/core/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - "@better-auth/utils/@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], + "@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="], "@modelcontextprotocol/sdk/jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="], @@ -1414,6 +1407,8 @@ "@oxc-resolver/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="], + "@pandacss/cli/@clack/prompts": ["@clack/prompts@1.7.0", "", { "dependencies": { "@clack/core": "1.4.3", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A=="], + "@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], "@rolldown/binding-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], @@ -1428,10 +1423,6 @@ "@types/ws/@types/node": ["@types/node@25.3.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A=="], - "@vercel/cli-exec/execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="], - - "@vercel/oidc/jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="], - "agent-install/commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], "agent-install/yaml": ["yaml@2.8.4", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog=="], @@ -1458,12 +1449,6 @@ "import-in-the-middle/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - "is-fullwidth-code-point/get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="], - - "log-update/slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="], - - "log-update/wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], - "magicast/@babel/parser": ["@babel/parser@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" }, "bin": "./bin/babel-parser.js" }, "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg=="], "magicast/@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="], @@ -1478,23 +1463,19 @@ "react-doctor/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], - "rolldown/@oxc-project/types": ["@oxc-project/types@0.127.0", "", {}, "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ=="], "router/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "send/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + "sharp/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "strip-ansi/ansi-regex": ["ansi-regex@6.2.0", "", {}, "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg=="], + "sharp/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], - "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - "wrap-ansi/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + "tinyglobby/picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], "@babel/core/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], @@ -1510,6 +1491,8 @@ "@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], + "@pandacss/cli/@clack/prompts/@clack/core": ["@clack/core@1.4.3", "", { "dependencies": { "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ=="], + "@rolldown/binding-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], "@rolldown/binding-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], @@ -1518,32 +1501,8 @@ "@types/ws/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], - "@vercel/cli-exec/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], - - "@vercel/cli-exec/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], - - "@vercel/cli-exec/execa/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], - - "@vercel/cli-exec/execa/npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="], - - "@vercel/cli-exec/execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - - "@vercel/cli-exec/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="], - "eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "log-update/slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "log-update/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "log-update/wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], - "magicast/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], - - "string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - - "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - - "log-update/wrap-ansi/string-width/get-east-asian-width": ["get-east-asian-width@1.3.0", "", {}, "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ=="], } } diff --git a/bunfig.toml b/bunfig.toml index ba2a61c..1703fd7 100644 --- a/bunfig.toml +++ b/bunfig.toml @@ -8,9 +8,26 @@ minimumReleaseAgeExcludes = [ "next", "@next/swc-linux-x64-gnu", "@next/swc-linux-x64-musl", + "@pandacss/cli", + "@pandacss/compiler", + "@pandacss/compiler-darwin-arm64", + "@pandacss/compiler-darwin-x64", + "@pandacss/compiler-linux-arm64-gnu", + "@pandacss/compiler-linux-arm64-musl", + "@pandacss/compiler-linux-x64-gnu", + "@pandacss/compiler-linux-x64-musl", + "@pandacss/compiler-shared", + "@pandacss/compiler-wasm", + "@pandacss/compiler-wasm32-wasi", + "@pandacss/compiler-win32-arm64-msvc", + "@pandacss/compiler-win32-x64-msvc", + "@pandacss/config", "@pandacss/dev", + "@pandacss/postcss", "@pandacss/preset-base", - "@pandacss/preset-panda" + "@pandacss/preset-panda", + "@pandacss/preset-typography", + "@pandacss/types", ] [test] diff --git a/docs/AUTH_SETUP.md b/docs/AUTH_SETUP.md index 3962464..7a0ad9f 100644 --- a/docs/AUTH_SETUP.md +++ b/docs/AUTH_SETUP.md @@ -20,18 +20,22 @@ All environment variables are validated using Valibot in `src/utils/env.ts`. Cre # Site Configuration NEXT_PUBLIC_SITE_URL="http://localhost:3000" # or your production URL -# Better Auth Configuration -AUTH_SECRET="your-secret-key-here-change-this-in-production" +# Better Auth +BETTER_AUTH_SECRET="your-secret-key-here-change-this-in-production" # GitHub OAuth GITHUB_CLIENT_ID="your-github-client-id" GITHUB_CLIENT_SECRET="your-github-client-secret" -# Database +# Turso (libSQL) +TURSO_DATABASE_URL="libsql://your-db.turso.io" +TURSO_DATABASE_AUTH="your-turso-auth-token" + +# Legacy Neon URL (kept in .env.schema; unused by app) DATABASE_URL="your-neon-database-connection-string" ``` -**Note**: The client-side auth client uses `NEXT_PUBLIC_SITE_URL` for `baseURL`. +**Note**: The client-side auth client uses `NEXT_PUBLIC_SITE_URL` for `baseURL`. Auth tables: `bun run auth:generate` (writes `src/db/schema/auth.ts` from `src/lib/auth.cli.config.ts`), then `bun run db:generate` / `db:migrate`. Runtime auth (secrets, OAuth, cookies) lives in `src/lib/auth.ts` (`server-only`). ## How to Get GitHub OAuth Credentials diff --git a/docs/VARLOCK.md b/docs/VARLOCK.md index 01c7cd4..e8036e8 100644 --- a/docs/VARLOCK.md +++ b/docs/VARLOCK.md @@ -11,7 +11,7 @@ This note summarizes how [Varlock](https://varlock.dev/) fits a Next.js app on * - **`.env.schema`** as a single, AI-safe description of config (names, types, validation) without exposing secret values. - **Validation, optional type generation**, log redaction, `varlock scan` for leaks, and **`varlock run`** to inject resolved env into arbitrary commands. -- **Next.js**: replaces internal [`@next/env`](https://www.npmjs.com/package/@next/env) loading via **`@varlock/nextjs-integration`** plus a small **`next.config`** plugin. +- **Next.js**: replaces internal `[@next/env](https://www.npmjs.com/package/@next/env)` loading via **`@varlock/nextjs-integration`** plus a small **`next.config`** plugin. ## Recommended integration path (high level) @@ -40,8 +40,10 @@ Varlock’s Bitwarden integration targets **Bitwarden Secrets Manager** (organiz # @type=bitwardenAccessToken @sensitive BITWARDEN_ACCESS_TOKEN= -# Example: load a DB URL from Secrets Manager by secret UUID -# DATABASE_URL=bitwarden("12345678-1234-1234-1234-123456789abc") +# Example: load Turso URL from Secrets Manager by secret UUID +# TURSO_DATABASE_URL=bitwarden("12345678-1234-1234-1234-123456789abc") +# TURSO_DATABASE_AUTH=bitwarden("12345678-1234-1234-1234-123456789abc") +# Legacy Neon (unused by app): DATABASE_URL=bitwarden("…") ``` Install the package **`@varlock/bitwarden-plugin`** as a dependency, or load the plugin from the schema with a version per the [plugins installation](https://varlock.dev/guides/plugins/#installation) docs. @@ -98,7 +100,7 @@ Per [Varlock’s Bun docs](https://varlock.dev/integrations/bun/): ### Caveats - **Bootstrap tokens** (e.g. **`BITWARDEN_ACCESS_TOKEN`**) must be present where Varlock runs (local shell, Vercel env, CI). They are not fetched from Bitwarden by magic without configuration. -- **`varlock run` in production**: The [standalone mode](https://varlock.dev/integrations/nextjs/) section notes that **standalone** output needs copying `.env.*` and running with the **varlock CLI** installed. This repo does **not** use `output: 'standalone'` today; if you add it later, follow Varlock’s standalone instructions. +- **`varlock run` in production**: The [standalone mode](https://varlock.dev/integrations/nextjs/) section notes that **standalone** output needs copying `.env.`* and running with the **varlock CLI** installed. This repo does **not** use `output: 'standalone'` today; if you add it later, follow Varlock’s standalone instructions. - **Branch-based logic**: For finer control than `VERCEL_ENV`, the docs point at **`VERCEL_GIT_COMMIT_REF`** and similar—useful if schema composition depends on branch name. ## Friction with the **current** tech stack @@ -123,7 +125,7 @@ Public client vars use **`NEXT_PUBLIC_SITE_URL`** as the canonical app URL. Varl ### 3. **Tools outside Next: Drizzle, Playwright, scripts** -- **`drizzle.config.ts`** reads **`process.env.DATABASE_URL`** directly. Drizzle CLI does not use `next.config`; ensure **`DATABASE_URL`** is available when running **`drizzle-kit`** (shell env, `.env`, or `varlock run -- bun x drizzle-kit ...`). +- **`drizzle.config.ts`** reads **`TURSO_DATABASE_URL`** + **`TURSO_DATABASE_AUTH`** via Varlock. Drizzle CLI does not use `next.config`; run kit via **`varlock run -- bun x drizzle-kit ...`** (or the `db:`* scripts). Legacy **`DATABASE_URL`** remains in `.env.schema` unused. - **`playwright.config.ts`** and **`tests/setup/test-preload.ts`** set or assume env. After Varlock + optional `bunfig` changes, re-verify **e2e** and **unit** runs. - **`db:seed`**, **`db:drop`**, etc. use **`bun --conditions=react-server`**: confirm env loading matches expectations once Bun auto-env is disabled. diff --git a/drizzle.config.ts b/drizzle.config.ts index 6630bef..15e2e33 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -2,11 +2,13 @@ import { defineConfig } from "drizzle-kit"; import { ENV } from "varlock/env"; + export default defineConfig({ dbCredentials: { - url: ENV.DATABASE_URL, + authToken: ENV.TURSO_DATABASE_AUTH, + url: ENV.TURSO_DATABASE_URL, }, - dialect: "postgresql", + dialect: "turso", out: "./src/db/migrations", schema: "./src/db/schema/*.ts", strict: true, diff --git a/git-pull-request.md b/git-pull-request.md new file mode 100644 index 0000000..a0321bc --- /dev/null +++ b/git-pull-request.md @@ -0,0 +1,279 @@ +# How to Open a Pull Request (AI Runnable) + +Provide this file (and ideally `git-commit-msg.md`) to have the AI: branch → commit → push → open a PR. Commit messages follow [`git-commit-msg.md`](./git-commit-msg.md). PR title/body derive from those commits (and the full branch diff). + +## What the AI will do + +1. Inspect working tree / branch vs base (`master`) +2. Create a branch if needed (or use current topic branch) +3. Generate commit message via `git-commit-msg.md`, then commit +4. Push branch to `origin` with upstream tracking +5. Open a PR with `gh pr create` — title + body derived from the commit(s) + +## Prerequisites + +- Attach **both** when possible: + - `git-commit-msg.md` — commit message format (required for step 3) + - `git-pull-request.md` — this file (branch / push / PR) +- User must explicitly ask to open a PR / push / commit (or paste the quick prompt below). Do not push or create a PR unless instructed. +- Base branch defaults to `master` unless the user names another. + +--- + +## Workflow (run in order) + +### 1. Inspect state + +Run in parallel: + +```bash +git status +git diff && git diff --cached +git diff --stat HEAD +git branch -vv +git rev-parse --abbrev-ref HEAD +git rev-parse --abbrev-ref @{upstream} 2>/dev/null || true +git log -5 --oneline +git log master..HEAD --oneline # commits already on branch (if any) +git diff master...HEAD --stat # full PR-bound diff once commits exist +``` + +Decide: + +| Situation | Action | +|-----------|--------| +| Uncommitted changes | Stage + commit (step 3) before push/PR | +| On `master` / `main` with changes | Create topic branch first (step 2) | +| Already on topic branch, clean, ahead of remote | Push + PR (steps 4–5) | +| No changes and no commits ahead of base | Stop — nothing to PR | + +### 2. Create / switch branch + +Prefer `git switch` over `git checkout` (branch moves only — safer, no path/restore confusion). + +If still on `master` (or user asks for a new branch): + +```bash +git switch -c / +``` + +If switching onto an existing topic branch (no create): + +```bash +git switch / +``` + +Branch naming: + +- Prefix with commit type: `feat/`, `fix/`, `refactor/`, `docs/`, `chore/`, `perf/`, `ci/`, `build/` +- Short kebab case from the main change: `feat/form-status-button`, `fix/auth-redirect` +- Match the `type:` that will lead the commit message + +If already on a good topic branch, keep it. + +Do **not** use `git checkout -b` / bare `git checkout ` here. Use `git restore` / `git restore --staged` only if discarding or unstaging file changes (rare in this workflow; never confuse with branch switch). + +### 3. Commit (use `git-commit-msg.md`) + +**Follow [`git-commit-msg.md`](./git-commit-msg.md) exactly** — do not invent a different commit style. + +1. Analyze staged + unstaged diffs (and `--stat`) +2. Produce message: `type:` + newline + emoji bullets (scale by file count per that file) +3. Stage relevant files (never secrets: `.env`, credentials, etc.) +4. Commit with HEREDOC: + +```bash +git add +git commit -m "$(cat <<'EOF' +type: +emoji bullet one +emoji bullet two +EOF +)" +git status +``` + +Rules (same as commit guide + safety): + +- Never `--no-verify` / skip hooks unless user asks +- Never amend unless user asks and amend safety rules pass +- Never update git config +- If pre-commit fails: fix, then **new** commit (do not amend failed commit) + +If multiple logical commits already exist on the branch, keep them; do not squash unless asked. Still use `git-commit-msg.md` for any **new** commit. + +### 4. Push to remote + +```bash +git push -u origin HEAD +``` + +- First push on a branch: always `-u` / `--set-upstream` (same thing) +- Later pushes on same branch: `git push` is enough (upstream already set) +- Prefer `HEAD` over hard-coding the branch name — tracks whatever is checked out +- Never force-push to `master`/`main` +- Never `--force` / `--force-with-lease` unless user explicitly requests + +### 5. Create PR title and description + +**Source of truth (in priority order):** + +1. Commit messages on the branch (`git log master..HEAD`) — already in `git-commit-msg.md` format +2. Full diff vs base (`git diff master...HEAD`) — for anything commits understate +3. Prefer synthesizing from commits; do not ignore extra commits or drift + +#### PR title + +- One line, ≤ ~72 chars preferred +- Pattern: `: ` +- Use the **same type** as the primary / most impactful commit (`feat`, `fix`, `refactor`, …) +- Summary = compressed why/what of the branch — **no emoji in the title** +- If one commit: title can mirror that commit’s type + first-bullet gist +- If many commits: pick dominant type; summarize the theme (not a comma-list of every bullet) + +Examples: + +```text +feat: shared StatusButton form submit feedback +fix: safe redirectTo on login after host auth fail +refactor: flatten D1 migrations while keeping snapshots +``` + +#### PR body + +Always use this structure (HEREDOC for `gh`): + +```markdown +## Summary +- +- +- + +## Test plan +- [ ] +- [ ] +``` + +**Summary bullets:** + +- Derive from emoji bullets across branch commits (and diff if needed) +- Strip leading emojis in Summary (or keep them — prefer **keep emojis** so PR body matches commit style) +- Keep the same priority order: most impactful first +- Scale like commits: + - 1 commit / small: 2–3 bullets + - Medium: 3–4 + - Large / multi-commit: 5–7 (cap ~8; consolidate noise) +- Do **not** paste the raw `type:` line into Summary; type belongs in the title + +**Test plan:** + +- Checklist of real verification steps for this diff (UI paths, `bun run typecheck` / `bun run check`, migrate/seed if schema changed, etc.) +- Prefer actionable `bun` / UI steps over vague “test everything” + +### 6. Open the PR + +```bash +gh pr create --title ": " --body "$(cat <<'EOF' +## Summary +✨ … +🎨 … +🔧 … + +## Test plan +- [ ] … +- [ ] … + +EOF +)" +``` + +After create: + +- Return the PR URL to the user +- Do not merge unless asked + +Optional flags (only if user asks): + +- `--draft` +- `--base ` +- `--reviewer ` + +--- + +## Mapping: commit message → PR + +| Commit (`git-commit-msg.md`) | Pull request | +|------------------------------|--------------| +| Leading `feat:` / `fix:` / … | Title prefix `feat:` / `fix:` / … | +| Emoji bullet lines | Summary bullets (same emojis, same order) | +| Multiple commits on branch | Merge themes into one title type; union bullets, dedupe | +| File-count scaling for bullets | Same scaling for Summary length | +| Common emoji meanings | Reuse from `git-commit-msg.md` | + +**Single-commit PR (ideal):** + +Commit: + +```text +feat: +✨ Added FormActionResult and StatusButton helpers +🎨 Wired auth and host forms to fetcher status +📝 Synced README badges and scripts +``` + +PR title: + +```text +feat: shared StatusButton form submit feedback +``` + +PR body Summary: + +```markdown +## Summary +✨ Added FormActionResult and StatusButton helpers +🎨 Wired auth and host forms to fetcher status +📝 Synced README badges and scripts +``` + +**Multi-commit PR:** fold bullets under one dominant type; drop duplicate themes. + +--- + +## Safety / do-not + +- Do not commit or push secrets +- Do not force-push `master`/`main` +- Do not open a PR with an empty Summary or empty Test plan +- Do not use Interactive git (`-i`) +- Do not use `git checkout` for branch create/switch — use `git switch` / `git switch -c` +- Do not rewrite published history unless user asks +- If push/PR fails on auth/network: report error; do not invent a “successful” URL + +--- + +## Quick prompt you can paste + +Copy into chat with `git-commit-msg.md` + this file attached: + +``` +Follow git-commit-msg.md and git-pull-request.md: inspect changes, git switch -c a topic branch if on master, commit using the emoji commit format, push -u to origin, and open a gh PR. Derive the PR title (type: summary, no emoji) and Summary bullets from the commit message(s); add a concrete Test plan. Return the PR URL. +``` + +Partial prompts: + +- Commit only: attach `git-commit-msg.md` only (or say “commit only”) +- PR only (already pushed): “open PR from current branch using git-pull-request.md” +- Draft PR: add “create as draft” + +--- + +## Post-create checklist (AI) + +- [ ] Branch not `master`/`main` +- [ ] Commit(s) follow `git-commit-msg.md` +- [ ] Remote tracking set (`-u` on first push) +- [ ] PR title = `type: summary` (no emoji) +- [ ] PR Summary bullets align with commit bullets +- [ ] Test plan present with checkboxes +- [ ] User received PR URL diff --git a/lint-staged.config.ts b/lint-staged.config.ts index e2b6d8b..bb4df41 100644 --- a/lint-staged.config.ts +++ b/lint-staged.config.ts @@ -3,7 +3,11 @@ import type { Configuration } from "lint-staged"; const config = { "*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}": ["bun fix"], // Function form = once per commit (not once per file). --staged = git index only. - "*.{ts,tsx}": () => ["bun run type", "bun run react-doctor:staged"], + "*.{ts,tsx}": () => [ + "bun run type", + "bun run react-doctor:staged", + "bun run test", + ], } satisfies Configuration; export default config; diff --git a/next.config.ts b/next.config.ts index 6855c7a..ce57af1 100644 --- a/next.config.ts +++ b/next.config.ts @@ -17,7 +17,6 @@ const nextConfig: NextConfig = { turbopackRustReactCompiler: true, // TypeScript 7 has no JS compiler API; next build uses project-local `tsc` instead useTypeScriptCli: true, - viewTransition: true, }, images: { remotePatterns: [ diff --git a/package.json b/package.json index ed1b8d5..a94b7ed 100644 --- a/package.json +++ b/package.json @@ -3,18 +3,17 @@ "@better-auth/drizzle-adapter": "1.7.0-rc.1", "@elysiajs/cors": "^1.4.2", "@elysiajs/openapi": "^1.4.15", + "@libsql/client": "^0.17.4", "@rsc-boundary/next": "^0.3.2", "@varlock/bitwarden-plugin": "^2.0.0", - "@vercel/functions": "^3.7.5", "babel-plugin-react-compiler": "^1.0.0", "better-auth": "1.7.0-rc.1", "drizzle-orm": "1.0.0-rc.4", "elysia": "^1.4.29", - "next": "16.3.0-canary.90", - "nuqs": "^2.9.0", - "pg": "^8.22.0", - "react": "19.3.0-canary-e92ecef2-20260618", - "react-dom": "19.3.0-canary-e92ecef2-20260618", + "next": "16.3.0-canary.95", + "nuqs": "^2.9.1", + "react": "19.3.0-canary-172742b4-20260716", + "react-dom": "19.3.0-canary-172742b4-20260716", "react-icons": "^5.7.0", "slugify": "^1.6.9", "valibot": "^1.4.2", @@ -22,24 +21,24 @@ }, "devDependencies": { "@biomejs/biome": "2.5.3", - "@happy-dom/global-registrator": "^20.10.6", - "@pandacss/dev": "^2.0.0-beta.8", - "@pandacss/preset-base": "2.0.0-beta.8", - "@pandacss/preset-panda": "2.0.0-beta.8", + "@happy-dom/global-registrator": "^20.11.0", + "@pandacss/dev": "^2.0.0-beta.10", + "@pandacss/preset-base": "2.0.0-beta.10", + "@pandacss/preset-panda": "2.0.0-beta.10", + "@pandacss/preset-typography": "2.0.0-beta.10", "@playwright/test": "^1.61.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@types/bun": "^1.3.14", - "@types/pg": "^8.20.0", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@varlock/nextjs-integration": "^1.1.6", "drizzle-kit": "1.0.0-rc.4", - "happy-dom": "^20.10.6", + "happy-dom": "^20.11.0", "husky": "^9.1.7", - "lint-staged": "^17.0.8", + "lint-staged": "^17.1.0", "next-devtools-mcp": "^0.4.0", - "react-doctor": "^0.7.8", + "react-doctor": "^0.8.1", "typescript": "^7.0.2", "typescript-plugin-directives": "^0.0.3", "ultracite": "7.9.4" @@ -63,6 +62,7 @@ "e2e:codegen": "NODE_ENV=test playwright codegen http://localhost:3000", "typegen": "bun --bun run next typegen && tsc --noEmit", "env:typegen": "varlock typegen", + "auth:generate": "varlock run -- bun x auth@1.7.0-rc.1 generate --config ./src/lib/auth.cli.config.ts --output ./src/db/schema/auth.ts --yes", "db:generate": "varlock run -- bun x drizzle-kit generate", "db:migrate": "varlock run -- bun x drizzle-kit migrate", "db:push": "varlock run -- bun x drizzle-kit push --force", diff --git a/panda-presets/tsconfig.json b/panda-presets/tsconfig.json deleted file mode 100644 index a5ac6b5..0000000 --- a/panda-presets/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "rootDir": "..", - "noEmit": true, - "strictNullChecks": true - }, - "include": ["./**/*.ts", "../panda.config.ts"] -} diff --git a/panda-presets/typography.ts b/panda-presets/typography.ts deleted file mode 100644 index 9bc5b45..0000000 --- a/panda-presets/typography.ts +++ /dev/null @@ -1,1284 +0,0 @@ -import { - definePreset, - defineRecipe, - defineSemanticTokens, -} from "@pandacss/dev"; -import type { RecipeConfig } from "@pandacss/types"; - -/** Static prose preset — vendored from pandacss-preset-typography to avoid v2 config bundling issues with tailwindcss CJS. */ -const proseRecipe = defineRecipe({ - base: { - '& [class~="lead"]': { - color: "var(--colors-prose-lead)", - }, - "& > :first-child": { - marginTop: "0px", - }, - "& > :last-child": { - marginBottom: "0px", - }, - "& a": { - color: "var(--colors-prose-link)", - fontWeight: "500", - textDecoration: "underline", - }, - "& a code": { - color: "inherit", - }, - "& a strong": { - color: "inherit", - }, - "& blockquote": { - borderInlineStartColor: "var(--colors-prose-quote-border)", - borderInlineStartWidth: "0.25rem", - color: "var(--colors-prose-quote)", - fontStyle: "italic", - fontWeight: "500", - quotes: '"\\201C""\\201D""\\2018""\\2019"', - }, - "& blockquote code": { - color: "inherit", - }, - "& blockquote p:first-of-type::before": { - content: "open-quote", - }, - "& blockquote p:last-of-type::after": { - content: "close-quote", - }, - "& blockquote strong": { - color: "inherit", - }, - "& code": { - color: "var(--colors-prose-code)", - fontWeight: "600", - }, - "& code::after": { - content: '"`"', - }, - "& code::before": { - content: '"`"', - }, - "& dt": { - color: "var(--colors-prose-heading)", - fontWeight: "600", - }, - "& figcaption": { - color: "var(--colors-prose-caption)", - }, - "& h1": { - color: "var(--colors-prose-heading)", - fontWeight: "800", - }, - "& h1 code": { - color: "inherit", - }, - "& h1 strong": { - color: "inherit", - fontWeight: "900", - }, - "& h2": { - color: "var(--colors-prose-heading)", - fontWeight: "700", - }, - "& h2 code": { - color: "inherit", - }, - "& h2 strong": { - color: "inherit", - fontWeight: "800", - }, - "& h3": { - color: "var(--colors-prose-heading)", - fontWeight: "600", - }, - "& h3 code": { - color: "inherit", - }, - "& h3 strong": { - color: "inherit", - fontWeight: "700", - }, - "& h4": { - color: "var(--colors-prose-heading)", - fontWeight: "600", - }, - "& h4 code": { - color: "inherit", - }, - "& h4 strong": { - color: "inherit", - fontWeight: "700", - }, - "& hr": { - borderColor: "var(--colors-prose-hr-border)", - borderTopWidth: "1px", - }, - "& kbd": { - boxShadow: - "0 0 0 1px var(--colors-prose-kbd-shadow), 0 3px 0 var(--colors-prose-kbd-shadow)", - color: "var(--colors-prose-kbd)", - fontFamily: "inherit", - fontWeight: "500", - }, - "& ol": { - listStyleType: "decimal", - }, - "& ol > li::marker": { - color: "var(--colors-prose-counter)", - fontWeight: "400", - }, - '& ol[type="1"]': { - listStyleType: "decimal", - }, - '& ol[type="A" s]': { - listStyleType: "upper-alpha", - }, - '& ol[type="A"]': { - listStyleType: "upper-alpha", - }, - '& ol[type="a" s]': { - listStyleType: "lower-alpha", - }, - '& ol[type="a"]': { - listStyleType: "lower-alpha", - }, - '& ol[type="I" s]': { - listStyleType: "upper-roman", - }, - '& ol[type="I"]': { - listStyleType: "upper-roman", - }, - '& ol[type="i" s]': { - listStyleType: "lower-roman", - }, - '& ol[type="i"]': { - listStyleType: "lower-roman", - }, - "& picture": { - display: "block", - }, - "& pre": { - backgroundColor: "var(--colors-prose-pre-bg)", - color: "var(--colors-prose-pre-code)", - fontWeight: "400", - overflowX: "auto", - }, - "& pre code": { - backgroundColor: "transparent", - borderRadius: "0px", - borderWidth: "0px", - color: "inherit", - fontFamily: "inherit", - fontSize: "inherit", - fontWeight: "inherit", - lineHeight: "inherit", - padding: "0px", - }, - "& pre code::after": { - content: "none", - }, - "& pre code::before": { - content: "none", - }, - "& strong": { - color: "var(--colors-prose-bold)", - fontWeight: "600", - }, - "& table": { - marginBottom: "2em", - marginTop: "2em", - tableLayout: "auto", - width: "100%", - }, - "& tbody td": { - verticalAlign: "baseline", - }, - "& tbody tr": { - borderBottomColor: "var(--colors-prose-td-border)", - borderBottomWidth: "1px", - }, - "& tbody tr:last-child": { - borderBottomWidth: "0px", - }, - "& tfoot": { - borderTopColor: "var(--colors-prose-th-border)", - borderTopWidth: "1px", - }, - "& tfoot td": { - verticalAlign: "top", - }, - "& th, & td": { - textAlign: "start", - }, - "& thead": { - borderBottomColor: "var(--colors-prose-th-border)", - borderBottomWidth: "1px", - }, - "& thead th": { - color: "var(--colors-prose-heading)", - fontWeight: "600", - verticalAlign: "bottom", - }, - "& thead th code": { - color: "inherit", - }, - "& thead th strong": { - color: "inherit", - }, - "& ul": { - listStyleType: "disc", - }, - "& ul > li::marker": { - color: "var(--colors-prose-bullet)", - }, - color: "var(--colors-prose-body)", - maxWidth: "65ch", - }, - className: "prose", - defaultVariants: { - size: "base", - }, - description: "Generated using 🐼 pandacss-preset-typography", - variants: { - size: { - "2xl": { - '& [class~="lead"]': { - fontSize: "1.25em", - lineHeight: "1.4666667", - marginBottom: "1.0666667em", - marginTop: "1.0666667em", - }, - "& > ol > li > p:first-child": { - marginTop: "1.3333333em", - }, - "& > ol > li > p:last-child": { - marginBottom: "1.3333333em", - }, - "& > ul > li > p:first-child": { - marginTop: "1.3333333em", - }, - "& > ul > li > p:last-child": { - marginBottom: "1.3333333em", - }, - "& > ul > li p": { - marginBottom: "0.8333333em", - marginTop: "0.8333333em", - }, - "& blockquote": { - marginBottom: "1.7777778em", - marginTop: "1.7777778em", - paddingInlineStart: "1.1111111em", - }, - "& code": { - fontSize: "0.8333333em", - }, - "& dd": { - marginTop: "0.5em", - paddingInlineStart: "1.5833333em", - }, - "& dl": { - marginBottom: "1.3333333em", - marginTop: "1.3333333em", - }, - "& dt": { - marginTop: "1.3333333em", - }, - "& figcaption": { - fontSize: "0.8333333em", - lineHeight: "1.6", - marginTop: "1em", - }, - "& figure": { - marginBottom: "2em", - marginTop: "2em", - }, - "& figure > *": { - marginBottom: "0px", - marginTop: "0px", - }, - "& h1": { - fontSize: "2.6666667em", - lineHeight: "1", - marginBottom: "0.875em", - marginTop: "0px", - }, - "& h2": { - fontSize: "2em", - lineHeight: "1.0833333", - marginBottom: "0.8333333em", - marginTop: "1.5em", - }, - "& h2 + *": { - marginTop: "0px", - }, - "& h2 code": { - fontSize: "0.875em", - }, - "& h3": { - fontSize: "1.5em", - lineHeight: "1.2222222", - marginBottom: "0.6666667em", - marginTop: "1.5555556em", - }, - "& h3 + *": { - marginTop: "0px", - }, - "& h3 code": { - fontSize: "0.8888889em", - }, - "& h4": { - lineHeight: "1.5", - marginBottom: "0.6666667em", - marginTop: "1.6666667em", - }, - "& h4 + *": { - marginTop: "0px", - }, - "& hr": { - marginBottom: "3em", - marginTop: "3em", - }, - "& hr + *": { - marginTop: "0px", - }, - "& img": { - marginBottom: "2em", - marginTop: "2em", - }, - "& kbd": { - borderRadius: "0.375rem", - fontSize: "0.8333333em", - paddingBottom: "0.25em", - paddingInlineEnd: "0.3333333em", - paddingInlineStart: "0.3333333em", - paddingTop: "0.25em", - }, - "& li": { - marginBottom: "0.5em", - marginTop: "0.5em", - }, - "& ol": { - marginBottom: "1.3333333em", - marginTop: "1.3333333em", - paddingInlineStart: "1.5833333em", - }, - "& ol > li": { - paddingInlineStart: "0.4166667em", - }, - "& p": { - marginBottom: "1.3333333em", - marginTop: "1.3333333em", - }, - "& picture": { - marginBottom: "2em", - marginTop: "2em", - }, - "& picture > img": { - marginBottom: "0px", - marginTop: "0px", - }, - "& pre": { - borderRadius: "0.5rem", - fontSize: "0.8333333em", - lineHeight: "1.8", - marginBottom: "2em", - marginTop: "2em", - paddingBottom: "1.2em", - paddingInlineEnd: "1.6em", - paddingInlineStart: "1.6em", - paddingTop: "1.2em", - }, - "& table": { - fontSize: "0.8333333em", - lineHeight: "1.4", - }, - "& tbody td, & tfoot td": { - paddingBottom: "0.8em", - paddingInlineEnd: "0.6em", - paddingInlineStart: "0.6em", - paddingTop: "0.8em", - }, - "& tbody td:first-child, & tfoot td:first-child": { - paddingInlineStart: "0px", - }, - "& tbody td:last-child, & tfoot td:last-child": { - paddingInlineEnd: "0px", - }, - "& thead th": { - paddingBottom: "0.8em", - paddingInlineEnd: "0.6em", - paddingInlineStart: "0.6em", - }, - "& thead th:first-child": { - paddingInlineStart: "0px", - }, - "& thead th:last-child": { - paddingInlineEnd: "0px", - }, - "& ul": { - marginBottom: "1.3333333em", - marginTop: "1.3333333em", - paddingInlineStart: "1.5833333em", - }, - "& ul > li": { - paddingInlineStart: "0.4166667em", - }, - "& ul ul, & ul ol, & ol ul, & ol ol": { - marginBottom: "0.6666667em", - marginTop: "0.6666667em", - }, - "& video": { - marginBottom: "2em", - marginTop: "2em", - }, - fontSize: "1.5rem", - lineHeight: "1.6666667", - }, - base: { - '& [class~="lead"]': { - fontSize: "1.25em", - lineHeight: "1.6", - marginBottom: "1.2em", - marginTop: "1.2em", - }, - "& > ol > li > p:first-child": { - marginTop: "1.25em", - }, - "& > ol > li > p:last-child": { - marginBottom: "1.25em", - }, - "& > ul > li > p:first-child": { - marginTop: "1.25em", - }, - "& > ul > li > p:last-child": { - marginBottom: "1.25em", - }, - "& > ul > li p": { - marginBottom: "0.75em", - marginTop: "0.75em", - }, - "& blockquote": { - marginBottom: "1.6em", - marginTop: "1.6em", - paddingInlineStart: "1em", - }, - "& code": { - fontSize: "0.875em", - }, - "& dd": { - marginTop: "0.5em", - paddingInlineStart: "1.625em", - }, - "& dl": { - marginBottom: "1.25em", - marginTop: "1.25em", - }, - "& dt": { - marginTop: "1.25em", - }, - "& figcaption": { - fontSize: "0.875em", - lineHeight: "1.4285714", - marginTop: "0.8571429em", - }, - "& figure": { - marginBottom: "2em", - marginTop: "2em", - }, - "& figure > *": { - marginBottom: "0px", - marginTop: "0px", - }, - "& h1": { - fontSize: "2.25em", - lineHeight: "1.1111111", - marginBottom: "0.8888889em", - marginTop: "0px", - }, - "& h2": { - fontSize: "1.5em", - lineHeight: "1.3333333", - marginBottom: "1em", - marginTop: "2em", - }, - "& h2 + *": { - marginTop: "0px", - }, - "& h2 code": { - fontSize: "0.875em", - }, - "& h3": { - fontSize: "1.25em", - lineHeight: "1.6", - marginBottom: "0.6em", - marginTop: "1.6em", - }, - "& h3 + *": { - marginTop: "0px", - }, - "& h3 code": { - fontSize: "0.9em", - }, - "& h4": { - lineHeight: "1.5", - marginBottom: "0.5em", - marginTop: "1.5em", - }, - "& h4 + *": { - marginTop: "0px", - }, - "& hr": { - marginBottom: "3em", - marginTop: "3em", - }, - "& hr + *": { - marginTop: "0px", - }, - "& img": { - marginBottom: "2em", - marginTop: "2em", - }, - "& kbd": { - borderRadius: "0.3125rem", - fontSize: "0.875em", - paddingBottom: "0.1875em", - paddingInlineEnd: "0.375em", - paddingInlineStart: "0.375em", - paddingTop: "0.1875em", - }, - "& li": { - marginBottom: "0.5em", - marginTop: "0.5em", - }, - "& ol": { - marginBottom: "1.25em", - marginTop: "1.25em", - paddingInlineStart: "1.625em", - }, - "& ol > li": { - paddingInlineStart: "0.375em", - }, - "& p": { - marginBottom: "1.25em", - marginTop: "1.25em", - }, - "& picture": { - marginBottom: "2em", - marginTop: "2em", - }, - "& picture > img": { - marginBottom: "0px", - marginTop: "0px", - }, - "& pre": { - borderRadius: "0.375rem", - fontSize: "0.875em", - lineHeight: "1.7142857", - marginBottom: "1.7142857em", - marginTop: "1.7142857em", - paddingBottom: "0.8571429em", - paddingInlineEnd: "1.1428571em", - paddingInlineStart: "1.1428571em", - paddingTop: "0.8571429em", - }, - "& table": { - fontSize: "0.875em", - lineHeight: "1.7142857", - }, - "& tbody td, & tfoot td": { - paddingBottom: "0.5714286em", - paddingInlineEnd: "0.5714286em", - paddingInlineStart: "0.5714286em", - paddingTop: "0.5714286em", - }, - "& tbody td:first-child, & tfoot td:first-child": { - paddingInlineStart: "0px", - }, - "& tbody td:last-child, & tfoot td:last-child": { - paddingInlineEnd: "0px", - }, - "& thead th": { - paddingBottom: "0.5714286em", - paddingInlineEnd: "0.5714286em", - paddingInlineStart: "0.5714286em", - }, - "& thead th:first-child": { - paddingInlineStart: "0px", - }, - "& thead th:last-child": { - paddingInlineEnd: "0px", - }, - "& ul": { - marginBottom: "1.25em", - marginTop: "1.25em", - paddingInlineStart: "1.625em", - }, - "& ul > li": { - paddingInlineStart: "0.375em", - }, - "& ul ul, & ul ol, & ol ul, & ol ol": { - marginBottom: "0.75em", - marginTop: "0.75em", - }, - "& video": { - marginBottom: "2em", - marginTop: "2em", - }, - fontSize: "1rem", - lineHeight: "1.75", - }, - lg: { - '& [class~="lead"]': { - fontSize: "1.2222222em", - lineHeight: "1.4545455", - marginBottom: "1.0909091em", - marginTop: "1.0909091em", - }, - "& > ol > li > p:first-child": { - marginTop: "1.3333333em", - }, - "& > ol > li > p:last-child": { - marginBottom: "1.3333333em", - }, - "& > ul > li > p:first-child": { - marginTop: "1.3333333em", - }, - "& > ul > li > p:last-child": { - marginBottom: "1.3333333em", - }, - "& > ul > li p": { - marginBottom: "0.8888889em", - marginTop: "0.8888889em", - }, - "& blockquote": { - marginBottom: "1.6666667em", - marginTop: "1.6666667em", - paddingInlineStart: "1em", - }, - "& code": { - fontSize: "0.8888889em", - }, - "& dd": { - marginTop: "0.6666667em", - paddingInlineStart: "1.5555556em", - }, - "& dl": { - marginBottom: "1.3333333em", - marginTop: "1.3333333em", - }, - "& dt": { - marginTop: "1.3333333em", - }, - "& figcaption": { - fontSize: "0.8888889em", - lineHeight: "1.5", - marginTop: "1em", - }, - "& figure": { - marginBottom: "1.7777778em", - marginTop: "1.7777778em", - }, - "& figure > *": { - marginBottom: "0px", - marginTop: "0px", - }, - "& h1": { - fontSize: "2.6666667em", - lineHeight: "1", - marginBottom: "0.8333333em", - marginTop: "0px", - }, - "& h2": { - fontSize: "1.6666667em", - lineHeight: "1.3333333", - marginBottom: "1.0666667em", - marginTop: "1.8666667em", - }, - "& h2 + *": { - marginTop: "0px", - }, - "& h2 code": { - fontSize: "0.8666667em", - }, - "& h3": { - fontSize: "1.3333333em", - lineHeight: "1.5", - marginBottom: "0.6666667em", - marginTop: "1.6666667em", - }, - "& h3 + *": { - marginTop: "0px", - }, - "& h3 code": { - fontSize: "0.875em", - }, - "& h4": { - lineHeight: "1.5555556", - marginBottom: "0.4444444em", - marginTop: "1.7777778em", - }, - "& h4 + *": { - marginTop: "0px", - }, - "& hr": { - marginBottom: "3.1111111em", - marginTop: "3.1111111em", - }, - "& hr + *": { - marginTop: "0px", - }, - "& img": { - marginBottom: "1.7777778em", - marginTop: "1.7777778em", - }, - "& kbd": { - borderRadius: "0.3125rem", - fontSize: "0.8888889em", - paddingBottom: "0.2222222em", - paddingInlineEnd: "0.4444444em", - paddingInlineStart: "0.4444444em", - paddingTop: "0.2222222em", - }, - "& li": { - marginBottom: "0.6666667em", - marginTop: "0.6666667em", - }, - "& ol": { - marginBottom: "1.3333333em", - marginTop: "1.3333333em", - paddingInlineStart: "1.5555556em", - }, - "& ol > li": { - paddingInlineStart: "0.4444444em", - }, - "& p": { - marginBottom: "1.3333333em", - marginTop: "1.3333333em", - }, - "& picture": { - marginBottom: "1.7777778em", - marginTop: "1.7777778em", - }, - "& picture > img": { - marginBottom: "0px", - marginTop: "0px", - }, - "& pre": { - borderRadius: "0.375rem", - fontSize: "0.8888889em", - lineHeight: "1.75", - marginBottom: "2em", - marginTop: "2em", - paddingBottom: "1em", - paddingInlineEnd: "1.5em", - paddingInlineStart: "1.5em", - paddingTop: "1em", - }, - "& table": { - fontSize: "0.8888889em", - lineHeight: "1.5", - }, - "& tbody td, & tfoot td": { - paddingBottom: "0.75em", - paddingInlineEnd: "0.75em", - paddingInlineStart: "0.75em", - paddingTop: "0.75em", - }, - "& tbody td:first-child, & tfoot td:first-child": { - paddingInlineStart: "0px", - }, - "& tbody td:last-child, & tfoot td:last-child": { - paddingInlineEnd: "0px", - }, - "& thead th": { - paddingBottom: "0.75em", - paddingInlineEnd: "0.75em", - paddingInlineStart: "0.75em", - }, - "& thead th:first-child": { - paddingInlineStart: "0px", - }, - "& thead th:last-child": { - paddingInlineEnd: "0px", - }, - "& ul": { - marginBottom: "1.3333333em", - marginTop: "1.3333333em", - paddingInlineStart: "1.5555556em", - }, - "& ul > li": { - paddingInlineStart: "0.4444444em", - }, - "& ul ul, & ul ol, & ol ul, & ol ol": { - marginBottom: "0.8888889em", - marginTop: "0.8888889em", - }, - "& video": { - marginBottom: "1.7777778em", - marginTop: "1.7777778em", - }, - fontSize: "1.125rem", - lineHeight: "1.7777778", - }, - sm: { - '& [class~="lead"]': { - fontSize: "1.2857143em", - lineHeight: "1.5555556", - marginBottom: "0.8888889em", - marginTop: "0.8888889em", - }, - "& > ol > li > p:first-child": { - marginTop: "1.1428571em", - }, - "& > ol > li > p:last-child": { - marginBottom: "1.1428571em", - }, - "& > ul > li > p:first-child": { - marginTop: "1.1428571em", - }, - "& > ul > li > p:last-child": { - marginBottom: "1.1428571em", - }, - "& > ul > li p": { - marginBottom: "0.5714286em", - marginTop: "0.5714286em", - }, - "& blockquote": { - marginBottom: "1.3333333em", - marginTop: "1.3333333em", - paddingInlineStart: "1.1111111em", - }, - "& code": { - fontSize: "0.8571429em", - }, - "& dd": { - marginTop: "0.2857143em", - paddingInlineStart: "1.5714286em", - }, - "& dl": { - marginBottom: "1.1428571em", - marginTop: "1.1428571em", - }, - "& dt": { - marginTop: "1.1428571em", - }, - "& figcaption": { - fontSize: "0.8571429em", - lineHeight: "1.3333333", - marginTop: "0.6666667em", - }, - "& figure": { - marginBottom: "1.7142857em", - marginTop: "1.7142857em", - }, - "& figure > *": { - marginBottom: "0px", - marginTop: "0px", - }, - "& h1": { - fontSize: "2.1428571em", - lineHeight: "1.2", - marginBottom: "0.8em", - marginTop: "0px", - }, - "& h2": { - fontSize: "1.4285714em", - lineHeight: "1.4", - marginBottom: "0.8em", - marginTop: "1.6em", - }, - "& h2 + *": { - marginTop: "0px", - }, - "& h2 code": { - fontSize: "0.9em", - }, - "& h3": { - fontSize: "1.2857143em", - lineHeight: "1.5555556", - marginBottom: "0.4444444em", - marginTop: "1.5555556em", - }, - "& h3 + *": { - marginTop: "0px", - }, - "& h3 code": { - fontSize: "0.8888889em", - }, - "& h4": { - lineHeight: "1.4285714", - marginBottom: "0.5714286em", - marginTop: "1.4285714em", - }, - "& h4 + *": { - marginTop: "0px", - }, - "& hr": { - marginBottom: "2.8571429em", - marginTop: "2.8571429em", - }, - "& hr + *": { - marginTop: "0px", - }, - "& img": { - marginBottom: "1.7142857em", - marginTop: "1.7142857em", - }, - "& kbd": { - borderRadius: "0.3125rem", - fontSize: "0.8571429em", - paddingBottom: "0.1428571em", - paddingInlineEnd: "0.3571429em", - paddingInlineStart: "0.3571429em", - paddingTop: "0.1428571em", - }, - "& li": { - marginBottom: "0.2857143em", - marginTop: "0.2857143em", - }, - "& ol": { - marginBottom: "1.1428571em", - marginTop: "1.1428571em", - paddingInlineStart: "1.5714286em", - }, - "& ol > li": { - paddingInlineStart: "0.4285714em", - }, - "& p": { - marginBottom: "1.1428571em", - marginTop: "1.1428571em", - }, - "& picture": { - marginBottom: "1.7142857em", - marginTop: "1.7142857em", - }, - "& picture > img": { - marginBottom: "0px", - marginTop: "0px", - }, - "& pre": { - borderRadius: "0.25rem", - fontSize: "0.8571429em", - lineHeight: "1.6666667", - marginBottom: "1.6666667em", - marginTop: "1.6666667em", - paddingBottom: "0.6666667em", - paddingInlineEnd: "1em", - paddingInlineStart: "1em", - paddingTop: "0.6666667em", - }, - "& table": { - fontSize: "0.8571429em", - lineHeight: "1.5", - }, - "& tbody td, & tfoot td": { - paddingBottom: "0.6666667em", - paddingInlineEnd: "1em", - paddingInlineStart: "1em", - paddingTop: "0.6666667em", - }, - "& tbody td:first-child, & tfoot td:first-child": { - paddingInlineStart: "0px", - }, - "& tbody td:last-child, & tfoot td:last-child": { - paddingInlineEnd: "0px", - }, - "& thead th": { - paddingBottom: "0.6666667em", - paddingInlineEnd: "1em", - paddingInlineStart: "1em", - }, - "& thead th:first-child": { - paddingInlineStart: "0px", - }, - "& thead th:last-child": { - paddingInlineEnd: "0px", - }, - "& ul": { - marginBottom: "1.1428571em", - marginTop: "1.1428571em", - paddingInlineStart: "1.5714286em", - }, - "& ul > li": { - paddingInlineStart: "0.4285714em", - }, - "& ul ul, & ul ol, & ol ul, & ol ol": { - marginBottom: "0.5714286em", - marginTop: "0.5714286em", - }, - "& video": { - marginBottom: "1.7142857em", - marginTop: "1.7142857em", - }, - fontSize: "0.875rem", - lineHeight: "1.7142857", - }, - xl: { - '& [class~="lead"]': { - fontSize: "1.2em", - lineHeight: "1.5", - marginBottom: "1em", - marginTop: "1em", - }, - "& > ol > li > p:first-child": { - marginTop: "1.2em", - }, - "& > ol > li > p:last-child": { - marginBottom: "1.2em", - }, - "& > ul > li > p:first-child": { - marginTop: "1.2em", - }, - "& > ul > li > p:last-child": { - marginBottom: "1.2em", - }, - "& > ul > li p": { - marginBottom: "0.8em", - marginTop: "0.8em", - }, - "& blockquote": { - marginBottom: "1.6em", - marginTop: "1.6em", - paddingInlineStart: "1.0666667em", - }, - "& code": { - fontSize: "0.9em", - }, - "& dd": { - marginTop: "0.6em", - paddingInlineStart: "1.6em", - }, - "& dl": { - marginBottom: "1.2em", - marginTop: "1.2em", - }, - "& dt": { - marginTop: "1.2em", - }, - "& figcaption": { - fontSize: "0.9em", - lineHeight: "1.5555556", - marginTop: "1em", - }, - "& figure": { - marginBottom: "2em", - marginTop: "2em", - }, - "& figure > *": { - marginBottom: "0px", - marginTop: "0px", - }, - "& h1": { - fontSize: "2.8em", - lineHeight: "1", - marginBottom: "0.8571429em", - marginTop: "0px", - }, - "& h2": { - fontSize: "1.8em", - lineHeight: "1.1111111", - marginBottom: "0.8888889em", - marginTop: "1.5555556em", - }, - "& h2 + *": { - marginTop: "0px", - }, - "& h2 code": { - fontSize: "0.8611111em", - }, - "& h3": { - fontSize: "1.5em", - lineHeight: "1.3333333", - marginBottom: "0.6666667em", - marginTop: "1.6em", - }, - "& h3 + *": { - marginTop: "0px", - }, - "& h3 code": { - fontSize: "0.9em", - }, - "& h4": { - lineHeight: "1.6", - marginBottom: "0.6em", - marginTop: "1.8em", - }, - "& h4 + *": { - marginTop: "0px", - }, - "& hr": { - marginBottom: "2.8em", - marginTop: "2.8em", - }, - "& hr + *": { - marginTop: "0px", - }, - "& img": { - marginBottom: "2em", - marginTop: "2em", - }, - "& kbd": { - borderRadius: "0.3125rem", - fontSize: "0.9em", - paddingBottom: "0.25em", - paddingInlineEnd: "0.4em", - paddingInlineStart: "0.4em", - paddingTop: "0.25em", - }, - "& li": { - marginBottom: "0.6em", - marginTop: "0.6em", - }, - "& ol": { - marginBottom: "1.2em", - marginTop: "1.2em", - paddingInlineStart: "1.6em", - }, - "& ol > li": { - paddingInlineStart: "0.4em", - }, - "& p": { - marginBottom: "1.2em", - marginTop: "1.2em", - }, - "& picture": { - marginBottom: "2em", - marginTop: "2em", - }, - "& picture > img": { - marginBottom: "0px", - marginTop: "0px", - }, - "& pre": { - borderRadius: "0.5rem", - fontSize: "0.9em", - lineHeight: "1.7777778", - marginBottom: "2em", - marginTop: "2em", - paddingBottom: "1.1111111em", - paddingInlineEnd: "1.3333333em", - paddingInlineStart: "1.3333333em", - paddingTop: "1.1111111em", - }, - "& table": { - fontSize: "0.9em", - lineHeight: "1.5555556", - }, - "& tbody td, & tfoot td": { - paddingBottom: "0.8888889em", - paddingInlineEnd: "0.6666667em", - paddingInlineStart: "0.6666667em", - paddingTop: "0.8888889em", - }, - "& tbody td:first-child, & tfoot td:first-child": { - paddingInlineStart: "0px", - }, - "& tbody td:last-child, & tfoot td:last-child": { - paddingInlineEnd: "0px", - }, - "& thead th": { - paddingBottom: "0.8888889em", - paddingInlineEnd: "0.6666667em", - paddingInlineStart: "0.6666667em", - }, - "& thead th:first-child": { - paddingInlineStart: "0px", - }, - "& thead th:last-child": { - paddingInlineEnd: "0px", - }, - "& ul": { - marginBottom: "1.2em", - marginTop: "1.2em", - paddingInlineStart: "1.6em", - }, - "& ul > li": { - paddingInlineStart: "0.4em", - }, - "& ul ul, & ul ol, & ol ul, & ol ol": { - marginBottom: "0.8em", - marginTop: "0.8em", - }, - "& video": { - marginBottom: "2em", - marginTop: "2em", - }, - fontSize: "1.25rem", - lineHeight: "1.8", - }, - }, - }, -} as RecipeConfig); - -const proseSemanticTokens = defineSemanticTokens({ - colors: { - prose: { - body: { - value: "{colors.slate.700}", - }, - bold: { - value: "{colors.slate.900}", - }, - bullet: { - value: "{colors.slate.300}", - }, - caption: { - value: "{colors.slate.500}", - }, - code: { - value: "{colors.slate.900}", - }, - counter: { - value: "{colors.slate.500}", - }, - heading: { - value: "{colors.slate.900}", - }, - hrBorder: { - value: "{colors.slate.200}", - }, - kbd: { - value: "{colors.slate.900}", - }, - kbdShadow: { - value: "0 0 0", - }, - lead: { - value: "{colors.slate.600}", - }, - link: { - value: "{colors.slate.900}", - }, - preBg: { - value: "{colors.slate.800}", - }, - preCode: { - value: "{colors.slate.200}", - }, - quote: { - value: "{colors.slate.900}", - }, - quoteBorder: { - value: "{colors.slate.200}", - }, - tdBorder: { - value: "{colors.slate.200}", - }, - thBorder: { - value: "{colors.slate.300}", - }, - }, - }, -}); - -export default definePreset({ - name: "typography", - theme: { - extend: { - recipes: { - prose: proseRecipe, - }, - semanticTokens: proseSemanticTokens, - }, - }, -}); diff --git a/panda.config.ts b/panda.config.ts index 12ebd29..566d33c 100644 --- a/panda.config.ts +++ b/panda.config.ts @@ -1,7 +1,8 @@ import { defineConfig } from "@pandacss/dev"; import presetBase from "@pandacss/preset-base"; import pandaPreset from "@pandacss/preset-panda"; -import typographyPreset from "./panda-presets/typography"; +import { typographyPreset } from "@pandacss/preset-typography"; + export default defineConfig({ conditions: { extend: { @@ -43,6 +44,7 @@ export default defineConfig({ removeUnusedKeyframes: true, removeUnusedTokens: true, smartCompoundVariants: true, + treeshakeDesignSystem: true, }, // The output directory for your css system @@ -95,7 +97,7 @@ export default defineConfig({ }, // Whether to use css reset preflight: true, - presets: [presetBase, pandaPreset, typographyPreset], + presets: [presetBase, pandaPreset, typographyPreset()], // Useful for theme customization theme: { diff --git a/src/app/(auth)/signin/page.tsx b/src/app/(auth)/signin/page.tsx index bbd413f..30b9424 100644 --- a/src/app/(auth)/signin/page.tsx +++ b/src/app/(auth)/signin/page.tsx @@ -2,10 +2,9 @@ import { css } from "@styled-system/css"; import { useActionState, useTransition } from "react"; -import { FieldError } from "@/components/form/field-errors"; import { FormError } from "@/components/form/form-error"; +import { FormField } from "@/components/form/form-field"; import { Input } from "@/components/form/input"; -import { Label } from "@/components/form/label"; import { SubmitButton } from "@/components/form/submit-button"; import { signInAction } from "@/features/auth/actions/sign-in-action"; import { AuthCard } from "@/features/auth/components/auth-card"; @@ -22,8 +21,8 @@ const SignInPage = () => { }); }; - // Extract email from payload if available (for preserving on error) - const emailValue = state?.payload?.get("email")?.toString() ?? ""; + // Preserve non-secret fields on validation / auth errors + const { email: emailValue = "" } = state?.payload ?? {}; return ( { title="Sign in to your account" >
-
- - - -
-
- - - -
+ + {(id) => ( + + )} + + + {(id) => ( + + )} + diff --git a/src/app/(auth)/signup/page.tsx b/src/app/(auth)/signup/page.tsx index 3fbd717..4f8bfef 100644 --- a/src/app/(auth)/signup/page.tsx +++ b/src/app/(auth)/signup/page.tsx @@ -2,10 +2,9 @@ import { css } from "@styled-system/css"; import { useActionState, useTransition } from "react"; -import { FieldError } from "@/components/form/field-errors"; import { FormError } from "@/components/form/form-error"; +import { FormField } from "@/components/form/form-field"; import { Input } from "@/components/form/input"; -import { Label } from "@/components/form/label"; import { SubmitButton } from "@/components/form/submit-button"; import { signUpAction } from "@/features/auth/actions/sign-up-action"; import { AuthCard } from "@/features/auth/components/auth-card"; @@ -21,9 +20,7 @@ const SignUpPage = () => { }); }; - // Extract form values from payload if available (for preserving on error) - const nameValue = state?.payload?.get("name")?.toString() ?? ""; - const emailValue = state?.payload?.get("email")?.toString() ?? ""; + const { name: nameValue = "", email: emailValue = "" } = state?.payload ?? {}; return ( { title="Create your account" > -
- - - -
-
- - - -
-
- - - -
+ + {(id) => ( + + )} + + + {(id) => ( + + )} + + + {(id) => ( + + )} + - + Sign up diff --git a/src/app/3d-models/page.tsx b/src/app/3d-models/page.tsx index 3351ac6..4a0d448 100644 --- a/src/app/3d-models/page.tsx +++ b/src/app/3d-models/page.tsx @@ -22,6 +22,7 @@ export const generateMetadata = async ({ return { ...listingMetadata, alternates: { canonical }, + description: listingMetadata.description, openGraph: { ...listingMetadata.openGraph, url: canonical, diff --git a/src/app/index.css b/src/app/index.css index ed0fd34..e27a23b 100644 --- a/src/app/index.css +++ b/src/app/index.css @@ -1,99 +1 @@ @layer reset, base, tokens, recipes, utilities; - -/* VIEW TRANSITIONS */ -::view-transition-old(.exit):only-child { - --slide-distance: 20px; - animation: - fade-out 250ms, - slide-out 250ms; -} - -::view-transition-new(.enter):only-child { - --slide-distance: -20px; - animation: - fade-in 250ms, - slide-in 250ms; -} - -::view-transition-old(.exit-left) { - --slide-distance: -60px; - animation: - fade-out 250ms, - slide-out 250ms; -} - -::view-transition-old(.exit-right) { - --slide-distance: calc(100vw + 60px); - animation: - fade-out 250ms, - slide-out 250ms; -} - -::view-transition-new(.enter-left) { - --slide-distance: -60px; - animation: - fade-in 250ms, - slide-in 250ms; -} - -::view-transition-new(.enter-right) { - --slide-distance: calc(100vw + 60px); - animation: - fade-in 250ms, - slide-in 250ms; -} - -/* Search input pending spinner (ViewTransition name search-input-spinner) */ -::view-transition-old(.search-spinner-quick) { - animation: fade-out 100ms ease-out; -} -::view-transition-new(.search-spinner-quick) { - animation: fade-in 100ms ease-out; -} -::view-transition-old(.search-spinner-standard) { - animation: fade-out 200ms ease-out; -} -::view-transition-new(.search-spinner-standard) { - animation: fade-in 200ms ease-out; -} - -/* Likes counter transitions */ - -::view-transition-new(.likes-update-increase) { - --slide-distance-y: -10px; - animation: - fade-out 200ms var(--easings-in-dramatic), - slide-out-y 200ms var(--easings-in-dramatic); -} -::view-transition-old(.likes-update-increase) { - --slide-distance-y: 8px; - animation: - slide-out-y 200ms var(--easings-out-dramatic), - fade-out 200ms var(--easings-out-dramatic); -} -::view-transition-new(.likes-update-decrease) { - --slide-distance-y: 10px; - animation: - fade-in 200ms var(--easings-in-dramatic), - slide-in-y 200ms var(--easings-in-dramatic); -} -::view-transition-old(.likes-update-decrease) { - --slide-distance-y: -8px; - animation: - slide-out-y 200ms var(--easings-out-dramatic), - fade-out 200ms var(--easings-out-dramatic); -} - -/* nav-link type */ -::view-transition-old(.exit-block) { - --slide-distance-y: 20px; - animation: - fade-out 200ms var(--easings-glide), - slide-out-y 200ms var(--easings-glide); -} -::view-transition-new(.enter-block) { - --slide-distance-y: -20px; - animation: - fade-in 200ms var(--easings-glide), - slide-in-y 200ms var(--easings-glide); -} diff --git a/src/components/form/field-errors.tsx b/src/components/form/field-errors.tsx index f0ed642..0e37b1e 100644 --- a/src/components/form/field-errors.tsx +++ b/src/components/form/field-errors.tsx @@ -2,7 +2,7 @@ import { css } from "@styled-system/css"; import { ViewTransition } from "react"; import { EMPTY_LIST_LENGTH } from "@/constants"; import type { Maybe } from "@/types"; -import type { ActionState } from "@/utils/to-action-state"; +import type { ActionState } from "@/utils/to-action-state/types"; interface FieldErrorProps { actionState: Maybe; diff --git a/src/components/form/form-error.tsx b/src/components/form/form-error.tsx index 4a83634..6a86f90 100644 --- a/src/components/form/form-error.tsx +++ b/src/components/form/form-error.tsx @@ -3,7 +3,7 @@ import { css } from "@styled-system/css"; import { ViewTransition } from "react"; import type { Maybe } from "@/types"; -import type { ActionState } from "@/utils/to-action-state"; +import type { ActionState } from "@/utils/to-action-state/types"; interface FormErrorProps { actionState: Maybe>; diff --git a/src/components/form/form-field.tsx b/src/components/form/form-field.tsx new file mode 100644 index 0000000..408c25e --- /dev/null +++ b/src/components/form/form-field.tsx @@ -0,0 +1,50 @@ +import { css, cx } from "@styled-system/css"; +import { type ReactNode, useId, ViewTransition } from "react"; +import type { Maybe } from "@/types"; +import type { ActionState } from "@/utils/to-action-state/types"; +import { FieldError } from "./field-errors"; +import { Label } from "./label"; + +interface FormFieldProps { + actionState: Maybe; + children: (id: string) => ReactNode; + className?: string; + disabled?: boolean; + label: string; + name: string; + transitionName?: string; +} + +/** + * A reusable form field component that links a label, input, and error message + * using a unique ID. Supports View Transitions via the transitionName prop. + */ +const FormField = ({ + label, + name, + actionState, + children, + transitionName, + disabled, + className, +}: FormFieldProps) => { + const id = useId(); + + return ( + +
+ + {children(id)} + +
+
+ ); +}; + +export { FormField }; diff --git a/src/components/form/submit-button.tsx b/src/components/form/submit-button.tsx index a2c15aa..a8a1ad5 100644 --- a/src/components/form/submit-button.tsx +++ b/src/components/form/submit-button.tsx @@ -1,5 +1,6 @@ import { css, cx } from "@styled-system/css"; import { square } from "@styled-system/patterns"; +import { ViewTransition } from "react"; import { FaSpinner } from "react-icons/fa"; import { skeletonEnter } from "@/app/styles"; import { Button } from "@/components/button"; @@ -17,25 +18,27 @@ const SubmitButton = ({ className, variant, }: SubmitButtonProps) => ( - + + + ); export { SubmitButton }; diff --git a/src/components/search-input/search-input-transition.tsx b/src/components/search-input/search-input-transition.tsx index 9d3b575..c5d0df3 100644 --- a/src/components/search-input/search-input-transition.tsx +++ b/src/components/search-input/search-input-transition.tsx @@ -1,19 +1,38 @@ +import { viewTransition } from "@styled-system/css"; import { ViewTransition } from "react"; import type { Children } from "@/types"; +const searchSpinnerQuick = viewTransition({ + new: { + animation: "fade-in 100ms ease-out", + }, + old: { + animation: "fade-out 100ms ease-out", + }, +}); + +const searchSpinnerStandard = viewTransition({ + new: { + animation: "fade-in 200ms ease-out", + }, + old: { + animation: "fade-out 200ms ease-out", + }, +}); + const SearchInputTransition = ({ children }: Children) => ( diff --git a/src/db/drop-tables.ts b/src/db/drop-tables.ts index c87e1da..440729c 100644 --- a/src/db/drop-tables.ts +++ b/src/db/drop-tables.ts @@ -1,11 +1,21 @@ /** biome-ignore-all lint/suspicious/noConsole: a command to clear db */ -import { Pool } from "pg"; -import { ENV } from "varlock/env"; +import { sql } from "drizzle-orm"; +import { db } from "@/db"; -const pool = new Pool({ connectionString: ENV.DATABASE_URL }); - -await pool.query(`DROP TABLE IF EXISTS "likes" CASCADE`); -await pool.query(`DROP TABLE IF EXISTS "models" CASCADE`); -await pool.query(`DROP TABLE IF EXISTS "categories" CASCADE`); -await pool.end(); -console.log("✓ All tables dropped successfully"); +await db.run(sql`PRAGMA foreign_keys = OFF`); +try { + await db.run(sql`DROP TABLE IF EXISTS likes`); + await db.run(sql`DROP TABLE IF EXISTS models`); + await db.run(sql`DROP TABLE IF EXISTS categories`); + await db.run(sql`DROP TABLE IF EXISTS session`); + await db.run(sql`DROP TABLE IF EXISTS account`); + await db.run(sql`DROP TABLE IF EXISTS verification`); + await db.run(sql`DROP TABLE IF EXISTS user`); + await db.run(sql`DROP TABLE IF EXISTS __drizzle_migrations`); + console.log("✓ All tables dropped successfully"); +} catch (error) { + console.error("✗ Failed to drop tables:", error); + throw error; +} finally { + await db.run(sql`PRAGMA foreign_keys = ON`); +} diff --git a/src/db/index.ts b/src/db/index.ts index 582c8f6..5ada78d 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -1,26 +1,14 @@ -import { attachDatabasePool } from "@vercel/functions"; -import { drizzle } from "drizzle-orm/node-postgres"; -import { Pool } from "pg"; +import { createClient } from "@libsql/client"; +import { drizzle } from "drizzle-orm/libsql"; import { ENV } from "varlock/env"; import { relations } from "./schema/relations"; -// Prefer Neon *pooled* URL (`ep-…-pooler.…`) in DATABASE_URL. -// connectionTimeoutMillis: Neon cold start can exceed pg default (~5s) → ETIMEDOUT in build. -// max > 1: Fluid Compute runs concurrent work on one instance; max: 1 queues/timeouts. -// min: 1 keeps a warm client; idleTimeout closes extras before suspend (attachDatabasePool). -const pool = new Pool({ - connectionString: ENV.DATABASE_URL, - connectionTimeoutMillis: 120_000, - idleTimeoutMillis: 120_000, - max: 10, - min: 1, +const client = createClient({ + authToken: ENV.TURSO_DATABASE_AUTH, + url: ENV.TURSO_DATABASE_URL, }); -// Fluid compute: reuse pool across warm invocations; close idle clients before suspend -attachDatabasePool(pool); - export const db = drizzle({ - client: pool, - jit: true, + client, relations, }); diff --git a/src/db/migrations/20260626222739_nervous_ultimates/migration.sql b/src/db/migrations/20260626222739_nervous_ultimates/migration.sql deleted file mode 100644 index 7dce19f..0000000 --- a/src/db/migrations/20260626222739_nervous_ultimates/migration.sql +++ /dev/null @@ -1,81 +0,0 @@ -CREATE TYPE "category_slug" AS ENUM('3d-printer', 'art', 'education', 'fashion', 'hobby-diy', 'household', 'miniatures', 'props-cosplay', 'tools', 'toys-games');--> statement-breakpoint -CREATE TABLE "account" ( - "id" text PRIMARY KEY, - "account_id" text NOT NULL, - "provider_id" text NOT NULL, - "user_id" text NOT NULL, - "access_token" text, - "refresh_token" text, - "id_token" text, - "access_token_expires_at" timestamp, - "refresh_token_expires_at" timestamp, - "scope" text, - "password" text, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp NOT NULL -); ---> statement-breakpoint -CREATE TABLE "session" ( - "id" text PRIMARY KEY, - "expires_at" timestamp NOT NULL, - "token" text NOT NULL UNIQUE, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp NOT NULL, - "ip_address" text, - "user_agent" text, - "user_id" text NOT NULL -); ---> statement-breakpoint -CREATE TABLE "user" ( - "id" text PRIMARY KEY, - "name" text NOT NULL, - "email" text NOT NULL UNIQUE, - "email_verified" boolean DEFAULT false NOT NULL, - "image" text, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp DEFAULT now() NOT NULL -); ---> statement-breakpoint -CREATE TABLE "verification" ( - "id" text PRIMARY KEY, - "identifier" text NOT NULL, - "value" text NOT NULL, - "expires_at" timestamp NOT NULL, - "created_at" timestamp DEFAULT now() NOT NULL, - "updated_at" timestamp DEFAULT now() NOT NULL -); ---> statement-breakpoint -CREATE TABLE "likes" ( - "id" serial PRIMARY KEY, - "user_id" text NOT NULL, - "model_slug" text NOT NULL, - "created_at" timestamp with time zone DEFAULT now() NOT NULL, - CONSTRAINT "unique_user_model" UNIQUE("user_id","model_slug") -); ---> statement-breakpoint -CREATE TABLE "categories" ( - "id" serial PRIMARY KEY, - "display_name" text NOT NULL, - "slug" "category_slug" NOT NULL UNIQUE -); ---> statement-breakpoint -CREATE TABLE "models" ( - "slug" text PRIMARY KEY, - "name" text NOT NULL UNIQUE, - "description" text NOT NULL, - "likes" integer DEFAULT 0 NOT NULL, - "image" text NOT NULL, - "category_slug" "category_slug" NOT NULL, - "user_id" text NOT NULL, - "date_added" timestamp with time zone DEFAULT now() NOT NULL -); ---> statement-breakpoint -CREATE INDEX "account_userId_idx" ON "account" ("user_id");--> statement-breakpoint -CREATE INDEX "session_userId_idx" ON "session" ("user_id");--> statement-breakpoint -CREATE INDEX "verification_identifier_idx" ON "verification" ("identifier");--> statement-breakpoint -ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE;--> statement-breakpoint -ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE;--> statement-breakpoint -ALTER TABLE "likes" ADD CONSTRAINT "likes_user_id_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE;--> statement-breakpoint -ALTER TABLE "likes" ADD CONSTRAINT "likes_model_slug_models_slug_fkey" FOREIGN KEY ("model_slug") REFERENCES "models"("slug") ON DELETE CASCADE;--> statement-breakpoint -ALTER TABLE "models" ADD CONSTRAINT "models_category_slug_categories_slug_fkey" FOREIGN KEY ("category_slug") REFERENCES "categories"("slug");--> statement-breakpoint -ALTER TABLE "models" ADD CONSTRAINT "models_user_id_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE; \ No newline at end of file diff --git a/src/db/migrations/20260723011929_turso_init/migration.sql b/src/db/migrations/20260723011929_turso_init/migration.sql new file mode 100644 index 0000000..b5158b6 --- /dev/null +++ b/src/db/migrations/20260723011929_turso_init/migration.sql @@ -0,0 +1,80 @@ +CREATE TABLE `account` ( + `access_token` text, + `access_token_expires_at` integer, + `account_id` text NOT NULL, + `created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL, + `id` text PRIMARY KEY, + `id_token` text, + `password` text, + `provider_id` text NOT NULL, + `refresh_token` text, + `refresh_token_expires_at` integer, + `scope` text, + `updated_at` integer NOT NULL, + `user_id` text NOT NULL, + CONSTRAINT `fk_account_user_id_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE +); +--> statement-breakpoint +CREATE TABLE `session` ( + `created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL, + `expires_at` integer NOT NULL, + `id` text PRIMARY KEY, + `ip_address` text, + `token` text NOT NULL UNIQUE, + `updated_at` integer NOT NULL, + `user_agent` text, + `user_id` text NOT NULL, + CONSTRAINT `fk_session_user_id_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE +); +--> statement-breakpoint +CREATE TABLE `user` ( + `created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL, + `email` text NOT NULL UNIQUE, + `email_verified` integer DEFAULT false NOT NULL, + `id` text PRIMARY KEY, + `image` text, + `name` text NOT NULL, + `updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL +); +--> statement-breakpoint +CREATE TABLE `verification` ( + `created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL, + `expires_at` integer NOT NULL, + `id` text PRIMARY KEY, + `identifier` text NOT NULL, + `updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL, + `value` text NOT NULL +); +--> statement-breakpoint +CREATE TABLE `likes` ( + `created_at` integer NOT NULL, + `id` integer PRIMARY KEY AUTOINCREMENT, + `model_slug` text NOT NULL, + `user_id` text NOT NULL, + CONSTRAINT `fk_likes_model_slug_models_slug_fk` FOREIGN KEY (`model_slug`) REFERENCES `models`(`slug`) ON DELETE CASCADE, + CONSTRAINT `fk_likes_user_id_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE, + CONSTRAINT `unique_user_model` UNIQUE(`user_id`,`model_slug`) +); +--> statement-breakpoint +CREATE TABLE `categories` ( + `display_name` text NOT NULL, + `id` integer PRIMARY KEY AUTOINCREMENT, + `slug` text NOT NULL UNIQUE +); +--> statement-breakpoint +CREATE TABLE `models` ( + `category_slug` text NOT NULL, + `date_added` integer NOT NULL, + `description` text NOT NULL, + `image` text NOT NULL, + `likes` integer DEFAULT 0 NOT NULL, + `name` text NOT NULL UNIQUE, + `slug` text PRIMARY KEY, + `user_id` text NOT NULL, + CONSTRAINT `fk_models_category_slug_categories_slug_fk` FOREIGN KEY (`category_slug`) REFERENCES `categories`(`slug`), + CONSTRAINT `fk_models_user_id_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE +); +--> statement-breakpoint +CREATE INDEX `account_userId_idx` ON `account` (`user_id`);--> statement-breakpoint +CREATE INDEX `session_userId_idx` ON `session` (`user_id`);--> statement-breakpoint +CREATE INDEX `verification_identifier_idx` ON `verification` (`identifier`); \ No newline at end of file diff --git a/src/db/migrations/20260626222739_nervous_ultimates/snapshot.json b/src/db/migrations/20260723011929_turso_init/snapshot.json similarity index 57% rename from src/db/migrations/20260626222739_nervous_ultimates/snapshot.json rename to src/db/migrations/20260723011929_turso_init/snapshot.json index b929117..8b7b10f 100644 --- a/src/db/migrations/20260626222739_nervous_ultimates/snapshot.json +++ b/src/db/migrations/20260723011929_turso_init/snapshot.json @@ -1,946 +1,718 @@ { - "version": "8", - "dialect": "postgres", - "id": "7e5c6dbd-43a5-4eea-98bc-cfe5e4ce7360", + "version": "7", + "dialect": "sqlite", + "id": "107a32fd-b9c3-4c84-9c91-178cc8f752b0", "prevIds": ["00000000-0000-0000-0000-000000000000"], "ddl": [ { - "values": [ - "3d-printer", - "art", - "education", - "fashion", - "hobby-diy", - "household", - "miniatures", - "props-cosplay", - "tools", - "toys-games" - ], - "name": "category_slug", - "entityType": "enums", - "schema": "public" - }, - { - "isRlsEnabled": false, "name": "account", - "entityType": "tables", - "schema": "public" + "entityType": "tables" }, { - "isRlsEnabled": false, "name": "session", - "entityType": "tables", - "schema": "public" + "entityType": "tables" }, { - "isRlsEnabled": false, "name": "user", - "entityType": "tables", - "schema": "public" + "entityType": "tables" }, { - "isRlsEnabled": false, "name": "verification", - "entityType": "tables", - "schema": "public" + "entityType": "tables" }, { - "isRlsEnabled": false, "name": "likes", - "entityType": "tables", - "schema": "public" + "entityType": "tables" }, { - "isRlsEnabled": false, "name": "categories", - "entityType": "tables", - "schema": "public" + "entityType": "tables" }, { - "isRlsEnabled": false, "name": "models", - "entityType": "tables", - "schema": "public" + "entityType": "tables" }, { "type": "text", - "typeSchema": null, - "notNull": true, - "dimensions": 0, + "notNull": false, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "id", + "name": "access_token", "entityType": "columns", - "schema": "public", "table": "account" }, { - "type": "text", - "typeSchema": null, - "notNull": true, - "dimensions": 0, + "type": "integer", + "notNull": false, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "account_id", + "name": "access_token_expires_at", "entityType": "columns", - "schema": "public", "table": "account" }, { "type": "text", - "typeSchema": null, "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "provider_id", + "name": "account_id", "entityType": "columns", - "schema": "public", "table": "account" }, { - "type": "text", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, - "default": null, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))", "generated": null, - "identity": null, - "name": "user_id", + "name": "created_at", "entityType": "columns", - "schema": "public", "table": "account" }, { "type": "text", - "typeSchema": null, "notNull": false, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "access_token", + "name": "id", "entityType": "columns", - "schema": "public", "table": "account" }, { "type": "text", - "typeSchema": null, "notNull": false, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "refresh_token", + "name": "id_token", "entityType": "columns", - "schema": "public", "table": "account" }, { "type": "text", - "typeSchema": null, "notNull": false, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "id_token", + "name": "password", "entityType": "columns", - "schema": "public", "table": "account" }, { - "type": "timestamp", - "typeSchema": null, - "notNull": false, - "dimensions": 0, + "type": "text", + "notNull": true, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "access_token_expires_at", + "name": "provider_id", "entityType": "columns", - "schema": "public", "table": "account" }, { - "type": "timestamp", - "typeSchema": null, + "type": "text", "notNull": false, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "refresh_token_expires_at", + "name": "refresh_token", "entityType": "columns", - "schema": "public", "table": "account" }, { - "type": "text", - "typeSchema": null, + "type": "integer", "notNull": false, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "scope", + "name": "refresh_token_expires_at", "entityType": "columns", - "schema": "public", "table": "account" }, { "type": "text", - "typeSchema": null, "notNull": false, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "password", + "name": "scope", "entityType": "columns", - "schema": "public", "table": "account" }, { - "type": "timestamp", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, - "default": "now()", + "autoincrement": false, + "default": null, "generated": null, - "identity": null, - "name": "created_at", + "name": "updated_at", "entityType": "columns", - "schema": "public", "table": "account" }, { - "type": "timestamp", - "typeSchema": null, + "type": "text", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "updated_at", + "name": "user_id", "entityType": "columns", - "schema": "public", "table": "account" }, { - "type": "text", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, - "default": null, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))", "generated": null, - "identity": null, - "name": "id", + "name": "created_at", "entityType": "columns", - "schema": "public", "table": "session" }, { - "type": "timestamp", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, "name": "expires_at", "entityType": "columns", - "schema": "public", "table": "session" }, { "type": "text", - "typeSchema": null, - "notNull": true, - "dimensions": 0, + "notNull": false, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "token", + "name": "id", "entityType": "columns", - "schema": "public", "table": "session" }, { - "type": "timestamp", - "typeSchema": null, - "notNull": true, - "dimensions": 0, - "default": "now()", + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, "generated": null, - "identity": null, - "name": "created_at", + "name": "ip_address", "entityType": "columns", - "schema": "public", "table": "session" }, { - "type": "timestamp", - "typeSchema": null, + "type": "text", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "updated_at", + "name": "token", "entityType": "columns", - "schema": "public", "table": "session" }, { - "type": "text", - "typeSchema": null, - "notNull": false, - "dimensions": 0, + "type": "integer", + "notNull": true, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "ip_address", + "name": "updated_at", "entityType": "columns", - "schema": "public", "table": "session" }, { "type": "text", - "typeSchema": null, "notNull": false, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, "name": "user_agent", "entityType": "columns", - "schema": "public", "table": "session" }, { "type": "text", - "typeSchema": null, "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, "name": "user_id", "entityType": "columns", - "schema": "public", "table": "session" }, { - "type": "text", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, - "default": null, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))", "generated": null, - "identity": null, - "name": "id", + "name": "created_at", "entityType": "columns", - "schema": "public", "table": "user" }, { "type": "text", - "typeSchema": null, "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "name", + "name": "email", "entityType": "columns", - "schema": "public", "table": "user" }, { - "type": "text", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, - "default": null, + "autoincrement": false, + "default": "false", "generated": null, - "identity": null, - "name": "email", + "name": "email_verified", "entityType": "columns", - "schema": "public", "table": "user" }, { - "type": "boolean", - "typeSchema": null, - "notNull": true, - "dimensions": 0, - "default": "false", + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, "generated": null, - "identity": null, - "name": "email_verified", + "name": "id", "entityType": "columns", - "schema": "public", "table": "user" }, { "type": "text", - "typeSchema": null, "notNull": false, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, "name": "image", "entityType": "columns", - "schema": "public", "table": "user" }, { - "type": "timestamp", - "typeSchema": null, + "type": "text", "notNull": true, - "dimensions": 0, - "default": "now()", + "autoincrement": false, + "default": null, "generated": null, - "identity": null, - "name": "created_at", + "name": "name", "entityType": "columns", - "schema": "public", "table": "user" }, { - "type": "timestamp", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, - "default": "now()", + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))", "generated": null, - "identity": null, "name": "updated_at", "entityType": "columns", - "schema": "public", "table": "user" }, { - "type": "text", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, - "default": null, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))", "generated": null, - "identity": null, - "name": "id", + "name": "created_at", "entityType": "columns", - "schema": "public", "table": "verification" }, { - "type": "text", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "identifier", + "name": "expires_at", "entityType": "columns", - "schema": "public", "table": "verification" }, { "type": "text", - "typeSchema": null, - "notNull": true, - "dimensions": 0, + "notNull": false, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "value", + "name": "id", "entityType": "columns", - "schema": "public", "table": "verification" }, { - "type": "timestamp", - "typeSchema": null, + "type": "text", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "expires_at", + "name": "identifier", "entityType": "columns", - "schema": "public", "table": "verification" }, { - "type": "timestamp", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, - "default": "now()", + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))", "generated": null, - "identity": null, - "name": "created_at", + "name": "updated_at", "entityType": "columns", - "schema": "public", "table": "verification" }, { - "type": "timestamp", - "typeSchema": null, + "type": "text", "notNull": true, - "dimensions": 0, - "default": "now()", + "autoincrement": false, + "default": null, "generated": null, - "identity": null, - "name": "updated_at", + "name": "value", "entityType": "columns", - "schema": "public", "table": "verification" }, { - "type": "serial", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "id", + "name": "created_at", "entityType": "columns", - "schema": "public", "table": "likes" }, { - "type": "text", - "typeSchema": null, - "notNull": true, - "dimensions": 0, + "type": "integer", + "notNull": false, + "autoincrement": true, "default": null, "generated": null, - "identity": null, - "name": "user_id", + "name": "id", "entityType": "columns", - "schema": "public", "table": "likes" }, { "type": "text", - "typeSchema": null, "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, "name": "model_slug", "entityType": "columns", - "schema": "public", "table": "likes" }, { - "type": "timestamp with time zone", - "typeSchema": null, + "type": "text", "notNull": true, - "dimensions": 0, - "default": "now()", + "autoincrement": false, + "default": null, "generated": null, - "identity": null, - "name": "created_at", + "name": "user_id", "entityType": "columns", - "schema": "public", "table": "likes" }, { - "type": "serial", - "typeSchema": null, + "type": "text", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "id", + "name": "display_name", "entityType": "columns", - "schema": "public", "table": "categories" }, { - "type": "text", - "typeSchema": null, - "notNull": true, - "dimensions": 0, + "type": "integer", + "notNull": false, + "autoincrement": true, "default": null, "generated": null, - "identity": null, - "name": "display_name", + "name": "id", "entityType": "columns", - "schema": "public", "table": "categories" }, { - "type": "category_slug", - "typeSchema": "public", + "type": "text", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, "name": "slug", "entityType": "columns", - "schema": "public", "table": "categories" }, { "type": "text", - "typeSchema": null, "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "slug", + "name": "category_slug", "entityType": "columns", - "schema": "public", "table": "models" }, { - "type": "text", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "name", + "name": "date_added", "entityType": "columns", - "schema": "public", "table": "models" }, { "type": "text", - "typeSchema": null, "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, "name": "description", "entityType": "columns", - "schema": "public", "table": "models" }, { - "type": "integer", - "typeSchema": null, + "type": "text", "notNull": true, - "dimensions": 0, - "default": "0", + "autoincrement": false, + "default": null, "generated": null, - "identity": null, - "name": "likes", + "name": "image", "entityType": "columns", - "schema": "public", "table": "models" }, { - "type": "text", - "typeSchema": null, + "type": "integer", "notNull": true, - "dimensions": 0, - "default": null, + "autoincrement": false, + "default": "0", "generated": null, - "identity": null, - "name": "image", + "name": "likes", "entityType": "columns", - "schema": "public", "table": "models" }, { - "type": "category_slug", - "typeSchema": "public", + "type": "text", "notNull": true, - "dimensions": 0, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "category_slug", + "name": "name", "entityType": "columns", - "schema": "public", "table": "models" }, { "type": "text", - "typeSchema": null, - "notNull": true, - "dimensions": 0, + "notNull": false, + "autoincrement": false, "default": null, "generated": null, - "identity": null, - "name": "user_id", + "name": "slug", "entityType": "columns", - "schema": "public", "table": "models" }, { - "type": "timestamp with time zone", - "typeSchema": null, + "type": "text", "notNull": true, - "dimensions": 0, - "default": "now()", + "autoincrement": false, + "default": null, "generated": null, - "identity": null, - "name": "date_added", + "name": "user_id", "entityType": "columns", - "schema": "public", "table": "models" }, { - "nameExplicit": true, - "columns": [ - { - "value": "user_id", - "isExpression": false, - "asc": true, - "nullsFirst": false, - "opclass": null - } - ], - "isUnique": false, - "where": null, - "with": "", - "method": "btree", - "concurrently": false, - "name": "account_userId_idx", - "entityType": "indexes", - "schema": "public", - "table": "account" - }, - { - "nameExplicit": true, - "columns": [ - { - "value": "user_id", - "isExpression": false, - "asc": true, - "nullsFirst": false, - "opclass": null - } - ], - "isUnique": false, - "where": null, - "with": "", - "method": "btree", - "concurrently": false, - "name": "session_userId_idx", - "entityType": "indexes", - "schema": "public", - "table": "session" - }, - { - "nameExplicit": true, - "columns": [ - { - "value": "identifier", - "isExpression": false, - "asc": true, - "nullsFirst": false, - "opclass": null - } - ], - "isUnique": false, - "where": null, - "with": "", - "method": "btree", - "concurrently": false, - "name": "verification_identifier_idx", - "entityType": "indexes", - "schema": "public", - "table": "verification" - }, - { - "nameExplicit": false, "columns": ["user_id"], - "schemaTo": "public", "tableTo": "user", "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", - "name": "account_user_id_user_id_fkey", + "nameExplicit": false, + "name": "fk_account_user_id_user_id_fk", "entityType": "fks", - "schema": "public", "table": "account" }, { - "nameExplicit": false, "columns": ["user_id"], - "schemaTo": "public", "tableTo": "user", "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", - "name": "session_user_id_user_id_fkey", + "nameExplicit": false, + "name": "fk_session_user_id_user_id_fk", "entityType": "fks", - "schema": "public", "table": "session" }, { - "nameExplicit": false, - "columns": ["user_id"], - "schemaTo": "public", - "tableTo": "user", - "columnsTo": ["id"], + "columns": ["model_slug"], + "tableTo": "models", + "columnsTo": ["slug"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", - "name": "likes_user_id_user_id_fkey", + "nameExplicit": false, + "name": "fk_likes_model_slug_models_slug_fk", "entityType": "fks", - "schema": "public", "table": "likes" }, { - "nameExplicit": false, - "columns": ["model_slug"], - "schemaTo": "public", - "tableTo": "models", - "columnsTo": ["slug"], + "columns": ["user_id"], + "tableTo": "user", + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", - "name": "likes_model_slug_models_slug_fkey", + "nameExplicit": false, + "name": "fk_likes_user_id_user_id_fk", "entityType": "fks", - "schema": "public", "table": "likes" }, { - "nameExplicit": false, "columns": ["category_slug"], - "schemaTo": "public", "tableTo": "categories", "columnsTo": ["slug"], "onUpdate": "NO ACTION", "onDelete": "NO ACTION", - "name": "models_category_slug_categories_slug_fkey", + "nameExplicit": false, + "name": "fk_models_category_slug_categories_slug_fk", "entityType": "fks", - "schema": "public", "table": "models" }, { - "nameExplicit": false, "columns": ["user_id"], - "schemaTo": "public", "tableTo": "user", "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", - "name": "models_user_id_user_id_fkey", + "nameExplicit": false, + "name": "fk_models_user_id_user_id_fk", "entityType": "fks", - "schema": "public", "table": "models" }, { "columns": ["id"], "nameExplicit": false, - "name": "account_pkey", - "schema": "public", + "name": "account_pk", "table": "account", "entityType": "pks" }, { "columns": ["id"], "nameExplicit": false, - "name": "session_pkey", - "schema": "public", + "name": "session_pk", "table": "session", "entityType": "pks" }, { "columns": ["id"], "nameExplicit": false, - "name": "user_pkey", - "schema": "public", + "name": "user_pk", "table": "user", "entityType": "pks" }, { "columns": ["id"], "nameExplicit": false, - "name": "verification_pkey", - "schema": "public", + "name": "verification_pk", "table": "verification", "entityType": "pks" }, { "columns": ["id"], "nameExplicit": false, - "name": "likes_pkey", - "schema": "public", + "name": "likes_pk", "table": "likes", "entityType": "pks" }, { "columns": ["id"], "nameExplicit": false, - "name": "categories_pkey", - "schema": "public", + "name": "categories_pk", "table": "categories", "entityType": "pks" }, { "columns": ["slug"], "nameExplicit": false, - "name": "models_pkey", - "schema": "public", + "name": "models_pk", "table": "models", "entityType": "pks" }, { - "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "account_userId_idx", + "entityType": "indexes", + "table": "account" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "session_userId_idx", + "entityType": "indexes", + "table": "session" + }, + { + "columns": [ + { + "value": "identifier", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "verification_identifier_idx", + "entityType": "indexes", + "table": "verification" + }, + { "columns": ["user_id", "model_slug"], - "nullsNotDistinct": false, + "nameExplicit": true, "name": "unique_user_model", "entityType": "uniques", - "schema": "public", "table": "likes" }, { - "nameExplicit": false, "columns": ["token"], - "nullsNotDistinct": false, - "name": "session_token_key", - "schema": "public", - "table": "session", - "entityType": "uniques" + "nameExplicit": false, + "name": "session_token_unique", + "entityType": "uniques", + "table": "session" }, { - "nameExplicit": false, "columns": ["email"], - "nullsNotDistinct": false, - "name": "user_email_key", - "schema": "public", - "table": "user", - "entityType": "uniques" + "nameExplicit": false, + "name": "user_email_unique", + "entityType": "uniques", + "table": "user" }, { - "nameExplicit": false, "columns": ["slug"], - "nullsNotDistinct": false, - "name": "categories_slug_key", - "schema": "public", - "table": "categories", - "entityType": "uniques" + "nameExplicit": false, + "name": "categories_slug_unique", + "entityType": "uniques", + "table": "categories" }, { - "nameExplicit": false, "columns": ["name"], - "nullsNotDistinct": false, - "name": "models_name_key", - "schema": "public", - "table": "models", - "entityType": "uniques" + "nameExplicit": false, + "name": "models_name_unique", + "entityType": "uniques", + "table": "models" } ], "renames": [] diff --git a/src/db/schema/auth.ts b/src/db/schema/auth.ts index e72a1b5..61118a6 100644 --- a/src/db/schema/auth.ts +++ b/src/db/schema/auth.ts @@ -1,28 +1,35 @@ -import { boolean, index, pgTable, text, timestamp } from "drizzle-orm/pg-core"; +import { sql } from "drizzle-orm"; +import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; import type { User } from "../brands"; -export const user = pgTable("user", { - createdAt: timestamp("created_at").defaultNow().notNull(), +export const user = sqliteTable("user", { + createdAt: integer("created_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .notNull(), email: text("email").notNull().unique(), - emailVerified: boolean("email_verified").default(false).notNull(), + emailVerified: integer("email_verified", { mode: "boolean" }) + .default(false) + .notNull(), id: text("id").primaryKey().$type(), image: text("image"), name: text("name").notNull(), - updatedAt: timestamp("updated_at") - .defaultNow() + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) .$onUpdate(() => /* @__PURE__ */ new Date()) .notNull(), }); -export const session = pgTable( +export const session = sqliteTable( "session", { - createdAt: timestamp("created_at").defaultNow().notNull(), - expiresAt: timestamp("expires_at").notNull(), + createdAt: integer("created_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .notNull(), + expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(), id: text("id").primaryKey(), ipAddress: text("ip_address"), token: text("token").notNull().unique(), - updatedAt: timestamp("updated_at") + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) .$onUpdate(() => /* @__PURE__ */ new Date()) .notNull(), userAgent: text("user_agent"), @@ -33,21 +40,27 @@ export const session = pgTable( (table) => [index("session_userId_idx").on(table.userId)], ); -export const account = pgTable( +export const account = sqliteTable( "account", { accessToken: text("access_token"), - accessTokenExpiresAt: timestamp("access_token_expires_at"), + accessTokenExpiresAt: integer("access_token_expires_at", { + mode: "timestamp_ms", + }), accountId: text("account_id").notNull(), - createdAt: timestamp("created_at").defaultNow().notNull(), + createdAt: integer("created_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .notNull(), id: text("id").primaryKey(), idToken: text("id_token"), password: text("password"), providerId: text("provider_id").notNull(), refreshToken: text("refresh_token"), - refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), + refreshTokenExpiresAt: integer("refresh_token_expires_at", { + mode: "timestamp_ms", + }), scope: text("scope"), - updatedAt: timestamp("updated_at") + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) .$onUpdate(() => /* @__PURE__ */ new Date()) .notNull(), userId: text("user_id") @@ -57,15 +70,17 @@ export const account = pgTable( (table) => [index("account_userId_idx").on(table.userId)], ); -export const verification = pgTable( +export const verification = sqliteTable( "verification", { - createdAt: timestamp("created_at").defaultNow().notNull(), - expiresAt: timestamp("expires_at").notNull(), + createdAt: integer("created_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) + .notNull(), + expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(), id: text("id").primaryKey(), identifier: text("identifier").notNull(), - updatedAt: timestamp("updated_at") - .defaultNow() + updatedAt: integer("updated_at", { mode: "timestamp_ms" }) + .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`) .$onUpdate(() => /* @__PURE__ */ new Date()) .notNull(), value: text("value").notNull(), diff --git a/src/db/schema/likes.ts b/src/db/schema/likes.ts index 7e34c19..e50fc3f 100644 --- a/src/db/schema/likes.ts +++ b/src/db/schema/likes.ts @@ -1,14 +1,14 @@ -import { pgTable, serial, text, timestamp, unique } from "drizzle-orm/pg-core"; +import { integer, sqliteTable, text, unique } from "drizzle-orm/sqlite-core"; import { user } from "./auth"; import { models } from "./models"; -export const likes = pgTable( +export const likes = sqliteTable( "likes", { - createdAt: timestamp("created_at", { withTimezone: true }) + createdAt: integer("created_at", { mode: "timestamp_ms" }) .notNull() - .defaultNow(), - id: serial("id").primaryKey(), + .$defaultFn(() => new Date()), + id: integer("id").primaryKey({ autoIncrement: true }), modelSlug: text("model_slug") .notNull() .references(() => models.slug, { onDelete: "cascade" }), diff --git a/src/db/schema/models.ts b/src/db/schema/models.ts index 8c4e384..09d54e2 100644 --- a/src/db/schema/models.ts +++ b/src/db/schema/models.ts @@ -1,35 +1,25 @@ -import { - integer, - pgEnum, - pgTable, - serial, - text, - timestamp, -} from "drizzle-orm/pg-core"; +import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; import { CATEGORIES, type Category } from "../categories"; import { user } from "./auth"; -export const categorySlugEnum = pgEnum( - "category_slug", - CATEGORIES.map((category) => category.slug) as [ - Category["slug"], - ...Category["slug"][], - ], -); +const categorySlugValues = CATEGORIES.map((category) => category.slug) as [ + Category["slug"], + ...Category["slug"][], +]; -export const categories = pgTable("categories", { +export const categories = sqliteTable("categories", { displayName: text("display_name").notNull(), - id: serial("id").primaryKey(), - slug: categorySlugEnum("slug").notNull().unique(), + id: integer("id").primaryKey({ autoIncrement: true }), + slug: text("slug", { enum: categorySlugValues }).notNull().unique(), }); -export const models = pgTable("models", { - categorySlug: categorySlugEnum("category_slug") +export const models = sqliteTable("models", { + categorySlug: text("category_slug", { enum: categorySlugValues }) .notNull() .references(() => categories.slug), - dateAdded: timestamp("date_added", { withTimezone: true }) + dateAdded: integer("date_added", { mode: "timestamp_ms" }) .notNull() - .defaultNow(), + .$defaultFn(() => new Date()), description: text("description").notNull(), image: text("image").notNull(), likes: integer("likes").notNull().default(0), diff --git a/src/db/seed.ts b/src/db/seed.ts index 21173cb..6d5bdc4 100644 --- a/src/db/seed.ts +++ b/src/db/seed.ts @@ -78,12 +78,11 @@ async function seed() { // Update every model's likes count in a single statement. A correlated // subquery avoids both an awaited loop and Promise.all fan-out, keeping - // this to one round-trip (gentle on Neon free-tier connection limits) and - // correctly sets 0 for models with no likes. + // this to one round-trip and correctly sets 0 for models with no likes. console.log("🔢 Updating likes counts..."); await db.update(models).set({ likes: sql`( - SELECT COUNT(*)::int + SELECT COUNT(*) FROM ${likes} WHERE ${likes.modelSlug} = ${models.slug} )`, diff --git a/src/env.d.ts b/src/env.d.ts index c36facd..cb20c1d 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -34,9 +34,7 @@ export type CoercedEnvSchema = { /** * **DATABASE_URL** 🔐 _sensitive_ - * PostgreSQL connection string (Neon) — Drizzle ORM, Better Auth adapter, and `db:*` scripts via `varlock run`. - * Use the *pooled* host (`ep-…-pooler.…aws.neon.tech`) for app/runtime. Prefer `sslmode=verify-full`. - * Optional: `&connect_timeout=30` if cold starts still ETIMEDOUT during `next build`. + * Legacy Neon PostgreSQL URL — retained in Bitwarden; unused by app after Turso cutover (Drizzle / Better Auth use TURSO_*). * ![icon](data:image/svg+xml;utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2032%2032%22%3E%3Cpath%20fill%3D%22%23808080%22%20d%3D%22M29%2022h-5a2.003%202.003%200%200%201-2-2v-6a2%202%200%200%201%202-2h5v2h-5v6h5ZM18%2012h-4V8h-2v14h6a2.003%202.003%200%200%200%202-2v-6a2%202%200%200%200-2-2m-4%208v-6h4v6Zm-6-8H3v2h5v2H4a2%202%200%200%200-2%202v2a2%202%200%200%200%202%202h6v-8a2%202%200%200%200-2-2m0%208H4v-2h4Z%22%2F%3E%3C%2Fsvg%3E) * * 📚 {@link https://neon.tech/docs/connect/connection-pooling} @@ -53,13 +51,33 @@ export type CoercedEnvSchema = { */ NEXT_PUBLIC_SITE_URL: string; + /** + * **TURSO_DATABASE_AUTH** 🔐 _sensitive_ + * Turso (libSQL) auth token — drizzle-kit / @libsql/client `authToken`. Keep server-only. + * ![icon](data:image/svg+xml;utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2032%2032%22%3E%3Cpath%20fill%3D%22%23808080%22%20d%3D%22M29%2022h-5a2.003%202.003%200%200%201-2-2v-6a2%202%200%200%201%202-2h5v2h-5v6h5ZM18%2012h-4V8h-2v14h6a2.003%202.003%200%200%200%202-2v-6a2%202%200%200%200-2-2m-4%208v-6h4v6Zm-6-8H3v2h5v2H4a2%202%200%200%200-2%202v2a2%202%200%200%200%202%202h6v-8a2%202%200%200%200-2-2m0%208H4v-2h4Z%22%2F%3E%3C%2Fsvg%3E) + * + * 📚 {@link https://docs.turso.tech/cli/db/tokens/create} + * 📚 {@link https://orm.drizzle.team/docs/connect-turso} + */ + TURSO_DATABASE_AUTH: string; + + /** + * **TURSO_DATABASE_URL** 🔐 _sensitive_ + * Turso database URL (`libsql://…`) — Drizzle ORM, Better Auth adapter, and `db:*` scripts via `varlock run`. + * ![icon](data:image/svg+xml;utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2032%2032%22%3E%3Cpath%20fill%3D%22%23808080%22%20d%3D%22M29%2022h-5a2.003%202.003%200%200%201-2-2v-6a2%202%200%200%201%202-2h5v2h-5v6h5ZM18%2012h-4V8h-2v14h6a2.003%202.003%200%200%200%202-2v-6a2%202%200%200%200-2-2m-4%208v-6h4v6Zm-6-8H3v2h5v2H4a2%202%200%200%200-2%202v2a2%202%200%200%200%202%202h6v-8a2%202%200%200%200-2-2m0%208H4v-2h4Z%22%2F%3E%3C%2Fsvg%3E) + * + * 📚 {@link https://docs.turso.tech/quickstart} + * 📚 {@link https://orm.drizzle.team/docs/connect-turso} + */ + TURSO_DATABASE_URL: string; + }; -type _CoercedEnvSchema_8b238210 = CoercedEnvSchema; +type _CoercedEnvSchema_ad610038 = CoercedEnvSchema; declare module 'varlock/env' { - export interface TypedEnvSchema extends Readonly<_CoercedEnvSchema_8b238210> {} - export interface PublicTypedEnvSchema extends Readonly> {} + export interface TypedEnvSchema extends Readonly<_CoercedEnvSchema_ad610038> {} + export interface PublicTypedEnvSchema extends Readonly> {} } @@ -69,17 +87,17 @@ export type EnvSchemaAsStrings = { : (CoercedEnvSchema[Property] extends boolean ? ('true' | 'false') : string) }; -type _EnvSchemaAsStrings_8b238210 = EnvSchemaAsStrings; +type _EnvSchemaAsStrings_ad610038 = EnvSchemaAsStrings; declare global { // add types for global import.meta.env - interface ImportMetaEnv extends _EnvSchemaAsStrings_8b238210 {} + interface ImportMetaEnv extends _EnvSchemaAsStrings_ad610038 {} interface ImportMeta { readonly env: ImportMetaEnv; } // add types for global process.env namespace NodeJS { - interface ProcessEnv extends _EnvSchemaAsStrings_8b238210 {} + interface ProcessEnv extends _EnvSchemaAsStrings_ad610038 {} } } \ No newline at end of file diff --git a/src/features/auth/actions/sign-in-action.ts b/src/features/auth/actions/sign-in-action.ts index b745ab8..0614393 100644 --- a/src/features/auth/actions/sign-in-action.ts +++ b/src/features/auth/actions/sign-in-action.ts @@ -4,6 +4,7 @@ import { headers } from "next/headers"; import { RedirectType, redirect, unstable_rethrow } from "next/navigation"; import { examples, + type InferOutput, maxLength, minLength, object, @@ -14,9 +15,11 @@ import { import { auth } from "@/lib/auth"; import type { Maybe } from "@/types"; import { - type ActionState, - fromErrorToActionState, -} from "@/utils/to-action-state"; + formDataToSafePayload, + type SafeFormFields, +} from "@/utils/to-action-state/form-data-to-safe-payload"; +import { fromErrorToActionState } from "@/utils/to-action-state/to-action-state"; +import type { ActionState } from "@/utils/to-action-state/types"; import { MAX_EMAIL_LENGTH, MAX_PASSWORD_LENGTH, @@ -50,10 +53,15 @@ const signInFormSchema = object({ ), }); +type SignInForm = InferOutput; +type SignInPayload = SafeFormFields; + const signInAction = async ( - _: Maybe, + _: Maybe>, formData: FormData, -): Promise => { +): Promise> => { + const payload = formDataToSafePayload(formData); + try { const { email, password } = parse( signInFormSchema, @@ -76,7 +84,7 @@ const signInAction = async ( } catch (error) { unstable_rethrow(error); - return fromErrorToActionState(error, formData); + return fromErrorToActionState(error, payload); } }; diff --git a/src/features/auth/actions/sign-out-action.ts b/src/features/auth/actions/sign-out-action.ts index 412c966..1a88251 100644 --- a/src/features/auth/actions/sign-out-action.ts +++ b/src/features/auth/actions/sign-out-action.ts @@ -3,7 +3,7 @@ import { headers } from "next/headers"; import { RedirectType, redirect } from "next/navigation"; import { auth } from "@/lib/auth"; -import { fromErrorToActionState } from "@/utils/to-action-state"; +import { fromErrorToActionState } from "@/utils/to-action-state/to-action-state"; import { tryCatch } from "@/utils/try-catch"; // Server action for sign-out diff --git a/src/features/auth/actions/sign-up-action.ts b/src/features/auth/actions/sign-up-action.ts index 8fd246e..86bfc8b 100644 --- a/src/features/auth/actions/sign-up-action.ts +++ b/src/features/auth/actions/sign-up-action.ts @@ -2,13 +2,23 @@ import { headers } from "next/headers"; import { RedirectType, redirect, unstable_rethrow } from "next/navigation"; -import { maxLength, minLength, object, parse, pipe, string } from "valibot"; +import { + type InferOutput, + maxLength, + minLength, + object, + parse, + pipe, + string, +} from "valibot"; import { auth } from "@/lib/auth"; import type { Maybe, Prettify } from "@/types"; import { - type ActionState, - fromErrorToActionState, -} from "@/utils/to-action-state"; + formDataToSafePayload, + type SafeFormFields, +} from "@/utils/to-action-state/form-data-to-safe-payload"; +import { fromErrorToActionState } from "@/utils/to-action-state/to-action-state"; +import type { ActionState } from "@/utils/to-action-state/types"; import type { User } from "../auth-types"; import { MAX_EMAIL_LENGTH, @@ -18,7 +28,6 @@ import { MIN_PASSWORD_LENGTH, } from "../constants"; -// Valibot schema for sign-up form const signUpFormSchema = object({ email: pipe( string("Email must be a string"), @@ -44,23 +53,25 @@ const signUpFormSchema = object({ ), }); +type SignUpForm = InferOutput; +type SignUpPayload = SafeFormFields; + interface SignUpData { user: Prettify>; } -// Server action for sign-up const signUpAction = async ( - _: Maybe>, + _: Maybe>, formData: FormData, -): Promise> => { +): Promise> => { + const payload = formDataToSafePayload(formData); + try { - // Validate form data with Valibot (parse throws ValiError on failure) const { email, password, name } = parse( signUpFormSchema, Object.fromEntries(formData.entries()), ); - // Call Better Auth sign-up API const session = await auth.api.signUpEmail({ body: { email, @@ -74,14 +85,11 @@ const signUpAction = async ( throw new Error("Failed to sign up"); } - // Redirect on success throw redirect("/", RedirectType.replace); } catch (error) { - // Handle redirect separately (it's not an error) unstable_rethrow(error); - // Convert error to ActionState - return fromErrorToActionState(error, formData); + return fromErrorToActionState(error, payload); } }; diff --git a/src/features/auth/components/auth-card.tsx b/src/features/auth/components/auth-card.tsx index 2075386..b3bb56b 100644 --- a/src/features/auth/components/auth-card.tsx +++ b/src/features/auth/components/auth-card.tsx @@ -1,5 +1,6 @@ -import { css } from "@styled-system/css"; +import { css, viewTransition } from "@styled-system/css"; import type { ReactNode } from "react"; +import { ViewTransition } from "react"; import type { Children, Prettify } from "@/types"; type AuthCardProps = Prettify< @@ -9,30 +10,55 @@ type AuthCardProps = Prettify< } >; +const authFooterVt = viewTransition({ + new: { + "--slide-distance-y": "-20px", + animationDuration: "250ms", + animationName: "fade-in, slide-in-y", + animationTimingFunction: "glide", + }, + old: { + "--slide-distance-y": "20px", + animationDuration: "250ms", + animationName: "fade-out, slide-out-y", + animationTimingFunction: "glide", + }, +}); + const AuthCard = ({ title, footer, children }: AuthCardProps) => ( -
-

+
- {title} -

- {children} - {footer} -
+ +

+ {title} +

+
+ {children} + +
{footer}
+
+ +
); export { AuthCard }; diff --git a/src/features/categories/components/categories-block-transition.tsx b/src/features/categories/components/categories-block-transition.tsx index 91263d0..125522e 100644 --- a/src/features/categories/components/categories-block-transition.tsx +++ b/src/features/categories/components/categories-block-transition.tsx @@ -1,20 +1,39 @@ +import { viewTransition } from "@styled-system/css"; import { ViewTransition } from "react"; import type { Children, Prettify } from "@/types"; import type { CategoryName } from "../types"; type CategoriesBlockTransitionProps = Prettify; +const enterBlock = viewTransition({ + new: { + "--slide-distance-y": "-20px", + animationDuration: "200ms", + animationName: "fade-in, slide-in-y", + animationTimingFunction: "glide", + }, +}); + +const exitBlock = viewTransition({ + old: { + "--slide-distance-y": "20px", + animationDuration: "200ms", + animationName: "fade-out, slide-out-y", + animationTimingFunction: "glide", + }, +}); + const CategoriesBlockTransition = ({ children, categoryName, }: CategoriesBlockTransitionProps) => ( ; +const modelCardEnter = viewTransition({ + new: { + _only: { + "--slide-distance": "-20px", + animation: "fade-in 250ms, slide-in 250ms", + }, + }, +}); + +const modelCardExit = viewTransition({ + old: { + _only: { + "--slide-distance": "20px", + animation: "fade-out 250ms, slide-out 250ms", + }, + }, +}); + const ModelCard = ({ isAuthenticated, model: { slug, name, description, image, categorySlug, likes, hasLiked }, + priority, }: ModelCardProps) => ( - +
{description} diff --git a/src/features/models/components/models-grid.tsx b/src/features/models/components/models-grid.tsx index 5b31560..c322bdb 100644 --- a/src/features/models/components/models-grid.tsx +++ b/src/features/models/components/models-grid.tsx @@ -18,9 +18,10 @@ type ModelsGridProps = Prettify< >; const ModelsGrid = ({ isAuthenticated, title, models }: ModelsGridProps) => { - const renderModelCardProps = (model: ModelWithLikeStatus) => ({ + const renderModelCardProps = (model: ModelWithLikeStatus, index: number) => ({ isAuthenticated, model, + priority: index < 4, }); return (
diff --git a/src/features/models/likes/actions/toggle-like.ts b/src/features/models/likes/actions/toggle-like.ts index 012381c..bf1eb08 100644 --- a/src/features/models/likes/actions/toggle-like.ts +++ b/src/features/models/likes/actions/toggle-like.ts @@ -5,10 +5,10 @@ import { toggleLikeForModel } from "@/features/models/likes/dal/toggle-like"; import type { Maybe } from "@/types"; import { invalidateModel } from "@/utils/cache-invalidation"; import { - type ActionState, fromErrorToActionState, toActionState, -} from "@/utils/to-action-state"; +} from "@/utils/to-action-state/to-action-state"; +import type { ActionState } from "@/utils/to-action-state/types"; import type { LikesCount } from "../types"; const likeSchema = object({ diff --git a/src/features/models/likes/components/likes-count-transition.tsx b/src/features/models/likes/components/likes-count-transition.tsx index bf00eba..40c5b2c 100644 --- a/src/features/models/likes/components/likes-count-transition.tsx +++ b/src/features/models/likes/components/likes-count-transition.tsx @@ -1,9 +1,40 @@ +import { viewTransition } from "@styled-system/css"; import { ViewTransition } from "react"; import type { Children, Prettify } from "@/types"; import type { LikesCount } from "../types"; type LikesCountTransitionProps = Prettify; +const likesUpdateIncrease = viewTransition({ + new: { + "--slide-distance-y": "-10px", + animationDuration: "200ms", + animationName: "fade-out, slide-out-y", + animationTimingFunction: "inDramatic", + }, + old: { + "--slide-distance-y": "8px", + animationDuration: "200ms", + animationName: "slide-out-y, fade-out", + animationTimingFunction: "outDramatic", + }, +}); + +const likesUpdateDecrease = viewTransition({ + new: { + "--slide-distance-y": "10px", + animationDuration: "200ms", + animationName: "fade-in, slide-in-y", + animationTimingFunction: "inDramatic", + }, + old: { + "--slide-distance-y": "-8px", + animationDuration: "200ms", + animationName: "slide-out-y, fade-out", + animationTimingFunction: "outDramatic", + }, +}); + const LikesCountTransition = ({ likesCount, children, @@ -11,9 +42,9 @@ const LikesCountTransition = ({ {children} diff --git a/src/features/models/likes/hooks/use-heart-like.ts b/src/features/models/likes/hooks/use-heart-like.ts index 6a6a2dd..d9b3c79 100644 --- a/src/features/models/likes/hooks/use-heart-like.ts +++ b/src/features/models/likes/hooks/use-heart-like.ts @@ -8,7 +8,7 @@ import { useTransition, } from "react"; import type { Maybe, Prettify } from "@/types"; -import type { ActionState } from "@/utils/to-action-state"; +import type { ActionState } from "@/utils/to-action-state/types"; import type { HeartButtonClientProps } from "../components/heart-button-client"; import type { HeartVisualState, LikesCount } from "../types"; import { diff --git a/src/features/models/queries/build-models-where.ts b/src/features/models/queries/build-models-where.ts index bce773b..8e8ea2e 100644 --- a/src/features/models/queries/build-models-where.ts +++ b/src/features/models/queries/build-models-where.ts @@ -1,4 +1,4 @@ -import { and, eq, ilike, or, type SQL } from "drizzle-orm"; +import { and, eq, like, or, type SQL, sql } from "drizzle-orm"; import type { CategorySlug } from "@/db/brands"; import { models } from "@/db/schema/models"; import type { Maybe } from "@/types"; @@ -12,8 +12,8 @@ const buildModelsWhere = ( if (searchPattern) { conditions.push( or( - ilike(models.name, searchPattern), - ilike(models.description, searchPattern), + like(sql`${models.name} COLLATE NOCASE`, searchPattern), + like(sql`${models.description} COLLATE NOCASE`, searchPattern), ) as SQL, ); } diff --git a/src/features/pagination/components/pagination-offset-transition.tsx b/src/features/pagination/components/pagination-offset-transition.tsx index cbe3074..ed76083 100644 --- a/src/features/pagination/components/pagination-offset-transition.tsx +++ b/src/features/pagination/components/pagination-offset-transition.tsx @@ -1,3 +1,4 @@ +import { viewTransition } from "@styled-system/css"; import { ViewTransition } from "react"; import type { Children, Prettify } from "@/types"; import type { Page } from "../types"; @@ -8,20 +9,48 @@ type PaginationOffsetTransitionProps = Prettify< } >; +const enterLeft = viewTransition({ + new: { + "--slide-distance": "-60px", + animation: "fade-in 250ms, slide-in 250ms", + }, +}); + +const enterRight = viewTransition({ + new: { + "--slide-distance": "calc(100vw + 60px)", + animation: "fade-in 250ms, slide-in 250ms", + }, +}); + +const exitLeft = viewTransition({ + old: { + "--slide-distance": "-60px", + animation: "fade-out 250ms, slide-out 250ms", + }, +}); + +const exitRight = viewTransition({ + old: { + "--slide-distance": "calc(100vw + 60px)", + animation: "fade-out 250ms, slide-out 250ms", + }, +}); + const PaginationOffsetTransition = ({ children, metadata, }: PaginationOffsetTransitionProps) => ( diff --git a/src/lib/auth.cli.config.ts b/src/lib/auth.cli.config.ts new file mode 100644 index 0000000..88bf839 --- /dev/null +++ b/src/lib/auth.cli.config.ts @@ -0,0 +1,23 @@ +import { drizzleAdapter } from "@better-auth/drizzle-adapter/relations-v2"; +import { betterAuth } from "better-auth/minimal"; +import { db } from "@/db"; +import { schema } from "@/db/schema"; + +/** + * CLI-only Better Auth config for `auth:generate`. + * No secrets, OAuth creds, or runtime plugins — keep schema-affecting options + * in sync with `auth.ts` (adapter provider, email/password, experimental joins, + * and any plugin that defines tables/columns). + */ +export const auth = betterAuth({ + database: drizzleAdapter(db, { + provider: "sqlite", + schema, + }), + emailAndPassword: { + enabled: true, + }, + experimental: { joins: true }, + // Placeholder so `betterAuth()` constructs without loading ENV secrets. + secret: "cli-generate-only", +}); diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 20f48e4..37d3744 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -1,4 +1,5 @@ import "server-only"; + import { drizzleAdapter } from "@better-auth/drizzle-adapter/relations-v2"; import { betterAuth } from "better-auth/minimal"; import { nextCookies } from "better-auth/next-js"; @@ -6,11 +7,17 @@ import { openAPI } from "better-auth/plugins"; import { ENV } from "varlock/env"; import { db } from "@/db"; import { schema } from "@/db/schema"; + +/** + * Runtime Better Auth instance (server-only). + * Schema generation uses `auth.cli.config.ts` instead — do not import this file + * from the CLI config path, and do not import `auth.cli.config` from app code. + */ export const auth = betterAuth({ basePath: "/api/auth", baseURL: ENV.NEXT_PUBLIC_SITE_URL, database: drizzleAdapter(db, { - provider: "pg", + provider: "sqlite", schema, }), emailAndPassword: { diff --git a/src/utils/to-action-state/form-data-to-safe-payload.ts b/src/utils/to-action-state/form-data-to-safe-payload.ts new file mode 100644 index 0000000..65e50a4 --- /dev/null +++ b/src/utils/to-action-state/form-data-to-safe-payload.ts @@ -0,0 +1,36 @@ +/** Never echoed back through ActionState.payload (RSC → client). */ +const SENSITIVE_FORM_KEYS = [ + "confirmPassword", + "newPassword", + "password", +] as const; + +type SensitiveFormKey = (typeof SENSITIVE_FORM_KEYS)[number]; + +const sensitiveKeySet = new Set(SENSITIVE_FORM_KEYS); + +/** Full form minus secrets — use as ActionState U; payload is Partial of this. */ +export type SafeFormFields> = Omit< + T, + SensitiveFormKey +>; + +/** FormData → plain Partial payload for ActionState; strips sensitive keys. */ +export const formDataToSafePayload = < + T extends Record = Record, +>( + formData: FormData, +): Partial> => { + const payload: Record = {}; + + for (const [key, value] of formData.entries()) { + if (sensitiveKeySet.has(key)) { + continue; + } + if (typeof value === "string") { + payload[key] = value; + } + } + + return payload as Partial>; +}; diff --git a/src/utils/to-action-state.ts b/src/utils/to-action-state/to-action-state.ts similarity index 62% rename from src/utils/to-action-state.ts rename to src/utils/to-action-state/to-action-state.ts index fa740e6..0be284f 100644 --- a/src/utils/to-action-state.ts +++ b/src/utils/to-action-state/to-action-state.ts @@ -1,26 +1,20 @@ import { APIError } from "better-auth/api"; import { flatten, ValiError } from "valibot"; -import type { Maybe } from "@/types"; +import type { ActionState } from "./types"; -export interface ActionState { - data?: T; - fieldErrors: Record>; - message: string; - payload?: FormData; - status?: "SUCCESS" | "ERROR"; - timestamp: number; -} - -const fromErrorToActionState = ( +const fromErrorToActionState = < + T = unknown, + U extends Record = Record, +>( err: unknown, - formData?: FormData, -): ActionState => { + payload?: Partial, +): ActionState => { if (err instanceof ValiError) { const flattened = flatten(err.issues); return { fieldErrors: flattened.nested || {}, message: "", - payload: formData, + payload, status: "ERROR", timestamp: Date.now(), }; @@ -30,7 +24,7 @@ const fromErrorToActionState = ( return { fieldErrors: {}, message: err.message, - payload: formData, + payload, status: "ERROR", timestamp: Date.now(), }; @@ -39,22 +33,25 @@ const fromErrorToActionState = ( return { fieldErrors: {}, message: "An unknown error occurred", - payload: formData, + payload, status: "ERROR", timestamp: Date.now(), }; }; -const toActionState = ( +const toActionState = < + T = unknown, + U extends Record = Record, +>( message: string, status: ActionState["status"], - formData?: FormData, + payload?: Partial, data?: T, -): ActionState => ({ +): ActionState => ({ data, fieldErrors: {}, message, - payload: formData, + payload, status, timestamp: Date.now(), }); diff --git a/src/utils/to-action-state/types.ts b/src/utils/to-action-state/types.ts new file mode 100644 index 0000000..c83dac2 --- /dev/null +++ b/src/utils/to-action-state/types.ts @@ -0,0 +1,17 @@ +import type { Maybe } from "@/types"; + +/** + * T — success `data` + * U — safe form echo shape (plain fields; payload is Partial of U) + */ +export interface ActionState< + T = unknown, + U extends Record = Record, +> { + data?: T; + fieldErrors: Record>; + message: string; + payload?: Partial; + status?: "SUCCESS" | "ERROR"; + timestamp: number; +}