From 060668e8c08de249e5af1976447bb018a9ea0413 Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi Date: Tue, 27 May 2025 23:12:05 +0530 Subject: [PATCH] Fix: echo v2 --- apps/webapp/.prettierrc | 4 + apps/webapp/README.md | 57 +- apps/webapp/app/components/ErrorDisplay.tsx | 61 + .../app/components/layout/AppLayout.tsx | 75 + .../app/components/layout/LoginPageLayout.tsx | 51 + apps/webapp/app/components/logo/index.ts | 1 + apps/webapp/app/components/logo/logo.tsx | 67 + apps/webapp/app/components/ui/Headers.tsx | 90 + apps/webapp/app/components/ui/Paragraph.tsx | 95 + apps/webapp/app/components/ui/button.tsx | 88 + apps/webapp/app/components/ui/index.ts | 1 + apps/webapp/app/db.server.ts | 232 ++ apps/webapp/app/env.server.ts | 5 + apps/webapp/app/hooks/useChanged.ts | 26 + apps/webapp/app/hooks/usePostHog.ts | 49 + apps/webapp/app/hooks/useTypedMatchData.ts | 44 + apps/webapp/app/hooks/useUser.ts | 43 + apps/webapp/app/models/message.server.ts | 31 +- apps/webapp/app/models/user.server.ts | 155 + apps/webapp/app/root.tsx | 141 +- apps/webapp/app/routes/action.set-theme.ts | 4 + apps/webapp/app/routes/login.tsx | 31 + .../app/services/apiRateLimit.server.ts | 64 + apps/webapp/app/services/auth.server.ts | 20 + apps/webapp/app/services/authUser.ts | 3 + apps/webapp/app/services/googleAuth.server.ts | 54 + .../app/services/httpAsyncStorage.server.ts | 20 + .../app/services/impersonation.server.ts | 44 + apps/webapp/app/services/logger.service.ts | 296 ++ apps/webapp/app/services/postAuth.server.ts | 14 + .../app/services/sensitiveDataReplacer.ts | 33 + apps/webapp/app/services/session.server.ts | 27 + .../app/services/sessionStorage.server.ts | 35 + apps/webapp/app/tailwind.css | 133 +- apps/webapp/app/utils.ts | 21 +- apps/webapp/app/utils/httpErrors.ts | 24 + apps/webapp/app/utils/singleton.ts | 6 + apps/webapp/package.json | 74 +- apps/webapp/postcss.config.js | 6 - apps/webapp/prettier.config.cjs | 4 - apps/webapp/remix.config.js | 30 - apps/webapp/server.js | 51 + apps/webapp/tailwind.config.js | 167 - apps/webapp/tailwind.config.ts | 169 + apps/webapp/tsconfig.json | 11 +- apps/webapp/vite.config.ts | 2 + package.json | 26 +- packages/database/package.json | 5 +- .../20250527101713_init/migration.sql | 84 + .../migration.sql | 75 + .../prisma/migrations/migration_lock.toml | 3 + packages/database/prisma/schema.prisma | 107 +- pnpm-lock.yaml | 2716 +++++++++++++---- turbo.json | 35 +- 54 files changed, 4714 insertions(+), 996 deletions(-) create mode 100644 apps/webapp/.prettierrc create mode 100644 apps/webapp/app/components/ErrorDisplay.tsx create mode 100644 apps/webapp/app/components/layout/AppLayout.tsx create mode 100644 apps/webapp/app/components/layout/LoginPageLayout.tsx create mode 100644 apps/webapp/app/components/logo/index.ts create mode 100644 apps/webapp/app/components/logo/logo.tsx create mode 100644 apps/webapp/app/components/ui/Headers.tsx create mode 100644 apps/webapp/app/components/ui/Paragraph.tsx create mode 100644 apps/webapp/app/components/ui/button.tsx create mode 100644 apps/webapp/app/components/ui/index.ts create mode 100644 apps/webapp/app/db.server.ts create mode 100644 apps/webapp/app/hooks/useChanged.ts create mode 100644 apps/webapp/app/hooks/usePostHog.ts create mode 100644 apps/webapp/app/hooks/useTypedMatchData.ts create mode 100644 apps/webapp/app/hooks/useUser.ts create mode 100644 apps/webapp/app/models/user.server.ts create mode 100644 apps/webapp/app/routes/action.set-theme.ts create mode 100644 apps/webapp/app/routes/login.tsx create mode 100644 apps/webapp/app/services/apiRateLimit.server.ts create mode 100644 apps/webapp/app/services/auth.server.ts create mode 100644 apps/webapp/app/services/authUser.ts create mode 100644 apps/webapp/app/services/googleAuth.server.ts create mode 100644 apps/webapp/app/services/httpAsyncStorage.server.ts create mode 100644 apps/webapp/app/services/impersonation.server.ts create mode 100644 apps/webapp/app/services/logger.service.ts create mode 100644 apps/webapp/app/services/postAuth.server.ts create mode 100644 apps/webapp/app/services/sensitiveDataReplacer.ts create mode 100644 apps/webapp/app/services/sessionStorage.server.ts create mode 100644 apps/webapp/app/utils/httpErrors.ts create mode 100644 apps/webapp/app/utils/singleton.ts delete mode 100644 apps/webapp/postcss.config.js delete mode 100644 apps/webapp/prettier.config.cjs delete mode 100644 apps/webapp/remix.config.js create mode 100644 apps/webapp/server.js delete mode 100644 apps/webapp/tailwind.config.js create mode 100644 apps/webapp/tailwind.config.ts create mode 100644 packages/database/prisma/migrations/20250527101713_init/migration.sql create mode 100644 packages/database/prisma/migrations/20250527174127_add_space_queue/migration.sql create mode 100644 packages/database/prisma/migrations/migration_lock.toml diff --git a/apps/webapp/.prettierrc b/apps/webapp/.prettierrc new file mode 100644 index 0000000..cb90d49 --- /dev/null +++ b/apps/webapp/.prettierrc @@ -0,0 +1,4 @@ +{ + "tailwindConfig": "./tailwind.config.ts", + "plugins": [ "prettier-plugin-tailwindcss" ] +} \ No newline at end of file diff --git a/apps/webapp/README.md b/apps/webapp/README.md index 6c4d216..dbb2130 100644 --- a/apps/webapp/README.md +++ b/apps/webapp/README.md @@ -1,40 +1,43 @@ -# Welcome to Remix! +# Memory Plane -- 📖 [Remix docs](https://remix.run/docs) +Simple memory management system for AI agents with per-space ingestion and search capabilities. -## Development +## Core APIs -Run the dev server: +### 1. Ingest API -```shellscript -npm run dev -``` +- Endpoint per space for data ingestion +- Queue-based processing per user +- Creates and links graph nodes automatically +- Optional review queue for controlled ingestion -## Deployment +### 2. Search API -First, build your app for production: +- Simple text-based search +- Input: query string +- Output: relevant text matches +- Scoped to specific memory space -```sh -npm run build -``` +## Features (v1) -Then run the app in production mode: +[ ] Auto-mode default with optional queue review +[ ] Multiple Spaces support (unique URL per space) +[ ] Basic rules engine for ingestion filters +[ ] Clear, user-friendly guidelines +[ ] Simple text search -```sh -npm start -``` +## Usage Guidelines -Now you'll need to pick a host to deploy it to. +Store: -### DIY +- Conversation history +- User preferences +- Task context +- Reference materials -If you're familiar with deploying Node applications, the built-in Remix app server is production-ready. +Don't Store: -Make sure to deploy the output of `npm run build` - -- `build/server` -- `build/client` - -## Styling - -This template comes with [Tailwind CSS](https://tailwindcss.com/) already configured for a simple default starting experience. You can use whatever css framework you prefer. See the [Vite docs on css](https://vitejs.dev/guide/features.html#css) for more information. +- Sensitive data (PII) +- Credentials +- System logs +- Temporary data diff --git a/apps/webapp/app/components/ErrorDisplay.tsx b/apps/webapp/app/components/ErrorDisplay.tsx new file mode 100644 index 0000000..f288cee --- /dev/null +++ b/apps/webapp/app/components/ErrorDisplay.tsx @@ -0,0 +1,61 @@ +import { isRouteErrorResponse, useRouteError } from "@remix-run/react"; + +import { friendlyErrorDisplay } from "~/utils/httpErrors"; + +import { type ReactNode } from "react"; +import { Button } from "./ui"; +import { Header1 } from "./ui/Headers"; +import { Paragraph } from "./ui/Paragraph"; + +type ErrorDisplayOptions = { + button?: { + title: string; + to: string; + }; +}; + +export function RouteErrorDisplay(options?: ErrorDisplayOptions) { + const error = useRouteError(); + + return ( + <> + {isRouteErrorResponse(error) ? ( + + ) : error instanceof Error ? ( + + ) : ( + + )} + + ); +} + +type DisplayOptionsProps = { + title: string; + message?: ReactNode; +} & ErrorDisplayOptions; + +export function ErrorDisplay({ title, message, button }: DisplayOptionsProps) { + return ( +
+
+ {title} + {message && {message}} + +
+
+ ); +} diff --git a/apps/webapp/app/components/layout/AppLayout.tsx b/apps/webapp/app/components/layout/AppLayout.tsx new file mode 100644 index 0000000..40ff842 --- /dev/null +++ b/apps/webapp/app/components/layout/AppLayout.tsx @@ -0,0 +1,75 @@ +import { cn } from "~/lib/utils"; + +/** This container is used to surround the entire app, it correctly places the nav bar */ +export function AppContainer({ children }: { children: React.ReactNode }) { + return
{children}
; +} + +export function MainBody({ children }: { children: React.ReactNode }) { + return
{children}
; +} + +/** This container should be placed around the content on a page */ +export function PageContainer({ children }: { children: React.ReactNode }) { + return
{children}
; +} + +export function PageBody({ + children, + scrollable = true, + className, +}: { + children: React.ReactNode; + scrollable?: boolean; + className?: string; +}) { + return ( +
+ {children} +
+ ); +} + +export function MainCenteredContainer({ + children, + className, +}: { + children: React.ReactNode; + className?: string; +}) { + return ( +
+
+ {children} +
+
+ ); +} + +export function MainHorizontallyCenteredContainer({ + children, + className, +}: { + children: React.ReactNode; + className?: string; +}) { + return ( +
+
+ {children} +
+
+ ); +} diff --git a/apps/webapp/app/components/layout/LoginPageLayout.tsx b/apps/webapp/app/components/layout/LoginPageLayout.tsx new file mode 100644 index 0000000..c5b7f5e --- /dev/null +++ b/apps/webapp/app/components/layout/LoginPageLayout.tsx @@ -0,0 +1,51 @@ +import { useEffect, useState } from "react"; +import { Paragraph } from "../ui/Paragraph"; +import { Header3 } from "../ui/Headers"; +import { Button } from "../ui"; +import Logo from "../logo/logo"; +import { Theme, useTheme } from "remix-themes"; + +interface QuoteType { + quote: string; +} + +const quotes: QuoteType[] = [ + { + quote: + "Echo remembers that I prefer emails in dark mode and hate promotional content. It automatically filters and formats my communications just the way I like.", + }, + { + quote: + "When I mention liking Nike's latest running shoes, Echo remembers this preference and helps surface relevant product launches and deals across my browsing.", + }, + { + quote: + "Echo knows I'm a vegetarian and helps filter restaurant recommendations and recipes accordingly, without me having to specify it every time.", + }, + { + quote: + "By remembering that I prefer technical documentation with code examples, Echo helps prioritize learning resources that match my learning style.", + }, +]; + +export function LoginPageLayout({ children }: { children: React.ReactNode }) { + const [randomQuote, setRandomQuote] = useState(null); + useEffect(() => { + const randomIndex = Math.floor(Math.random() * quotes.length); + setRandomQuote(quotes[randomIndex]); + }, []); + const [, setTheme] = useTheme(); + + return ( +
+
+ + +
+ +
+ {children} +
+
+ ); +} diff --git a/apps/webapp/app/components/logo/index.ts b/apps/webapp/app/components/logo/index.ts new file mode 100644 index 0000000..4671724 --- /dev/null +++ b/apps/webapp/app/components/logo/index.ts @@ -0,0 +1 @@ +export * from "./logo"; diff --git a/apps/webapp/app/components/logo/logo.tsx b/apps/webapp/app/components/logo/logo.tsx new file mode 100644 index 0000000..95fc0b7 --- /dev/null +++ b/apps/webapp/app/components/logo/logo.tsx @@ -0,0 +1,67 @@ +import React from "react"; +import { Theme, useTheme } from "remix-themes"; + +export interface LogoProps { + width: number; + height: number; +} + +export default function StaticLogo({ width, height }: LogoProps) { + const [theme] = useTheme(); + + if (theme === Theme.LIGHT) { + return ( + + + + + + + + + + + ); + } + + return ( + + + + + + + + + + + + ); +} diff --git a/apps/webapp/app/components/ui/Headers.tsx b/apps/webapp/app/components/ui/Headers.tsx new file mode 100644 index 0000000..45473c5 --- /dev/null +++ b/apps/webapp/app/components/ui/Headers.tsx @@ -0,0 +1,90 @@ +import { cn } from "~/lib/utils"; + +const headerVariants = { + header1: { + text: "font-sans text-2xl leading-5 md:leading-6 lg:leading-7 font-medium", + spacing: "mb-2", + }, + header2: { + text: "font-sans text-base leading-6 font-medium", + spacing: "mb-2", + }, + header3: { + text: "font-sans text-sm leading-5 font-medium", + spacing: "mb-2", + }, +}; + +const textColorVariants = { + bright: "text-text-bright", + dimmed: "text-text-dimmed", +}; + +export type HeaderVariant = keyof typeof headerVariants; + +type HeaderProps = { + className?: string; + children: React.ReactNode; + spacing?: boolean; + textColor?: "bright" | "dimmed"; +} & React.HTMLAttributes; + +export function Header1({ + className, + children, + spacing = false, + textColor = "bright", +}: HeaderProps) { + return ( +

+ {children} +

+ ); +} + +export function Header2({ + className, + children, + spacing = false, + textColor = "bright", +}: HeaderProps) { + return ( +

+ {children} +

+ ); +} + +export function Header3({ + className, + children, + spacing = false, + textColor = "bright", +}: HeaderProps) { + return ( +

+ {children} +

+ ); +} diff --git a/apps/webapp/app/components/ui/Paragraph.tsx b/apps/webapp/app/components/ui/Paragraph.tsx new file mode 100644 index 0000000..26adf40 --- /dev/null +++ b/apps/webapp/app/components/ui/Paragraph.tsx @@ -0,0 +1,95 @@ +import { cn } from "~/lib/utils"; + +const paragraphVariants = { + base: { + text: "font-sans text-base font-normal text-text-dimmed", + spacing: "mb-3", + }, + "base/bright": { + text: "font-sans text-base font-normal text-text-bright", + spacing: "mb-3", + }, + small: { + text: "font-sans text-sm font-normal text-text-dimmed", + spacing: "mb-2", + }, + "small/bright": { + text: "font-sans text-sm font-normal text-text-bright", + spacing: "mb-2", + }, + "extra-small": { + text: "font-sans text-xs font-normal text-text-dimmed", + spacing: "mb-1.5", + }, + "extra-small/bright": { + text: "font-sans text-xs font-normal text-text-bright", + spacing: "mb-1.5", + }, + "extra-small/mono": { + text: "font-mono text-xs font-normal text-text-dimmed", + spacing: "mb-1.5", + }, + "extra-small/bright/mono": { + text: "font-mono text-xs text-text-bright", + spacing: "mb-1.5", + }, + "extra-small/caps": { + text: "font-sans text-xs uppercase tracking-wider font-normal text-text-dimmed", + spacing: "mb-1.5", + }, + "extra-small/bright/caps": { + text: "font-sans text-xs uppercase tracking-wider font-normal text-text-bright", + spacing: "mb-1.5", + }, + "extra-extra-small": { + text: "font-sans text-xxs font-normal text-text-dimmed", + spacing: "mb-1", + }, + "extra-extra-small/bright": { + text: "font-sans text-xxs font-normal text-text-bright", + spacing: "mb-1", + }, + + "extra-extra-small/caps": { + text: "font-sans text-xxs uppercase tracking-wider font-normal text-text-dimmed", + spacing: "mb-1", + }, + "extra-extra-small/bright/caps": { + text: "font-sans text-xxs uppercase tracking-wider font-normal text-text-bright", + spacing: "mb-1", + }, + "extra-extra-small/dimmed/caps": { + text: "font-sans text-xxs uppercase tracking-wider font-normal text-text-dimmed", + spacing: "mb-1", + }, +}; + +export type ParagraphVariant = keyof typeof paragraphVariants; + +type ParagraphProps = { + variant?: ParagraphVariant; + className?: string; + spacing?: boolean; + children: React.ReactNode; +} & React.HTMLAttributes; + +export function Paragraph({ + variant = "base", + className, + spacing = false, + children, + ...props +}: ParagraphProps) { + return ( +

+ {children} +

+ ); +} diff --git a/apps/webapp/app/components/ui/button.tsx b/apps/webapp/app/components/ui/button.tsx new file mode 100644 index 0000000..4235f9f --- /dev/null +++ b/apps/webapp/app/components/ui/button.tsx @@ -0,0 +1,88 @@ +import { Slot } from "@radix-ui/react-slot"; + +import { cva, type VariantProps } from "class-variance-authority"; +import React from "react"; + +import { cn } from "../../lib/utils"; +import { Loader } from "lucide-react"; + +const buttonVariants = cva( + "inline-flex items-center justify-center whitespace-nowrap rounded transition-colors focus-visible:outline-none focus-visible:shadow-none disabled:pointer-events-none disabled:opacity-50 dark:focus-visible:ring-slate-300", + { + variants: { + variant: { + default: "bg-primary text-white shadow hover:bg-primary/90 dark:hover:bg-primary/90", + destructive: "text-red-500 bg-grayAlpha-100 border-none", + outline: "border border-border shadow-sm hover:bg-gray-100 shadow-none", + secondary: "bg-grayAlpha-100 border-none", + ghost: "dark:focus-visible:ring-0 hover:bg-grayAlpha-100", + link: "dark:focus-visible:ring-0", + }, + size: { + default: "h-7 rounded px-2 py-1", + sm: "h-6 rounded-sm px-2 py-2", + xs: "h-5 rounded-sm px-1 py-1", + lg: "h-8 px-4 py-2", + xl: "h-9 rounded px-8", + "2xl": "h-12 rounded px-8", + icon: "h-9 w-9", + }, + full: { + false: "w-auto", + true: "w-full", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + full: false, + }, + } +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + isLoading?: boolean; + asChild?: boolean; + isActive?: boolean; +} + +const Button = React.forwardRef( + ( + { + className, + variant, + size, + full, + asChild = false, + children, + isLoading, + isActive, + disabled, + ...props + }, + ref + ) => { + const Comp = asChild ? Slot : "button"; + + return ( + + {isLoading ? : <>} + {children} + + ); + } +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/apps/webapp/app/components/ui/index.ts b/apps/webapp/app/components/ui/index.ts new file mode 100644 index 0000000..98d55ac --- /dev/null +++ b/apps/webapp/app/components/ui/index.ts @@ -0,0 +1 @@ +export * from "./button"; diff --git a/apps/webapp/app/db.server.ts b/apps/webapp/app/db.server.ts new file mode 100644 index 0000000..ee06a04 --- /dev/null +++ b/apps/webapp/app/db.server.ts @@ -0,0 +1,232 @@ +import { + Prisma, + PrismaClient, + type PrismaClientOrTransaction, + type PrismaReplicaClient, + type PrismaTransactionClient, + type PrismaTransactionOptions, + $transaction as transac, +} from "@echo/database"; +import invariant from "tiny-invariant"; +import { z } from "zod"; +import { env } from "./env.server"; +import { logger } from "./services/logger.service"; +import { isValidDatabaseUrl } from "./utils/db"; +import { singleton } from "./utils/singleton"; + +import { type Span } from "@opentelemetry/api"; + +export type { + PrismaTransactionClient, + PrismaClientOrTransaction, + PrismaTransactionOptions, + PrismaReplicaClient, +}; + +export async function $transaction( + prisma: PrismaClientOrTransaction, + name: string, + fn: (prisma: PrismaTransactionClient, span?: Span) => Promise, + options?: PrismaTransactionOptions +): Promise; +export async function $transaction( + prisma: PrismaClientOrTransaction, + fn: (prisma: PrismaTransactionClient) => Promise, + options?: PrismaTransactionOptions +): Promise; +export async function $transaction( + prisma: PrismaClientOrTransaction, + fnOrName: ((prisma: PrismaTransactionClient) => Promise) | string, + fnOrOptions?: ((prisma: PrismaTransactionClient) => Promise) | PrismaTransactionOptions, + options?: PrismaTransactionOptions +): Promise { + if (typeof fnOrName === "string") { + const fn = fnOrOptions as (prisma: PrismaTransactionClient) => Promise; + + return await transac( + prisma, + (client) => fn(client), + (error) => { + logger.error("prisma.$transaction error", { + code: error.code, + meta: error.meta, + stack: error.stack, + message: error.message, + name: error.name, + }); + }, + options + ); + } else { + return transac( + prisma, + fnOrName, + (error) => { + logger.error("prisma.$transaction error", { + code: error.code, + meta: error.meta, + stack: error.stack, + message: error.message, + name: error.name, + }); + }, + typeof fnOrOptions === "function" ? undefined : fnOrOptions + ); + } +} + +export { Prisma }; + +export const prisma = singleton("prisma", getClient); + +export const $replica: PrismaReplicaClient = singleton( + "replica", + () => getReplicaClient() ?? prisma +); + +function getClient() { + const { DATABASE_URL } = process.env; + invariant(typeof DATABASE_URL === "string", "DATABASE_URL env var not set"); + + const databaseUrl = extendQueryParams(DATABASE_URL, { + connection_limit: env.DATABASE_CONNECTION_LIMIT.toString(), + pool_timeout: env.DATABASE_POOL_TIMEOUT.toString(), + connection_timeout: env.DATABASE_CONNECTION_TIMEOUT.toString(), + }); + + console.log(`🔌 setting up prisma client to ${redactUrlSecrets(databaseUrl)}`); + + const client = new PrismaClient({ + datasources: { + db: { + url: databaseUrl.href, + }, + }, + // @ts-expect-error + log: [ + { + emit: "stdout", + level: "error", + }, + { + emit: "stdout", + level: "info", + }, + { + emit: "stdout", + level: "warn", + }, + ].concat( + process.env.VERBOSE_PRISMA_LOGS === "1" + ? [ + { emit: "event", level: "query" }, + { emit: "stdout", level: "query" }, + ] + : [] + ), + }); + + // connect eagerly + client.$connect(); + + console.log(`🔌 prisma client connected`); + + return client; +} + +function getReplicaClient() { + if (!env.DATABASE_READ_REPLICA_URL) { + console.log(`🔌 No database replica, using the regular client`); + return; + } + + const replicaUrl = extendQueryParams(env.DATABASE_READ_REPLICA_URL, { + connection_limit: env.DATABASE_CONNECTION_LIMIT.toString(), + pool_timeout: env.DATABASE_POOL_TIMEOUT.toString(), + connection_timeout: env.DATABASE_CONNECTION_TIMEOUT.toString(), + }); + + console.log(`🔌 setting up read replica connection to ${redactUrlSecrets(replicaUrl)}`); + + const replicaClient = new PrismaClient({ + datasources: { + db: { + url: replicaUrl.href, + }, + }, + // @ts-expect-error + log: [ + { + emit: "stdout", + level: "error", + }, + { + emit: "stdout", + level: "info", + }, + { + emit: "stdout", + level: "warn", + }, + ].concat( + process.env.VERBOSE_PRISMA_LOGS === "1" + ? [ + { emit: "event", level: "query" }, + { emit: "stdout", level: "query" }, + ] + : [] + ), + }); + + // connect eagerly + replicaClient.$connect(); + + console.log(`🔌 read replica connected`); + + return replicaClient; +} + +function extendQueryParams(hrefOrUrl: string | URL, queryParams: Record) { + const url = new URL(hrefOrUrl); + const query = url.searchParams; + + for (const [key, val] of Object.entries(queryParams)) { + query.set(key, val); + } + + url.search = query.toString(); + + return url; +} + +function redactUrlSecrets(hrefOrUrl: string | URL) { + const url = new URL(hrefOrUrl); + url.password = ""; + return url.href; +} + +export type { PrismaClient } from "@echo/database"; + +export const PrismaErrorSchema = z.object({ + code: z.string(), +}); + +function getDatabaseSchema() { + if (!isValidDatabaseUrl(env.DATABASE_URL)) { + throw new Error("Invalid Database URL"); + } + + const databaseUrl = new URL(env.DATABASE_URL); + const schemaFromSearchParam = databaseUrl.searchParams.get("schema"); + + if (!schemaFromSearchParam) { + console.debug("❗ database schema unspecified, will default to `public` schema"); + return "public"; + } + + return schemaFromSearchParam; +} + +export const DATABASE_SCHEMA = singleton("DATABASE_SCHEMA", getDatabaseSchema); + +export const sqlDatabaseSchema = Prisma.sql([`${DATABASE_SCHEMA}`]); diff --git a/apps/webapp/app/env.server.ts b/apps/webapp/app/env.server.ts index e3441af..0cd9480 100644 --- a/apps/webapp/app/env.server.ts +++ b/apps/webapp/app/env.server.ts @@ -22,8 +22,13 @@ const EnvironmentSchema = z.object({ SESSION_SECRET: z.string(), APP_ENV: z.string().default(process.env.NODE_ENV), + LOGIN_ORIGIN: z.string().default("http://localhost:5173"), APP_ORIGIN: z.string().default("http://localhost:5173"), POSTHOG_PROJECT_KEY: z.string().default(""), + + // google auth + AUTH_GOOGLE_CLIENT_ID: z.string().optional(), + AUTH_GOOGLE_CLIENT_SECRET: z.string().optional(), }); export type Environment = z.infer; diff --git a/apps/webapp/app/hooks/useChanged.ts b/apps/webapp/app/hooks/useChanged.ts new file mode 100644 index 0000000..650a6b3 --- /dev/null +++ b/apps/webapp/app/hooks/useChanged.ts @@ -0,0 +1,26 @@ +import { useEffect, useRef } from "react"; + +/** Call a function when the id of the item changes */ +export function useChanged( + getItem: () => T | undefined, + action: (item: T | undefined) => void, + sendInitialUndefined = true +) { + const previousItemId = useRef(); + const item = getItem(); + + //when the value changes, call the action + useEffect(() => { + if (previousItemId.current !== item?.id) { + action(item); + } + + previousItemId.current = item?.id; + }, [item]); + + //if sendInitialUndefined is true, call the action when the component first renders + useEffect(() => { + if (item !== undefined || sendInitialUndefined === false) return; + action(item); + }, []); +} diff --git a/apps/webapp/app/hooks/usePostHog.ts b/apps/webapp/app/hooks/usePostHog.ts new file mode 100644 index 0000000..d6aa7fc --- /dev/null +++ b/apps/webapp/app/hooks/usePostHog.ts @@ -0,0 +1,49 @@ +import { useLocation } from "@remix-run/react"; +import posthog from "posthog-js"; +import { useEffect, useRef } from "react"; + +import { useOptionalUser, useUserChanged } from "./useUser"; + +export const usePostHog = (apiKey?: string, logging = false, debug = false): void => { + const postHogInitialized = useRef(false); + const location = useLocation(); + const user = useOptionalUser(); + + //start PostHog once + useEffect(() => { + if (apiKey === undefined || apiKey === "") return; + if (postHogInitialized.current === true) return; + if (logging) console.log("Initializing PostHog"); + posthog.init(apiKey, { + api_host: "https://eu.posthog.com", + opt_in_site_apps: true, + debug, + loaded: function (posthog) { + if (logging) console.log("PostHog loaded"); + if (user !== undefined) { + if (logging) console.log("Loaded: Identifying user", user); + posthog.identify(user.id, { email: user.email }); + } + }, + }); + postHogInitialized.current = true; + }, [apiKey, logging, user]); + + useUserChanged((user) => { + if (postHogInitialized.current === false) return; + if (logging) console.log("User changed"); + if (user) { + if (logging) console.log("Identifying user", user); + posthog.identify(user.id, { email: user.email }); + } else { + if (logging) console.log("Resetting user"); + posthog.reset(); + } + }); + + //page view + useEffect(() => { + if (postHogInitialized.current === false) return; + posthog.capture("$pageview"); + }, [location, logging]); +}; diff --git a/apps/webapp/app/hooks/useTypedMatchData.ts b/apps/webapp/app/hooks/useTypedMatchData.ts new file mode 100644 index 0000000..09a25dd --- /dev/null +++ b/apps/webapp/app/hooks/useTypedMatchData.ts @@ -0,0 +1,44 @@ +import { type UIMatch, useMatches } from "@remix-run/react"; +import { + type RemixSerializedType, + type UseDataFunctionReturn, + deserializeRemix, +} from "remix-typedjson"; + +type AppData = any; + +function useTypedDataFromMatches({ + id, + matches, +}: { + id: string; + matches: UIMatch[]; +}): UseDataFunctionReturn | undefined { + const match = matches.find((m) => m.id === id); + return useTypedMatchData(match); +} + +export function useTypedMatchesData({ + id, + matches, +}: { + id: string; + matches?: UIMatch[]; +}): UseDataFunctionReturn | undefined { + if (!matches) { + matches = useMatches(); + } + + return useTypedDataFromMatches({ id, matches }); +} + +export function useTypedMatchData( + match: UIMatch | undefined +): UseDataFunctionReturn | undefined { + if (!match) { + return undefined; + } + return deserializeRemix(match.data as RemixSerializedType) as + | UseDataFunctionReturn + | undefined; +} diff --git a/apps/webapp/app/hooks/useUser.ts b/apps/webapp/app/hooks/useUser.ts new file mode 100644 index 0000000..5fabc08 --- /dev/null +++ b/apps/webapp/app/hooks/useUser.ts @@ -0,0 +1,43 @@ +import { type UIMatch } from "@remix-run/react"; +import type { User } from "~/models/user.server"; +import { type loader } from "~/root"; +import { useChanged } from "./useChanged"; +import { useTypedMatchesData } from "./useTypedMatchData"; + +export function useIsImpersonating(matches?: UIMatch[]) { + const data = useTypedMatchesData({ + id: "routes/_app.workspace.$workspaceSlug", + matches, + }); + return data?.isImpersonating === true; +} + +export function useOptionalUser(matches?: UIMatch[]): User | undefined { + const routeMatch = useTypedMatchesData({ + id: "root", + matches, + }); + + return routeMatch?.user ?? undefined; +} + +export function useUser(matches?: UIMatch[]): User { + const maybeUser = useOptionalUser(matches); + if (!maybeUser) { + throw new Error( + "No user found in root loader, but user is required by useUser. If user is optional, try useOptionalUser instead." + ); + } + return maybeUser; +} + +export function useUserChanged(callback: (user: User | undefined) => void) { + useChanged(useOptionalUser, callback); +} + +export function useHasAdminAccess(matches?: UIMatch[]): boolean { + const user = useOptionalUser(matches); + const isImpersonating = useIsImpersonating(matches); + + return Boolean(user?.admin) || isImpersonating; +} diff --git a/apps/webapp/app/models/message.server.ts b/apps/webapp/app/models/message.server.ts index cb4f1de..124406b 100644 --- a/apps/webapp/app/models/message.server.ts +++ b/apps/webapp/app/models/message.server.ts @@ -1,6 +1,11 @@ -import { json, type Session , createCookieSessionStorage } from "@remix-run/node"; +import { + json, + type Session, + createCookieSessionStorage, +} from "@remix-run/node"; import { redirect } from "remix-typedjson"; import { env } from "~/env.server"; +import { createThemeSessionResolver } from "remix-themes"; export type ToastMessage = { message: string; @@ -29,7 +34,7 @@ export const { commitSession, getSession } = createCookieSessionStorage({ export function setSuccessMessage( session: Session, message: string, - options?: ToastMessageOptions + options?: ToastMessageOptions, ) { session.flash("toastMessage", { message, @@ -40,7 +45,11 @@ export function setSuccessMessage( } as ToastMessage); } -export function setErrorMessage(session: Session, message: string, options?: ToastMessageOptions) { +export function setErrorMessage( + session: Session, + message: string, + options?: ToastMessageOptions, +) { session.flash("toastMessage", { message, type: "error", @@ -53,7 +62,7 @@ export function setErrorMessage(session: Session, message: string, options?: Toa export async function setRequestErrorMessage( request: Request, message: string, - options?: ToastMessageOptions + options?: ToastMessageOptions, ) { const session = await getSession(request.headers.get("cookie")); @@ -65,7 +74,7 @@ export async function setRequestErrorMessage( export async function setRequestSuccessMessage( request: Request, message: string, - options?: ToastMessageOptions + options?: ToastMessageOptions, ) { const session = await getSession(request.headers.get("cookie")); @@ -86,7 +95,7 @@ export async function jsonWithSuccessMessage( data: any, request: Request, message: string, - options?: ToastMessageOptions + options?: ToastMessageOptions, ) { const session = await getSession(request.headers.get("cookie")); @@ -105,7 +114,7 @@ export async function jsonWithErrorMessage( data: any, request: Request, message: string, - options?: ToastMessageOptions + options?: ToastMessageOptions, ) { const session = await getSession(request.headers.get("cookie")); @@ -124,7 +133,7 @@ export async function redirectWithSuccessMessage( path: string, request: Request, message: string, - options?: ToastMessageOptions + options?: ToastMessageOptions, ) { const session = await getSession(request.headers.get("cookie")); @@ -143,7 +152,7 @@ export async function redirectWithErrorMessage( path: string, request: Request, message: string, - options?: ToastMessageOptions + options?: ToastMessageOptions, ) { const session = await getSession(request.headers.get("cookie")); @@ -161,7 +170,7 @@ export async function redirectWithErrorMessage( export async function redirectBackWithErrorMessage( request: Request, message: string, - options?: ToastMessageOptions + options?: ToastMessageOptions, ) { const url = new URL(request.url); return redirectWithErrorMessage(url.pathname, request, message, options); @@ -170,7 +179,7 @@ export async function redirectBackWithErrorMessage( export async function redirectBackWithSuccessMessage( request: Request, message: string, - options?: ToastMessageOptions + options?: ToastMessageOptions, ) { const url = new URL(request.url); return redirectWithSuccessMessage(url.pathname, request, message, options); diff --git a/apps/webapp/app/models/user.server.ts b/apps/webapp/app/models/user.server.ts new file mode 100644 index 0000000..2da0727 --- /dev/null +++ b/apps/webapp/app/models/user.server.ts @@ -0,0 +1,155 @@ +import type { Prisma, User } from "@echo/database"; +import type { GoogleProfile } from "remix-auth-google"; +import { prisma } from "~/db.server"; +export type { User } from "@echo/database"; + +type FindOrCreateGoogle = { + authenticationMethod: "GOOGLE"; + email: User["email"]; + authenticationProfile: GoogleProfile; + authenticationExtraParams: Record; +}; + +type FindOrCreateUser = FindOrCreateGoogle; + +type LoggedInUser = { + user: User; + isNewUser: boolean; +}; + +export async function findOrCreateUser(input: FindOrCreateUser): Promise { + return findOrCreateGoogleUser(input); +} + +export async function findOrCreateGoogleUser({ + email, + authenticationProfile, + authenticationExtraParams, +}: FindOrCreateGoogle): Promise { + const name = authenticationProfile._json.name; + let avatarUrl: string | undefined = undefined; + if (authenticationProfile.photos[0]) { + avatarUrl = authenticationProfile.photos[0].value; + } + const displayName = authenticationProfile.displayName; + const authProfile = authenticationProfile + ? (authenticationProfile as unknown as Prisma.JsonObject) + : undefined; + const authExtraParams = authenticationExtraParams + ? (authenticationExtraParams as unknown as Prisma.JsonObject) + : undefined; + + const authIdentifier = `github:${authenticationProfile.id}`; + + const existingUser = await prisma.user.findUnique({ + where: { + authIdentifier, + }, + }); + + const existingEmailUser = await prisma.user.findUnique({ + where: { + email, + }, + }); + + if (existingEmailUser && !existingUser) { + const user = await prisma.user.update({ + where: { + email, + }, + data: { + authenticationProfile: authProfile, + authenticationExtraParams: authExtraParams, + avatarUrl, + authIdentifier, + }, + }); + + return { + user, + isNewUser: false, + }; + } + + if (existingEmailUser && existingUser) { + const user = await prisma.user.update({ + where: { + id: existingUser.id, + }, + data: {}, + }); + + return { + user, + isNewUser: false, + }; + } + + const user = await prisma.user.upsert({ + where: { + authIdentifier, + }, + update: {}, + create: { + authenticationProfile: authProfile, + authenticationExtraParams: authExtraParams, + name, + avatarUrl, + displayName, + authIdentifier, + email, + authenticationMethod: "GOOGLE", + }, + }); + + return { + user, + isNewUser: !existingUser, + }; +} + +export async function getUserById(id: User["id"]) { + const user = await prisma.user.findUnique({ where: { id } }); + + if (!user) { + return null; + } + + return { + ...user, + }; +} + +export async function getUserByEmail(email: User["email"]) { + return prisma.user.findUnique({ where: { email } }); +} + +export function updateUser({ + id, + name, + email, + marketingEmails, + referralSource, +}: Pick & { + marketingEmails?: boolean; + referralSource?: string; +}) { + return prisma.user.update({ + where: { id }, + data: { name, email, marketingEmails, referralSource, confirmedBasicDetails: true }, + }); +} + +export async function grantUserCloudAccess({ id, inviteCode }: { id: string; inviteCode: string }) { + return prisma.user.update({ + where: { id }, + data: { + InvitationCode: { + connect: { + code: inviteCode, + }, + }, + }, + }); +} diff --git a/apps/webapp/app/root.tsx b/apps/webapp/app/root.tsx index a369c51..8f8b713 100644 --- a/apps/webapp/app/root.tsx +++ b/apps/webapp/app/root.tsx @@ -1,47 +1,73 @@ -import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react"; -import type { LinksFunction, LoaderFunctionArgs, MetaFunction } from "@remix-run/node"; -import { type UseDataFunctionReturn, typedjson, useTypedLoaderData } from "remix-typedjson"; +import { + Links, + LiveReload, + Meta, + Outlet, + Scripts, + ScrollRestoration, + useLoaderData, +} from "@remix-run/react"; +import type { + LinksFunction, + LoaderFunctionArgs, + MetaFunction, +} from "@remix-run/node"; +import { + type UseDataFunctionReturn, + typedjson, + useTypedLoaderData, +} from "remix-typedjson"; + +import styles from "./tailwind.css?url"; -import tailwindStylesheetUrl from "~/tailwind.css"; import { appEnvTitleTag } from "./utils"; -import { commitSession, getSession, type ToastMessage } from "./models/message.server"; +import { + commitSession, + getSession, + type ToastMessage, +} from "./models/message.server"; import { env } from "./env.server"; +import { getUser } from "./services/session.server"; +import { usePostHog } from "./hooks/usePostHog"; +import { + AppContainer, + MainCenteredContainer, +} from "./components/layout/AppLayout"; +import { RouteErrorDisplay } from "./components/ErrorDisplay"; +import { themeSessionResolver } from "./services/sessionStorage.server"; +import { + PreventFlashOnWrongTheme, + ThemeProvider, + useTheme, +} from "remix-themes"; +import clsx from "clsx"; -export const links: LinksFunction = () => [ - { rel: "preconnect", href: "https://fonts.googleapis.com" }, - { - rel: "preconnect", - href: "https://fonts.gstatic.com", - crossOrigin: "anonymous", - }, - { - rel: "stylesheet", - href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap", - }, - { rel: "stylesheet", href: tailwindStylesheetUrl }, -]; +export const links: LinksFunction = () => [{ rel: "stylesheet", href: styles }]; export const loader = async ({ request }: LoaderFunctionArgs) => { const session = await getSession(request.headers.get("cookie")); const toastMessage = session.get("toastMessage") as ToastMessage; + const { getTheme } = await themeSessionResolver(request); + const posthogProjectKey = env.POSTHOG_PROJECT_KEY; return typedjson( { - user: await getUser(request), toastMessage, + theme: getTheme(), posthogProjectKey, appEnv: env.APP_ENV, appOrigin: env.APP_ORIGIN, }, - { headers: { "Set-Cookie": await commitSession(session) } } + { headers: { "Set-Cookie": await commitSession(session) } }, ); }; export const meta: MetaFunction = ({ data }) => { const typedData = data as UseDataFunctionReturn; + return [ - { title: `Echo${appEnvTitleTag(typedData.appEnv)}` }, + { title: `Echo${typedData && appEnvTitleTag(typedData.appEnv)}` }, { name: "viewport", content: "width=1024, initial-scale=1", @@ -49,31 +75,70 @@ export const meta: MetaFunction = ({ data }) => { { name: "robots", content: - typeof window === "undefined" || window.location.hostname !== "echo.mysigma.ai" + typeof window === "undefined" || + window.location.hostname !== "echo.mysigma.ai" ? "noindex, nofollow" : "index, follow", }, ]; }; -export function Layout({ children }: { children: React.ReactNode }) { +export function ErrorBoundary() { return ( - - - - - - - - - {children} - - - - + <> + + + + + + + + + + + + + + + + + ); } -export default function App() { - return ; +function App() { + const { posthogProjectKey } = useTypedLoaderData(); + usePostHog(posthogProjectKey); + const [theme] = useTheme(); + + return ( + <> + + + + + + + + + + + + + + + + ); +} + +// Wrap your app with ThemeProvider. +// `specifiedTheme` is the stored theme in the session storage. +// `themeAction` is the action name that's used to change the theme in the session storage. +export default function AppWithProviders() { + const data = useLoaderData(); + return ( + + + + ); } diff --git a/apps/webapp/app/routes/action.set-theme.ts b/apps/webapp/app/routes/action.set-theme.ts new file mode 100644 index 0000000..f81e5db --- /dev/null +++ b/apps/webapp/app/routes/action.set-theme.ts @@ -0,0 +1,4 @@ +import { createThemeAction } from "remix-themes"; +import { themeSessionResolver } from "~/services/sessionStorage.server"; + +export const action = createThemeAction(themeSessionResolver); diff --git a/apps/webapp/app/routes/login.tsx b/apps/webapp/app/routes/login.tsx new file mode 100644 index 0000000..511bd17 --- /dev/null +++ b/apps/webapp/app/routes/login.tsx @@ -0,0 +1,31 @@ +import { type LoaderFunctionArgs } from "@remix-run/node"; +import { useNavigation } from "@remix-run/react"; +import { typedjson } from "remix-typedjson"; +import { LoginPageLayout } from "~/components/layout/LoginPageLayout"; +import { authenticator } from "~/services/auth.server"; +import { + commitSession, + getUserSession, +} from "~/services/sessionStorage.server"; + +export async function loader({ request }: LoaderFunctionArgs) { + await authenticator.isAuthenticated(request, { + successRedirect: "/", + }); + + const session = await getUserSession(request); + + return typedjson({ + headers: { "Set-Cookie": await commitSession(session) }, + }); +} + +export default function LoginPage() { + const navigate = useNavigation(); + + return ( + +

Lohin

+
+ ); +} diff --git a/apps/webapp/app/services/apiRateLimit.server.ts b/apps/webapp/app/services/apiRateLimit.server.ts new file mode 100644 index 0000000..5dca750 --- /dev/null +++ b/apps/webapp/app/services/apiRateLimit.server.ts @@ -0,0 +1,64 @@ +import { env } from "~/env.server"; +import { authenticateAuthorizationHeader } from "./apiAuth.server"; +import { authorizationRateLimitMiddleware } from "./authorizationRateLimitMiddleware.server"; +import { Duration } from "./rateLimiter.server"; + +export const apiRateLimiter = authorizationRateLimitMiddleware({ + redis: { + port: env.RATE_LIMIT_REDIS_PORT, + host: env.RATE_LIMIT_REDIS_HOST, + username: env.RATE_LIMIT_REDIS_USERNAME, + password: env.RATE_LIMIT_REDIS_PASSWORD, + tlsDisabled: env.RATE_LIMIT_REDIS_TLS_DISABLED === "true", + clusterMode: env.RATE_LIMIT_REDIS_CLUSTER_MODE_ENABLED === "1", + }, + keyPrefix: "api", + defaultLimiter: { + type: "tokenBucket", + refillRate: env.API_RATE_LIMIT_REFILL_RATE, + interval: env.API_RATE_LIMIT_REFILL_INTERVAL as Duration, + maxTokens: env.API_RATE_LIMIT_MAX, + }, + limiterCache: { + fresh: 60_000 * 10, // Data is fresh for 10 minutes + stale: 60_000 * 20, // Date is stale after 20 minutes + }, + limiterConfigOverride: async (authorizationValue) => { + const authenticatedEnv = await authenticateAuthorizationHeader(authorizationValue, { + allowPublicKey: true, + allowJWT: true, + }); + + if (!authenticatedEnv || !authenticatedEnv.ok) { + return; + } + + if (authenticatedEnv.type === "PUBLIC_JWT") { + return { + type: "fixedWindow", + window: env.API_RATE_LIMIT_JWT_WINDOW, + tokens: env.API_RATE_LIMIT_JWT_TOKENS, + }; + } else { + return authenticatedEnv.environment.organization.apiRateLimiterConfig; + } + }, + pathMatchers: [/^\/api/], + // Allow /api/v1/tasks/:id/callback/:secret + pathWhiteList: [ + "/api/internal/stripe_webhooks", + "/api/v1/authorization-code", + "/api/v1/token", + "/api/v1/usage/ingest", + "/api/v1/timezones", + "/api/v1/usage/ingest", + "/api/v1/auth/jwt/claims", + ], + log: { + rejections: env.API_RATE_LIMIT_REJECTION_LOGS_ENABLED === "1", + requests: env.API_RATE_LIMIT_REQUEST_LOGS_ENABLED === "1", + limiter: env.API_RATE_LIMIT_LIMITER_LOGS_ENABLED === "1", + }, +}); + +export type RateLimitMiddleware = ReturnType; diff --git a/apps/webapp/app/services/auth.server.ts b/apps/webapp/app/services/auth.server.ts new file mode 100644 index 0000000..035da44 --- /dev/null +++ b/apps/webapp/app/services/auth.server.ts @@ -0,0 +1,20 @@ +import { Authenticator } from "remix-auth"; +import type { AuthUser } from "./authUser"; + +import { addGoogleStrategy } from "./googleAuth.server"; +import { sessionStorage } from "./sessionStorage.server"; +import { env } from "~/env.server"; + +// Create an instance of the authenticator, pass a generic with what +// strategies will return and will store in the session +const authenticator = new Authenticator(sessionStorage); + +const isGoogleAuthSupported = + typeof env.AUTH_GOOGLE_CLIENT_ID === "string" && + typeof env.AUTH_GOOGLE_CLIENT_SECRET === "string"; + +if (env.AUTH_GOOGLE_CLIENT_ID && env.AUTH_GOOGLE_CLIENT_SECRET) { + addGoogleStrategy(authenticator, env.AUTH_GOOGLE_CLIENT_ID, env.AUTH_GOOGLE_CLIENT_SECRET); +} + +export { authenticator, isGoogleAuthSupported }; diff --git a/apps/webapp/app/services/authUser.ts b/apps/webapp/app/services/authUser.ts new file mode 100644 index 0000000..4c1ce6a --- /dev/null +++ b/apps/webapp/app/services/authUser.ts @@ -0,0 +1,3 @@ +export type AuthUser = { + userId: string; +}; diff --git a/apps/webapp/app/services/googleAuth.server.ts b/apps/webapp/app/services/googleAuth.server.ts new file mode 100644 index 0000000..bf38643 --- /dev/null +++ b/apps/webapp/app/services/googleAuth.server.ts @@ -0,0 +1,54 @@ +import type { Authenticator } from "remix-auth"; +import { GoogleStrategy } from "remix-auth-google"; +import { env } from "~/env.server"; +import { findOrCreateUser } from "~/models/user.server"; +import type { AuthUser } from "./authUser"; +import { postAuthentication } from "./postAuth.server"; +import { logger } from "./logger.service"; + +export function addGoogleStrategy( + authenticator: Authenticator, + clientID: string, + clientSecret: string +) { + const googleStrategy = new GoogleStrategy( + { + clientID, + clientSecret, + callbackURL: `${env.LOGIN_ORIGIN}/auth/google/callback`, + }, + async ({ extraParams, profile }) => { + const emails = profile.emails; + + if (!emails) { + throw new Error("Google login requires an email address"); + } + + try { + logger.debug("Google login", { + emails, + profile, + extraParams, + }); + + const { user, isNewUser } = await findOrCreateUser({ + email: emails[0].value, + authenticationMethod: "GOOGLE", + authenticationProfile: profile, + authenticationExtraParams: extraParams, + }); + + await postAuthentication({ user, isNewUser, loginMethod: "GOOGLE" }); + + return { + userId: user.id, + }; + } catch (error) { + console.error(error); + throw error; + } + } + ); + + authenticator.use(googleStrategy); +} diff --git a/apps/webapp/app/services/httpAsyncStorage.server.ts b/apps/webapp/app/services/httpAsyncStorage.server.ts new file mode 100644 index 0000000..7b709e4 --- /dev/null +++ b/apps/webapp/app/services/httpAsyncStorage.server.ts @@ -0,0 +1,20 @@ +import { AsyncLocalStorage } from "node:async_hooks"; + +export type HttpLocalStorage = { + requestId: string; + path: string; + host: string; + method: string; +}; + +const httpLocalStorage = new AsyncLocalStorage(); + +export type RunWithHttpContextFunction = (context: HttpLocalStorage, fn: () => T) => T; + +export function runWithHttpContext(context: HttpLocalStorage, fn: () => T): T { + return httpLocalStorage.run(context, fn); +} + +export function getHttpContext(): HttpLocalStorage | undefined { + return httpLocalStorage.getStore(); +} diff --git a/apps/webapp/app/services/impersonation.server.ts b/apps/webapp/app/services/impersonation.server.ts new file mode 100644 index 0000000..78c7715 --- /dev/null +++ b/apps/webapp/app/services/impersonation.server.ts @@ -0,0 +1,44 @@ +import { createCookieSessionStorage, type Session } from "@remix-run/node"; +import { env } from "~/env.server"; + +export const impersonationSessionStorage = createCookieSessionStorage({ + cookie: { + name: "__impersonate", // use any name you want here + sameSite: "lax", // this helps with CSRF + path: "/", // remember to add this so the cookie will work in all routes + httpOnly: true, // for security reasons, make this cookie http only + secrets: [env.SESSION_SECRET], + secure: env.NODE_ENV === "production", // enable this in prod only + maxAge: 60 * 60 * 24, // 1 day + }, +}); + +export function getImpersonationSession(request: Request) { + return impersonationSessionStorage.getSession(request.headers.get("Cookie")); +} + +export function commitImpersonationSession(session: Session) { + return impersonationSessionStorage.commitSession(session); +} + +export async function getImpersonationId(request: Request) { + const session = await getImpersonationSession(request); + + return session.get("impersonatedUserId") as string | undefined; +} + +export async function setImpersonationId(userId: string, request: Request) { + const session = await getImpersonationSession(request); + + session.set("impersonatedUserId", userId); + + return session; +} + +export async function clearImpersonationId(request: Request) { + const session = await getImpersonationSession(request); + + session.unset("impersonatedUserId"); + + return session; +} diff --git a/apps/webapp/app/services/logger.service.ts b/apps/webapp/app/services/logger.service.ts new file mode 100644 index 0000000..72d6faa --- /dev/null +++ b/apps/webapp/app/services/logger.service.ts @@ -0,0 +1,296 @@ +import { sensitiveDataReplacer } from "./sensitiveDataReplacer"; +import { AsyncLocalStorage } from "async_hooks"; +import { getHttpContext } from "./httpAsyncStorage.server"; + +import { env } from "node:process"; +import { Buffer } from "node:buffer"; +import { trace, context } from "@opentelemetry/api"; + +export type LogLevel = "log" | "error" | "warn" | "info" | "debug"; + +const logLevels: Array = ["log", "error", "warn", "info", "debug"]; + +export class Logger { + #name: string; + readonly #level: number; + #filteredKeys: string[] = []; + #jsonReplacer?: (key: string, value: unknown) => unknown; + #additionalFields: () => Record; + + constructor( + name: string, + level: LogLevel = "info", + filteredKeys: string[] = [], + jsonReplacer?: (key: string, value: unknown) => unknown, + additionalFields?: () => Record + ) { + this.#name = name; + this.#level = logLevels.indexOf((env.APP_LOG_LEVEL ?? level) as LogLevel); + this.#filteredKeys = filteredKeys; + this.#jsonReplacer = createReplacer(jsonReplacer); + this.#additionalFields = additionalFields ?? (() => ({})); + } + + child(fields: Record) { + return new Logger( + this.#name, + logLevels[this.#level], + this.#filteredKeys, + this.#jsonReplacer, + () => ({ ...this.#additionalFields(), ...fields }) + ); + } + + // Return a new Logger instance with the same name and a new log level + // but filter out the keys from the log messages (at any level) + filter(...keys: string[]) { + return new Logger(this.#name, logLevels[this.#level], keys, this.#jsonReplacer); + } + + static satisfiesLogLevel(logLevel: LogLevel, setLevel: LogLevel) { + return logLevels.indexOf(logLevel) <= logLevels.indexOf(setLevel); + } + + log(message: string, ...args: Array | undefined>) { + if (this.#level < 0) return; + + this.#structuredLog(console.log, message, "log", ...args); + } + + error(message: string, ...args: Array | undefined>) { + if (this.#level < 1) return; + + this.#structuredLog(console.error, message, "error", ...args); + } + + warn(message: string, ...args: Array | undefined>) { + if (this.#level < 2) return; + + this.#structuredLog(console.warn, message, "warn", ...args); + } + + info(message: string, ...args: Array | undefined>) { + if (this.#level < 3) return; + + this.#structuredLog(console.info, message, "info", ...args); + } + + debug(message: string, ...args: Array | undefined>) { + if (this.#level < 4) return; + + this.#structuredLog(console.debug, message, "debug", ...args); + } + + #structuredLog( + loggerFunction: (message: string, ...args: any[]) => void, + message: string, + level: string, + ...args: Array | undefined> + ) { + // Get the current context from trace if it exists + const currentSpan = trace.getSpan(context.active()); + + const structuredError = extractStructuredErrorFromArgs(...args); + const structuredMessage = extractStructuredMessageFromArgs(...args); + + const structuredLog = { + ...structureArgs(safeJsonClone(args) as Record[], this.#filteredKeys), + ...this.#additionalFields(), + ...(structuredError ? { error: structuredError } : {}), + timestamp: new Date(), + name: this.#name, + message, + ...(structuredMessage ? { $message: structuredMessage } : {}), + level, + traceId: + currentSpan && currentSpan.isRecording() ? currentSpan?.spanContext().traceId : undefined, + parentSpanId: + currentSpan && currentSpan.isRecording() ? currentSpan?.spanContext().spanId : undefined, + }; + + // If the span is not recording, and it's a debug log, mark it so we can filter it out when we forward it + if (currentSpan && !currentSpan.isRecording() && level === "debug") { + structuredLog.skipForwarding = true; + } + + loggerFunction(JSON.stringify(structuredLog, this.#jsonReplacer)); + } +} + +// Detect if args is an error object +// Or if args contains an error object at the "error" key +// In both cases, return the error object as a structured error +function extractStructuredErrorFromArgs(...args: Array | undefined>) { + const error = args.find((arg) => arg instanceof Error) as Error | undefined; + + if (error) { + return { + message: error.message, + stack: error.stack, + name: error.name, + }; + } + + const structuredError = args.find((arg) => arg?.error); + + if (structuredError && structuredError.error instanceof Error) { + return { + message: structuredError.error.message, + stack: structuredError.error.stack, + name: structuredError.error.name, + }; + } + + return; +} + +function extractStructuredMessageFromArgs(...args: Array | undefined>) { + // Check to see if there is a `message` key in the args, and if so, return it + const structuredMessage = args.find((arg) => arg?.message); + + if (structuredMessage) { + return structuredMessage.message; + } + + return; +} + +function createReplacer(replacer?: (key: string, value: unknown) => unknown) { + return (key: string, value: unknown) => { + if (typeof value === "bigint") { + return value.toString(); + } + + if (replacer) { + return replacer(key, value); + } + + return value; + }; +} + +// Replacer function for JSON.stringify that converts BigInts to strings +function bigIntReplacer(_key: string, value: unknown) { + if (typeof value === "bigint") { + return value.toString(); + } + + return value; +} + +function safeJsonClone(obj: unknown) { + try { + return JSON.parse(JSON.stringify(obj, bigIntReplacer)); + } catch (e) { + return; + } +} + +// If args is has a single item that is an object, return that object +function structureArgs(args: Array>, filteredKeys: string[] = []) { + if (!args) { + return; + } + + if (args.length === 0) { + return; + } + + if (args.length === 1 && typeof args[0] === "object") { + return filterKeys(JSON.parse(JSON.stringify(args[0], bigIntReplacer)), filteredKeys); + } + + return args; +} + +// Recursively filter out keys from an object, including nested objects, and arrays +function filterKeys(obj: unknown, keys: string[]): any { + if (typeof obj !== "object" || obj === null) { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map((item) => filterKeys(item, keys)); + } + + const filteredObj: any = {}; + + for (const [key, value] of Object.entries(obj)) { + if (keys.includes(key)) { + if (value) { + filteredObj[key] = `[filtered ${prettyPrintBytes(value)}]`; + } else { + filteredObj[key] = value; + } + continue; + } + + filteredObj[key] = filterKeys(value, keys); + } + + return filteredObj; +} + +function prettyPrintBytes(value: unknown): string { + if (env.NODE_ENV === "production") { + return "skipped size"; + } + + const sizeInBytes = getSizeInBytes(value); + + if (sizeInBytes < 1024) { + return `${sizeInBytes} bytes`; + } + + if (sizeInBytes < 1024 * 1024) { + return `${(sizeInBytes / 1024).toFixed(2)} KB`; + } + + if (sizeInBytes < 1024 * 1024 * 1024) { + return `${(sizeInBytes / (1024 * 1024)).toFixed(2)} MB`; + } + + return `${(sizeInBytes / (1024 * 1024 * 1024)).toFixed(2)} GB`; +} + +function getSizeInBytes(value: unknown) { + const jsonString = JSON.stringify(value); + + return Buffer.byteLength(jsonString, "utf8"); +} + +const currentFieldsStore = new AsyncLocalStorage>(); + +export const logger = new Logger( + "webapp", + (process.env.APP_LOG_LEVEL ?? "debug") as LogLevel, + ["examples", "output", "connectionString", "payload"], + sensitiveDataReplacer, + () => { + const fields = currentFieldsStore.getStore(); + const httpContext = getHttpContext(); + return { ...fields, http: httpContext }; + } +); + +export const workerLogger = new Logger( + "worker", + (process.env.APP_LOG_LEVEL ?? "debug") as LogLevel, + ["examples", "output", "connectionString"], + sensitiveDataReplacer, + () => { + const fields = currentFieldsStore.getStore(); + return fields ? { ...fields } : {}; + } +); + +export const socketLogger = new Logger( + "socket", + (process.env.APP_LOG_LEVEL ?? "debug") as LogLevel, + [], + sensitiveDataReplacer, + () => { + const fields = currentFieldsStore.getStore(); + return fields ? { ...fields } : {}; + } +); diff --git a/apps/webapp/app/services/postAuth.server.ts b/apps/webapp/app/services/postAuth.server.ts new file mode 100644 index 0000000..72c3dcf --- /dev/null +++ b/apps/webapp/app/services/postAuth.server.ts @@ -0,0 +1,14 @@ +import type { User } from "~/models/user.server"; +import { singleton } from "~/utils/singleton"; + +export async function postAuthentication({ + user, + loginMethod, + isNewUser, +}: { + user: User; + loginMethod: User["authenticationMethod"]; + isNewUser: boolean; +}) { + console.log(user); +} diff --git a/apps/webapp/app/services/sensitiveDataReplacer.ts b/apps/webapp/app/services/sensitiveDataReplacer.ts new file mode 100644 index 0000000..a66757c --- /dev/null +++ b/apps/webapp/app/services/sensitiveDataReplacer.ts @@ -0,0 +1,33 @@ +import { z } from "zod"; + +export const RedactStringSchema = z.object({ + __redactedString: z.literal(true), + strings: z.array(z.string()), + interpolations: z.array(z.string()), +}); + +export type RedactString = z.infer; + +// Replaces redacted strings with "******". +// For example, this object: {"Authorization":{"__redactedString":true,"strings":["Bearer ",""],"interpolations":["sk-1234"]}} +// Would get stringified like so: {"Authorization": "Bearer ******"} +export function sensitiveDataReplacer(key: string, value: any): any { + if (typeof value === "object" && value !== null && value.__redactedString === true) { + return redactString(value); + } + + return value; +} + +function redactString(value: RedactString) { + let result = ""; + + for (let i = 0; i < value.strings.length; i++) { + result += value.strings[i]; + if (i < value.interpolations.length) { + result += "********"; + } + } + + return result; +} diff --git a/apps/webapp/app/services/session.server.ts b/apps/webapp/app/services/session.server.ts index e69de29..b09e827 100644 --- a/apps/webapp/app/services/session.server.ts +++ b/apps/webapp/app/services/session.server.ts @@ -0,0 +1,27 @@ +import { redirect } from "@remix-run/node"; +import { getUserById } from "~/models/user.server"; +import { authenticator } from "./auth.server"; +import { getImpersonationId } from "./impersonation.server"; + +export async function getUserId(request: Request): Promise { + const impersonatedUserId = await getImpersonationId(request); + + if (impersonatedUserId) return impersonatedUserId; + + let authUser = await authenticator.isAuthenticated(request); + return authUser?.userId; +} + +export async function getUser(request: Request) { + const userId = await getUserId(request); + if (userId === undefined) return null; + + const user = await getUserById(userId); + if (user) return user; + + throw await logout(request); +} + +export async function logout(request: Request) { + return redirect("/logout"); +} diff --git a/apps/webapp/app/services/sessionStorage.server.ts b/apps/webapp/app/services/sessionStorage.server.ts new file mode 100644 index 0000000..1ba119b --- /dev/null +++ b/apps/webapp/app/services/sessionStorage.server.ts @@ -0,0 +1,35 @@ +import { createCookieSessionStorage } from "@remix-run/node"; +import { createThemeSessionResolver } from "remix-themes"; +import { env } from "~/env.server"; + +export const sessionStorage = createCookieSessionStorage({ + cookie: { + name: "__session", // use any name you want here + sameSite: "lax", // this helps with CSRF + path: "/", // remember to add this so the cookie will work in all routes + httpOnly: true, // for security reasons, make this cookie http only + secrets: [env.SESSION_SECRET], + secure: env.NODE_ENV === "production", // enable this in prod only + maxAge: 60 * 60 * 24 * 365, // 7 days + }, +}); + +export const themeStorage = createCookieSessionStorage({ + cookie: { + name: "__theme", + sameSite: "lax", + path: "/", + httpOnly: true, + secrets: [env.SESSION_SECRET], + secure: env.NODE_ENV === "production", + maxAge: 60 * 60 * 24 * 365, // 1 year + }, +}); + +export const themeSessionResolver = createThemeSessionResolver(sessionStorage); + +export function getUserSession(request: Request) { + return sessionStorage.getSession(request.headers.get("Cookie")); +} + +export const { getSession, commitSession, destroySession } = sessionStorage; diff --git a/apps/webapp/app/tailwind.css b/apps/webapp/app/tailwind.css index 5b4e8b7..605af84 100644 --- a/apps/webapp/app/tailwind.css +++ b/apps/webapp/app/tailwind.css @@ -1,85 +1,66 @@ @import url("non.geist"); @import url("non.geist/mono"); -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss"; -html, -body { - @apply bg-background; - @media (prefers-color-scheme: dark) { - color-scheme: dark; - } +:root { + --background: oklch(91.28% 0 0); + --background-2: oklch(95.21% 0 0); + --background-3: oklch(100% 0 0); + --foreground: oklch(0% 0 0); + --popover: oklch(93.05% 0 0); + --popover-foreground: oklch(0% 0 0); + --primary: oklch(54% 0.1789 271); + --primary-foreground: oklch(100% 0 0); + --secondary: 210 40% 96.1%; + --secondary-foreground: oklch(0% 0 0); + --muted: oklch(0% 0 0 / 19.22%); + --muted-foreground: oklch(49.26% 0 0); + --accent: oklch(100% 0 0); + --accent-foreground: oklch(0% 0 0); + --destructive: oklch(61.34% 0.162 23.58); + --destructive-foreground: oklch(100% 0 0); + --warning: oklch(70.43% 0.14390424619548714 87.9634104985311); + --warning-foreground: oklch(100% 0 0); + --success: oklch(64.93% 0.107 154.24); + --success-foreground: oklch(100% 0 0); + --border: oklch(0% 0 0 / 19.22%); + --border-dark: oklch(0% 0 0 / 39.22%); + --input: oklch(0% 0 0 / 6.27%); + --ring: 221.2 83.2% 53.3%; + --radius: 8px; } - - -@layer base { - :root { - --background: 91.28% 0 0; - --background-2: 95.21% 0 0; - --background-3: 100% 0 0; - --foreground: 0% 0 0; - --popover: 93.05% 0 0; - --popover-foreground: 0% 0 0; - --primary: 54% 0.1789 271; - --primary-foreground: 100% 0 0; - --secondary: 210 40% 96.1%; - --secondary-foreground: 0% 0 0; - --muted: 0% 0 0 / 19.22%; - --muted-foreground: 49.26% 0 0; - --accent: 100% 0 0; - --accent-foreground: 0% 0 0; - --destructive: 61.34% 0.162 23.58; - --destructive-foreground: 100% 0 0; - --warning: 70.43% 0.14390424619548714 87.9634104985311; - --warning-foreground: 100% 0 0; - --success: 64.93% 0.107 154.24; - --success-foreground: 100% 0 0; - --border: 0% 0 0 / 19.22%; - --border-dark: 0% 0 0 / 39.22%; - --input: 0% 0 0 / 6.27%; - --ring: 221.2 83.2% 53.3%; - --radius: 8px; - } - - .dark { - --background: 21.34% 0 0; - --background-2: 25.2% 0 0; - --background-3: 28.5% 0 0; - --foreground: 92.8% 0 0; - --popover: 28.5% 0 0; - --popover-foreground: 92.8% 0 0; - --primary: 54% 0.1789 271; - --primary-foreground: 92.8% 0 0; - --secondary: 210 40% 96.1%; - --secondary-foreground: 92.8% 0 0; - --muted: 100% 0 0 / 13.33%; - --muted-foreground: 76.99% 0 0; - --accent: 95.81% 0 0; - --accent-foreground: 0% 0 0; - --warning: 70.43% 0.14390424619548714 87.9634104985311; - --warning-foreground: 100% 0 0; - --destructive: 61.34% 0.162 23.58; - --destructive-foreground: 100% 0 0; - --success: 64.93% 0.107 154.24; - --success-foreground: 100% 0 0; - --border: 100% 0 0 / 13.33%; - --border-dark: 100% 0 0 / 39.33%; - --input: 100% 0 0 / 10.59%; - --ring: 221.2 83.2% 53.3%; - } +.dark, +:root[class~="dark"] { + --background: oklch(21.34% 0 0); + --background-2: oklch(25.2% 0 0); + --background-3: oklch(28.5% 0 0); + --foreground: oklch(92.8% 0 0); + --popover: oklch(28.5% 0 0); + --popover-foreground: oklch(92.8% 0 0); + --primary: oklch(54% 0.1789 271); + --primary-foreground: oklch(92.8% 0 0); + --secondary: 210 40% 96.1%; + --secondary-foreground: oklch(92.8% 0 0); + --muted: oklch(100% 0 0 / 13.33%); + --muted-foreground: oklch(76.99% 0 0); + --accent: oklch(95.81% 0 0); + --accent-foreground: oklch(0% 0 0); + --warning: oklch(70.43% 0.14390424619548714 87.9634104985311); + --warning-foreground: oklch(100% 0 0); + --destructive: oklch(61.34% 0.162 23.58); + --destructive-foreground: oklch(100% 0 0); + --success: oklch(64.93% 0.107 154.24); + --success-foreground: oklch(100% 0 0); + --border: oklch(100% 0 0 / 13.33%); + --border-dark: oklch(100% 0 0 / 39.33%); + --input: oklch(100% 0 0 / 10.59%); + --ring: 221.2 83.2% 53.3%; } - - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); +} \ No newline at end of file diff --git a/apps/webapp/app/utils.ts b/apps/webapp/app/utils.ts index bb6fb76..0b3dbbf 100644 --- a/apps/webapp/app/utils.ts +++ b/apps/webapp/app/utils.ts @@ -1,5 +1,4 @@ -import type { UIMatch } from "@remix-run/react"; -import { useMatches } from "@remix-run/react"; +import { useMatches, type UIMatch } from "@remix-run/react"; const DEFAULT_REDIRECT = "/"; @@ -12,7 +11,7 @@ const DEFAULT_REDIRECT = "/"; */ export function safeRedirect( to: FormDataEntryValue | string | null | undefined, - defaultRedirect: string = DEFAULT_REDIRECT + defaultRedirect: string = DEFAULT_REDIRECT, ) { if (!to || typeof to !== "string") { return defaultRedirect; @@ -31,7 +30,10 @@ export function safeRedirect( * @param {string} id The route id * @returns {JSON|undefined} The router data or undefined if not found */ -export function useMatchesData(id: string | string[], debug: boolean = false): UIMatch | undefined { +export function useMatchesData( + id: string | string[], + debug: boolean = false, +): UIMatch | undefined { const matchingRoutes = useMatches(); if (debug) { @@ -41,10 +43,13 @@ export function useMatchesData(id: string | string[], debug: boolean = false): U const paths = Array.isArray(id) ? id : [id]; // Get the first matching route - const route = paths.reduce((acc, path) => { - if (acc) return acc; - return matchingRoutes.find((route) => route.id === path); - }, undefined as UIMatch | undefined); + const route = paths.reduce( + (acc, path) => { + if (acc) return acc; + return matchingRoutes.find((route) => route.id === path); + }, + undefined as UIMatch | undefined, + ); return route; } diff --git a/apps/webapp/app/utils/httpErrors.ts b/apps/webapp/app/utils/httpErrors.ts new file mode 100644 index 0000000..637b6bf --- /dev/null +++ b/apps/webapp/app/utils/httpErrors.ts @@ -0,0 +1,24 @@ +export function friendlyErrorDisplay(statusCode: number, statusText?: string) { + switch (statusCode) { + case 400: + return { + title: "400: Bad request", + message: statusText ?? "The request was invalid.", + }; + case 404: + return { + title: "404: Page not found", + message: statusText ?? "The page you're looking for doesn't exist.", + }; + case 500: + return { + title: "500: Server error", + message: statusText ?? "Something went wrong on our end. Please try again later.", + }; + default: + return { + title: `${statusCode}: Error`, + message: statusText ?? "An error occurred.", + }; + } +} diff --git a/apps/webapp/app/utils/singleton.ts b/apps/webapp/app/utils/singleton.ts new file mode 100644 index 0000000..6aac987 --- /dev/null +++ b/apps/webapp/app/utils/singleton.ts @@ -0,0 +1,6 @@ +export function singleton(name: string, getValue: () => T): T { + const thusly = globalThis as any; + thusly.__echo_singletons ??= {}; + thusly.__echo_singletons[name] ??= getValue(); + return thusly.__echo_singletons[name]; +} diff --git a/apps/webapp/package.json b/apps/webapp/package.json index 10b92ad..5abd635 100644 --- a/apps/webapp/package.json +++ b/apps/webapp/package.json @@ -5,55 +5,85 @@ "type": "module", "scripts": { "build": "remix vite:build", - "dev": "remix vite:dev", + "dev": "node ./server.js", "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "remix-serve ./build/server/index.js", "typecheck": "tsc" }, "dependencies": { - "@remix-run/node": "^2.16.7", - "@remix-run/react": "^2.16.7", - "@remix-run/serve": "^2.16.7", - "@tailwindcss/container-queries": "^0.1.1", "@echo/database": "workspace:*", + "@opentelemetry/api": "1.9.0", + "@radix-ui/react-slot": "^1.2.3", + "@remix-run/express": "2.16.7", + "@remix-run/node": "2.1.0", + "@remix-run/react": "2.16.7", + "@remix-run/router": "^1.15.3", + "@remix-run/serve": "2.16.7", + "@remix-run/server-runtime": "2.16.7", + "@remix-run/v1-meta": "^0.1.3", + "@tailwindcss/postcss": "^4.1.7", + "@tailwindcss/container-queries": "^0.1.1", + "compression": "^1.7.4", "class-variance-authority": "^0.7.1", - "remix-typedjson": "0.3.1", "clsx": "^2.1.1", + "cross-env": "^7.0.3", + "express": "^4.18.1", "isbot": "^4.1.0", + "morgan": "^1.10.0", + "nanoid": "3.3.8", "lucide-react": "^0.511.0", + "non.geist": "^1.0.2", + "posthog-js": "^1.116.6", "react": "^18.2.0", "react-dom": "^18.2.0", - "tailwind-merge": "^1.12.0", - "tailwind-scrollbar-hide": "^1.1.7", - "tailwindcss-animate": "^1.0.5", + "remix-auth": "^3.6.0", + "remix-auth-google": "^2.0.0", + "remix-typedjson": "0.3.1", + "remix-utils": "^7.7.0", + "remix-themes": "^1.3.1", + "tailwind-merge": "^2.6.0", + "tailwind-scrollbar-hide": "^2.0.0", + "tailwindcss-animate": "^1.0.7", "tailwindcss-textshadow": "^2.1.3", - "non.geist": "^1.0.2", + "tiny-invariant": "^1.3.1", "zod": "3.23.8", "zod-error": "1.5.0", "zod-validation-error": "^1.5.0" }, "devDependencies": { - "@remix-run/dev": "^2.16.7", + "@remix-run/dev": "2.16.7", + "@remix-run/eslint-config": "2.16.7", + "@remix-run/testing": "^2.16.7", + "@tailwindcss/forms": "^0.5.10", + "@tailwindcss/typography": "^0.5.16", + "@tailwindcss/vite": "^4.1.7", + + "@types/compression": "^1.7.2", + "@types/morgan": "^1.9.3", + "@types/express": "^4.17.13", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "@typescript-eslint/eslint-plugin": "^6.7.4", "@typescript-eslint/parser": "^6.7.4", "autoprefixer": "^10.4.19", - "esbuild": "0.25.5", - "eslint": "^8.38.0", + "css-loader": "^6.10.0", + "esbuild": "^0.25.5", "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.28.1", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", + "eslint": "^8.24.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-turbo": "^2.0.4", "postcss": "^8.4.38", - "prettier": "^2.8.8", - "prettier-plugin-tailwindcss": "^0.3.0", - "@tailwindcss/forms": "^0.5.3", - "@tailwindcss/typography": "^0.5.9", - "tailwind-scrollbar": "^3.0.1", - "tailwindcss": "3.4.1", - "typescript": "^5.1.6", + "postcss-import": "^16.0.1", + "postcss-loader": "^8.1.1", + "prettier": "^3.5.3", + "prettier-plugin-tailwindcss": "^0.6.11", + "tailwind-scrollbar": "^4.0.2", + "tailwindcss": "4.1.7", + "typescript": "5.8.3", "vite": "^6.0.0", "vite-tsconfig-paths": "^4.2.1" }, diff --git a/apps/webapp/postcss.config.js b/apps/webapp/postcss.config.js deleted file mode 100644 index 2aa7205..0000000 --- a/apps/webapp/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/apps/webapp/prettier.config.cjs b/apps/webapp/prettier.config.cjs deleted file mode 100644 index f652d8b..0000000 --- a/apps/webapp/prettier.config.cjs +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - ...require("../../prettier.config.js"), - plugins: [require("prettier-plugin-tailwindcss")], -}; diff --git a/apps/webapp/remix.config.js b/apps/webapp/remix.config.js deleted file mode 100644 index 1573d84..0000000 --- a/apps/webapp/remix.config.js +++ /dev/null @@ -1,30 +0,0 @@ -/** @type {import('@remix-run/dev').AppConfig} */ -module.exports = { - dev: { - port: 8002, - }, - tailwind: true, - postcss: true, - cacheDirectory: "./node_modules/.cache/remix", - ignoredRouteFiles: ["**/.*"], - serverModuleFormat: "cjs", - serverDependenciesToBundle: [ - /^remix-utils.*/, - /^@internal\//, // Bundle all internal packages - "marked", - "axios", - "p-limit", - "yocto-queue", - "@unkey/cache", - "@unkey/cache/stores", - "emails", - "highlight.run", - "random-words", - "superjson", - "prismjs/components/prism-json", - "prismjs/components/prism-typescript", - "redlock", - "parse-duration", - ], - browserNodeBuiltinsPolyfill: { modules: { path: true, os: true, crypto: true } }, -}; diff --git a/apps/webapp/server.js b/apps/webapp/server.js new file mode 100644 index 0000000..1cdb58a --- /dev/null +++ b/apps/webapp/server.js @@ -0,0 +1,51 @@ +import { createRequestHandler } from "@remix-run/express"; +import compression from "compression"; +import express from "express"; +import morgan from "morgan"; + +const viteDevServer = + process.env.NODE_ENV === "production" + ? undefined + : await import("vite").then((vite) => + vite.createServer({ + server: { middlewareMode: true }, + }), + ); + +const remixHandler = createRequestHandler({ + build: viteDevServer + ? () => viteDevServer.ssrLoadModule("virtual:remix/server-build") + : await import("./build/server/index.js"), +}); + +const app = express(); + +app.use(compression()); + +// http://expressjs.com/en/advanced/best-practice-security.html#at-a-minimum-disable-x-powered-by-header +app.disable("x-powered-by"); + +// handle asset requests +if (viteDevServer) { + app.use(viteDevServer.middlewares); +} else { + // Vite fingerprints its assets so we can cache forever. + app.use( + "/assets", + express.static("build/client/assets", { immutable: true, maxAge: "1y" }), + ); +} + +// Everything else (like favicon.ico) is cached for an hour. You may want to be +// more aggressive with this caching. +app.use(express.static("build/client", { maxAge: "1h" })); + +app.use(morgan("tiny")); + +// handle SSR requests +app.all("*", remixHandler); + +const port = process.env.REMIX_APP_PORT || 3000; +app.listen(port, () => + console.log(`Express server listening at http://localhost:${port}`), +); diff --git a/apps/webapp/tailwind.config.js b/apps/webapp/tailwind.config.js deleted file mode 100644 index fb33c21..0000000 --- a/apps/webapp/tailwind.config.js +++ /dev/null @@ -1,167 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -const colors = require("tailwindcss/colors"); - - -/** @type {import('tailwindcss').Config} */ -module.exports = { - darkMode: ["class"], - content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"], - theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px", - }, - }, - extend: { - fontFamily: { - sans: ["Geist Variable", "Helvetica Neue", "Helvetica", "Arial", "sans-serif"], - mono: ["Geist Mono Variable", "monaco", "Consolas", "Lucida Console", "monospace"], - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' - }, - colors: { - border: { - DEFAULT: 'oklch(var(--border))', - dark: 'oklch(var(--border-dark))', - }, - input: 'oklch(var(--input))', - ring: 'oklch(var(--ring))', - background: { - '2': 'oklch(var(--background-2) / )', - '3': 'oklch(var(--background-3) / )', - DEFAULT: 'oklch(var(--background) / )', - }, - foreground: 'oklch(var(--foreground) / )', - primary: { - DEFAULT: 'oklch(var(--primary) / )', - foreground: 'oklch(var(--primary-foreground) / )', - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))', - }, - destructive: { - DEFAULT: 'oklch(var(--destructive) / )', - foreground: 'oklch(var(--destructive-foreground) / )', - }, - warning: { - DEFAULT: 'oklch(var(--warning) / )', - foreground: 'oklch(var(--warning-foreground) / )', - }, - success: { - DEFAULT: 'oklch(var(--success) / )', - foreground: 'oklch(var(--success-foreground) / )', - }, - muted: { - DEFAULT: 'oklch(var(--muted))', - foreground: 'oklch(var(--muted-foreground) / )', - }, - accent: { - DEFAULT: 'oklch(var(--accent) / )', - foreground: 'oklch(var(--accent-foreground) / )', - }, - popover: { - DEFAULT: 'oklch(var(--popover) / )', - foreground: 'oklch(var(--popover-foreground) / )', - }, - gray: { - '50': 'var(--gray-50)', - '100': 'var(--gray-100)', - '200': 'var(--gray-200)', - '300': 'var(--gray-300)', - '400': 'var(--gray-400)', - '500': 'var(--gray-500)', - '600': 'var(--gray-600)', - '700': 'var(--gray-700)', - '800': 'var(--gray-800)', - '900': 'var(--gray-900)', - '950': 'var(--gray-950)', - }, - grayAlpha: { - '50': 'oklch(var(--grayAlpha-50))', - '100': 'oklch(var(--grayAlpha-100))', - '200': 'oklch(var(--grayAlpha-200))', - '300': 'oklch(var(--grayAlpha-300))', - '400': 'oklch(var(--grayAlpha-400))', - '500': 'oklch(var(--grayAlpha-500))', - '600': 'oklch(var(--grayAlpha-600))', - '700': 'oklch(var(--grayAlpha-700))', - '800': 'oklch(var(--grayAlpha-800))', - '900': 'oklch(var(--grayAlpha-900))', - '950': 'oklch(var(--grayAlpha-950))', - }, - red: { - '50': '#fdf3f3', - '100': '#fbe9e8', - '200': '#f7d4d4', - '300': '#f0b1b1', - '400': '#e78587', - '500': '#d75056', - '600': '#c43a46', - '700': '#a52b3a', - '800': '#8a2735', - '900': '#772433', - '950': '#420f18', - }, - orange: { - '50': '#fdf6ef', - '100': '#fbead9', - '200': '#f7d2b1', - '300': '#f1b480', - '400': '#ea8c4d', - '500': '#e67333', - '600': '#d65520', - '700': '#b2401c', - '800': '#8e341e', - '900': '#732d1b', - '950': '#3e140c', - }, - yellow: { - '50': '#fdfbe9', - '100': '#faf7c7', - '200': '#f7ec91', - '300': '#f1db53', - '400': '#ebc724', - '500': '#dcb016', - '600': '#c28c11', - '700': '#976211', - '800': '#7d4f16', - '900': '#6b4118', - '950': '#3e220a', - }, - sidebar: { - DEFAULT: 'oklch(var(--background-2) / )', - foreground: 'oklch(var(--foreground) / )', - primary: 'oklch(var(--primary) / )', - 'primary-foreground': - 'oklch(var(--primary-foreground) / )', - accent: 'oklch(var(--accent) / )', - 'accent-foreground': - 'oklch(var(--accent-foreground) / )', - border: 'oklch(var(--border))', - ring: 'oklch(var(--ring))', - }, - }, - } - }, - plugins: [ require("@tailwindcss/container-queries"), - require("@tailwindcss/forms"), - require("@tailwindcss/typography"), - require("tailwindcss-animate"), - require("tailwind-scrollbar"), - require("tailwind-scrollbar-hide"), - require("tailwindcss-textshadow"), - function ({ addUtilities, theme }) { - const focusStyles = theme("focusStyles", {}); - addUtilities({ - ".focus-custom": { - "&:focus-visible": focusStyles, - }, - }); - },], -} diff --git a/apps/webapp/tailwind.config.ts b/apps/webapp/tailwind.config.ts new file mode 100644 index 0000000..fee4ac5 --- /dev/null +++ b/apps/webapp/tailwind.config.ts @@ -0,0 +1,169 @@ +import type { Config } from "tailwindcss"; + +export default { + content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"], + theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + fontFamily: { + sans: [ + "Geist Variable", + "Helvetica Neue", + "Helvetica", + "Arial", + "sans-serif", + ], + mono: [ + "Geist Mono Variable", + "monaco", + "Consolas", + "Lucida Console", + "monospace", + ], + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + colors: { + border: { + DEFAULT: "oklch(var(--border))", + dark: "oklch(var(--border-dark))", + }, + input: "oklch(var(--input))", + ring: "oklch(var(--ring))", + background: { + 2: "oklch(var(--background-2) / )", + 3: "oklch(var(--background-3) / )", + DEFAULT: "oklch(var(--background) / )", + }, + foreground: "oklch(var(--foreground) / )", + primary: { + DEFAULT: "oklch(var(--primary) / )", + foreground: "oklch(var(--primary-foreground) / )", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "oklch(var(--destructive) / )", + foreground: "oklch(var(--destructive-foreground) / )", + }, + warning: { + DEFAULT: "oklch(var(--warning) / )", + foreground: "oklch(var(--warning-foreground) / )", + }, + success: { + DEFAULT: "oklch(var(--success) / )", + foreground: "oklch(var(--success-foreground) / )", + }, + muted: { + DEFAULT: "oklch(var(--muted))", + foreground: "oklch(var(--muted-foreground) / )", + }, + accent: { + DEFAULT: "oklch(var(--accent) / )", + foreground: "oklch(var(--accent-foreground) / )", + }, + popover: { + DEFAULT: "oklch(var(--popover) / )", + foreground: "oklch(var(--popover-foreground) / )", + }, + gray: { + 50: "var(--gray-50)", + 100: "var(--gray-100)", + 200: "var(--gray-200)", + 300: "var(--gray-300)", + 400: "var(--gray-400)", + 500: "var(--gray-500)", + 600: "var(--gray-600)", + 700: "var(--gray-700)", + 800: "var(--gray-800)", + 900: "var(--gray-900)", + 950: "var(--gray-950)", + }, + grayAlpha: { + 50: "oklch(var(--grayAlpha-50))", + 100: "oklch(var(--grayAlpha-100))", + 200: "oklch(var(--grayAlpha-200))", + 300: "oklch(var(--grayAlpha-300))", + 400: "oklch(var(--grayAlpha-400))", + 500: "oklch(var(--grayAlpha-500))", + 600: "oklch(var(--grayAlpha-600))", + 700: "oklch(var(--grayAlpha-700))", + 800: "oklch(var(--grayAlpha-800))", + 900: "oklch(var(--grayAlpha-900))", + 950: "oklch(var(--grayAlpha-950))", + }, + red: { + 50: "#fdf3f3", + 100: "#fbe9e8", + 200: "#f7d4d4", + 300: "#f0b1b1", + 400: "#e78587", + 500: "#d75056", + 600: "#c43a46", + 700: "#a52b3a", + 800: "#8a2735", + 900: "#772433", + 950: "#420f18", + }, + orange: { + 50: "#fdf6ef", + 100: "#fbead9", + 200: "#f7d2b1", + 300: "#f1b480", + 400: "#ea8c4d", + 500: "#e67333", + 600: "#d65520", + 700: "#b2401c", + 800: "#8e341e", + 900: "#732d1b", + 950: "#3e140c", + }, + yellow: { + 50: "#fdfbe9", + 100: "#faf7c7", + 200: "#f7ec91", + 300: "#f1db53", + 400: "#ebc724", + 500: "#dcb016", + 600: "#c28c11", + 700: "#976211", + 800: "#7d4f16", + 900: "#6b4118", + 950: "#3e220a", + }, + sidebar: { + DEFAULT: "oklch(var(--background-2) / )", + foreground: "oklch(var(--foreground) / )", + primary: "oklch(var(--primary) / )", + "primary-foreground": + "oklch(var(--primary-foreground) / )", + accent: "oklch(var(--accent) / )", + "accent-foreground": + "oklch(var(--accent-foreground) / )", + border: "oklch(var(--border))", + ring: "oklch(var(--ring))", + }, + }, + }, + }, + plugins: [ + require("@tailwindcss/container-queries"), + require("@tailwindcss/forms"), + require("@tailwindcss/typography"), + require("tailwindcss-animate"), + require("tailwind-scrollbar"), + require("tailwind-scrollbar-hide"), + require("tailwindcss-textshadow"), + ], +} satisfies Config; diff --git a/apps/webapp/tsconfig.json b/apps/webapp/tsconfig.json index 5086e29..19e3238 100644 --- a/apps/webapp/tsconfig.json +++ b/apps/webapp/tsconfig.json @@ -1,8 +1,15 @@ { "exclude": [], - "include": ["remix.env.d.ts", "global.d.ts", "**/*.ts", "**/*.tsx"], + "include": [ + "remix.env.d.ts", + "global.d.ts", + "**/*.ts", + "**/*.tsx", + "tailwind.config.js", + "tailwind.config.js" + ], "compilerOptions": { - "types": [], + "types": ["@remix-run/node", "vite/client"], "lib": ["DOM", "DOM.Iterable", "DOM.AsyncIterable", "ES2020"], "isolatedModules": true, "esModuleInterop": true, diff --git a/apps/webapp/vite.config.ts b/apps/webapp/vite.config.ts index e4e8cef..3b74ab7 100644 --- a/apps/webapp/vite.config.ts +++ b/apps/webapp/vite.config.ts @@ -1,6 +1,7 @@ import { vitePlugin as remix } from "@remix-run/dev"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; +import tailwindcss from "@tailwindcss/vite"; declare module "@remix-run/node" { interface Future { @@ -10,6 +11,7 @@ declare module "@remix-run/node" { export default defineConfig({ plugins: [ + tailwindcss(), remix({ future: { v3_fetcherPersist: true, diff --git a/package.json b/package.json index f2f198b..a7b7974 100644 --- a/package.json +++ b/package.json @@ -2,24 +2,26 @@ "name": "echo", "private": true, "workspaces": - [ "apps/*" ] + [ "apps/*", "packages/*" ] , "scripts": { - "build": "turbo run build", - "dev": "turbo run dev", - "lint": "turbo run lint", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "check-types": "turbo run check-types", - "db:migrate": "turbo run db:migrate:deploy generate", - "db:seed": "turbo run db:seed", - "db:studio": "turbo run db:studio", - "db:populate": "turbo run db:populate", - "generate": "turbo run generate" + "build": "dotenv -- turbo run build", + "dev": "dotenv -- turbo run dev", + "lint": "dotenv -- turbo run lint", + "format": "dotenv -- prettier --write \"**/*.{ts,tsx,md}\"", + "check-types": "dotenv -- turbo run check-types", + "db:migrate": "dotenv -- turbo run db:migrate:deploy generate", + "db:migrate:create": "dotenv -- turbo run db:migrate:create generate", + "db:seed": "dotenv -- turbo run db:seed", + "db:studio": "dotenv -- turbo run db:studio", + "db:populate": "dotenv -- turbo run db:populate", + "generate": "dotenv -- turbo run generate" }, "devDependencies": { + "dotenv-cli": "^7.4.4", "prettier": "^3.5.3", "turbo": "^2.5.3", - "typescript": "5.8.2" + "typescript": "5.5.4" }, "dependencies": { "@changesets/cli": "2.26.2", diff --git a/packages/database/package.json b/packages/database/package.json index 041e225..dfbbba3 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -9,12 +9,13 @@ }, "devDependencies": { "prisma": "5.4.1", - "rimraf": "6.0.1" + "rimraf": "6.0.1", + "esbuild": "^0.15.10" }, "scripts": { "clean": "rimraf dist", "generate": "prisma generate", - "db:migrate:dev:create": "prisma migrate dev --create-only", + "db:migrate:create": "prisma migrate dev --preview-feature", "db:migrate:deploy": "prisma migrate deploy", "db:push": "prisma db push", "db:studio": "prisma studio", diff --git a/packages/database/prisma/migrations/20250527101713_init/migration.sql b/packages/database/prisma/migrations/20250527101713_init/migration.sql new file mode 100644 index 0000000..acddb54 --- /dev/null +++ b/packages/database/prisma/migrations/20250527101713_init/migration.sql @@ -0,0 +1,84 @@ +-- CreateEnum +CREATE TYPE "AuthenticationMethod" AS ENUM ('GOOGLE'); + +-- CreateTable +CREATE TABLE "User" ( + "id" TEXT NOT NULL, + "email" TEXT NOT NULL, + "authenticationMethod" "AuthenticationMethod" NOT NULL, + "authenticationProfile" JSONB, + "authenticationExtraParams" JSONB, + "authIdentifier" TEXT, + "displayName" TEXT, + "name" TEXT, + "avatarUrl" TEXT, + "admin" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "marketingEmails" BOOLEAN NOT NULL DEFAULT true, + "confirmedBasicDetails" BOOLEAN NOT NULL DEFAULT false, + "referralSource" TEXT, + "invitationCodeId" TEXT, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "AuthorizationCode" ( + "id" TEXT NOT NULL, + "code" TEXT NOT NULL, + "personalAccessTokenId" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "AuthorizationCode_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "PersonalAccessToken" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "encryptedToken" JSONB NOT NULL, + "obfuscatedToken" TEXT NOT NULL, + "hashedToken" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "revokedAt" TIMESTAMP(3), + "lastAccessedAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "PersonalAccessToken_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "InvitationCode" ( + "id" TEXT NOT NULL, + "code" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "InvitationCode_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_authIdentifier_key" ON "User"("authIdentifier"); + +-- CreateIndex +CREATE UNIQUE INDEX "AuthorizationCode_code_key" ON "AuthorizationCode"("code"); + +-- CreateIndex +CREATE UNIQUE INDEX "PersonalAccessToken_hashedToken_key" ON "PersonalAccessToken"("hashedToken"); + +-- CreateIndex +CREATE UNIQUE INDEX "InvitationCode_code_key" ON "InvitationCode"("code"); + +-- AddForeignKey +ALTER TABLE "User" ADD CONSTRAINT "User_invitationCodeId_fkey" FOREIGN KEY ("invitationCodeId") REFERENCES "InvitationCode"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AuthorizationCode" ADD CONSTRAINT "AuthorizationCode_personalAccessTokenId_fkey" FOREIGN KEY ("personalAccessTokenId") REFERENCES "PersonalAccessToken"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PersonalAccessToken" ADD CONSTRAINT "PersonalAccessToken_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/packages/database/prisma/migrations/20250527174127_add_space_queue/migration.sql b/packages/database/prisma/migrations/20250527174127_add_space_queue/migration.sql new file mode 100644 index 0000000..223ea79 --- /dev/null +++ b/packages/database/prisma/migrations/20250527174127_add_space_queue/migration.sql @@ -0,0 +1,75 @@ +-- CreateEnum +CREATE TYPE "IngestionStatus" AS ENUM ('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED', 'CANCELLED'); + +-- AlterTable +ALTER TABLE "User" ADD COLUMN "memoryFilter" TEXT; + +-- CreateTable +CREATE TABLE "Space" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "autoMode" BOOLEAN NOT NULL DEFAULT false, + "userId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Space_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Entity" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "metadata" JSONB NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Entity_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "SpaceEntity" ( + "id" TEXT NOT NULL, + "spaceId" TEXT NOT NULL, + "entityId" TEXT NOT NULL, + "settings" JSONB, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "SpaceEntity_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "IngestionQueue" ( + "id" TEXT NOT NULL, + "spaceId" TEXT NOT NULL, + "data" JSONB NOT NULL, + "status" "IngestionStatus" NOT NULL, + "priority" INTEGER NOT NULL DEFAULT 0, + "error" TEXT, + "retryCount" INTEGER NOT NULL DEFAULT 0, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "processedAt" TIMESTAMP(3), + + CONSTRAINT "IngestionQueue_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Entity_name_key" ON "Entity"("name"); + +-- CreateIndex +CREATE UNIQUE INDEX "SpaceEntity_spaceId_entityId_key" ON "SpaceEntity"("spaceId", "entityId"); + +-- AddForeignKey +ALTER TABLE "Space" ADD CONSTRAINT "Space_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "SpaceEntity" ADD CONSTRAINT "SpaceEntity_spaceId_fkey" FOREIGN KEY ("spaceId") REFERENCES "Space"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "SpaceEntity" ADD CONSTRAINT "SpaceEntity_entityId_fkey" FOREIGN KEY ("entityId") REFERENCES "Entity"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "IngestionQueue" ADD CONSTRAINT "IngestionQueue_spaceId_fkey" FOREIGN KEY ("spaceId") REFERENCES "Space"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/packages/database/prisma/migrations/migration_lock.toml b/packages/database/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..fbffa92 --- /dev/null +++ b/packages/database/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/packages/database/prisma/schema.prisma b/packages/database/prisma/schema.prisma index 4079e1b..39cedb9 100644 --- a/packages/database/prisma/schema.prisma +++ b/packages/database/prisma/schema.prisma @@ -23,27 +23,22 @@ model User { name String? avatarUrl String? - admin Boolean @default(false) + memoryFilter String? // Adding memory filter instructions - /// Preferences for the dashboard - dashboardPreferences Json? + admin Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - /// @deprecated - isOnCloudWaitlist Boolean @default(false) - /// @deprecated - featureCloud Boolean @default(false) - /// @deprecated - isOnHostedRepoWaitlist Boolean @default(false) - marketingEmails Boolean @default(true) confirmedBasicDetails Boolean @default(false) referralSource String? personalAccessTokens PersonalAccessToken[] + InvitationCode InvitationCode? @relation(fields: [invitationCodeId], references: [id]) + invitationCodeId String? + Space Space[] } enum AuthenticationMethod { @@ -90,3 +85,95 @@ model PersonalAccessToken { authorizationCodes AuthorizationCode[] } + +model InvitationCode { + id String @id @default(cuid()) + code String @unique + + users User[] + + createdAt DateTime @default(now()) +} + +// Space model for user workspaces +model Space { + id String @id @default(cuid()) + name String + description String? + autoMode Boolean @default(false) + + // Relations + user User @relation(fields: [userId], references: [id]) + userId String + + // Space's enabled entities + enabledEntities SpaceEntity[] + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + IngestionQueue IngestionQueue[] +} + +// Entity types that can be stored in the memory plane +model Entity { + id String @id @default(cuid()) + name String @unique // e.g., "User", "Issue", "Task", "Automation" + metadata Json // Store field definitions and their types + + // Relations + spaceEntities SpaceEntity[] + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +// Junction table for Space-Entity relationship (what entities are enabled in each space) +model SpaceEntity { + id String @id @default(cuid()) + + // Relations + space Space @relation(fields: [spaceId], references: [id]) + spaceId String + + entity Entity @relation(fields: [entityId], references: [id]) + entityId String + + // Custom settings for this entity in this space + settings Json? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([spaceId, entityId]) +} + +// Queue for processing ingestion tasks +model IngestionQueue { + id String @id @default(cuid()) + + // Relations + space Space @relation(fields: [spaceId], references: [id]) + spaceId String + + // Queue metadata + data Json // The actual data to be processed + status IngestionStatus + priority Int @default(0) + + // Error handling + error String? + retryCount Int @default(0) + + // Timestamps + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + processedAt DateTime? +} + +enum IngestionStatus { + PENDING + PROCESSING + COMPLETED + FAILED + CANCELLED +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 79c857c..52e597f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,6 +15,9 @@ importers: specifier: ^0.0.5 version: 0.0.5 devDependencies: + dotenv-cli: + specifier: ^7.4.4 + version: 7.4.4 prettier: specifier: ^3.5.3 version: 3.5.3 @@ -22,62 +25,116 @@ importers: specifier: ^2.5.3 version: 2.5.3 typescript: - specifier: 5.8.2 - version: 5.8.2 + specifier: 5.5.4 + version: 5.5.4 apps/webapp: dependencies: '@echo/database': specifier: workspace:* version: link:../../packages/database + '@opentelemetry/api': + specifier: 1.9.0 + version: 1.9.0 + '@radix-ui/react-slot': + specifier: ^1.2.3 + version: 1.2.3(@types/react@18.3.23)(react@18.3.1) + '@remix-run/express': + specifier: 2.16.7 + version: 2.16.7(express@4.21.2)(typescript@5.8.3) '@remix-run/node': - specifier: ^2.16.7 - version: 2.16.7(typescript@5.8.2) + specifier: 2.1.0 + version: 2.1.0(typescript@5.8.3) '@remix-run/react': - specifier: ^2.16.7 - version: 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.2) + specifier: 2.16.7 + version: 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) + '@remix-run/router': + specifier: ^1.15.3 + version: 1.23.0 '@remix-run/serve': - specifier: ^2.16.7 - version: 2.16.7(typescript@5.8.2) + specifier: 2.16.7 + version: 2.16.7(typescript@5.8.3) + '@remix-run/server-runtime': + specifier: 2.16.7 + version: 2.16.7(typescript@5.8.3) + '@remix-run/v1-meta': + specifier: ^0.1.3 + version: 0.1.3(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3)) '@tailwindcss/container-queries': specifier: ^0.1.1 - version: 0.1.1(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))) + version: 0.1.1(tailwindcss@4.1.7) + '@tailwindcss/postcss': + specifier: ^4.1.7 + version: 4.1.7 class-variance-authority: specifier: ^0.7.1 version: 0.7.1 clsx: specifier: ^2.1.1 version: 2.1.1 + compression: + specifier: ^1.7.4 + version: 1.8.0 + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + express: + specifier: ^4.18.1 + version: 4.21.2 isbot: specifier: ^4.1.0 version: 4.4.0 lucide-react: specifier: ^0.511.0 version: 0.511.0(react@18.3.1) + morgan: + specifier: ^1.10.0 + version: 1.10.0 + nanoid: + specifier: 3.3.8 + version: 3.3.8 non.geist: specifier: ^1.0.2 version: 1.0.4 + posthog-js: + specifier: ^1.116.6 + version: 1.246.0 react: specifier: ^18.2.0 version: 18.3.1 react-dom: specifier: ^18.2.0 version: 18.3.1(react@18.3.1) + remix-auth: + specifier: ^3.6.0 + version: 3.7.0(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3)) + remix-auth-google: + specifier: ^2.0.0 + version: 2.0.0(@remix-run/server-runtime@2.16.7(typescript@5.8.3))(remix-auth@3.7.0(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3))) + remix-themes: + specifier: ^1.3.1 + version: 1.6.1(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3)) remix-typedjson: specifier: 0.3.1 - version: 0.3.1(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.2))(@remix-run/server-runtime@2.16.7(typescript@5.8.2))(react@18.3.1) + version: 0.3.1(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3))(react@18.3.1) + remix-utils: + specifier: ^7.7.0 + version: 7.7.0(@remix-run/node@2.1.0(typescript@5.8.3))(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/router@1.23.0)(react@18.3.1)(zod@3.23.8) tailwind-merge: - specifier: ^1.12.0 - version: 1.14.0 + specifier: ^2.6.0 + version: 2.6.0 tailwind-scrollbar-hide: - specifier: ^1.1.7 - version: 1.3.1(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))) + specifier: ^2.0.0 + version: 2.0.0(tailwindcss@4.1.7) tailwindcss-animate: - specifier: ^1.0.5 - version: 1.0.7(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))) + specifier: ^1.0.7 + version: 1.0.7(tailwindcss@4.1.7) tailwindcss-textshadow: specifier: ^2.1.3 version: 2.1.3 + tiny-invariant: + specifier: ^1.3.1 + version: 1.3.3 zod: specifier: 3.23.8 version: 3.23.8 @@ -89,74 +146,107 @@ importers: version: 1.5.0(zod@3.23.8) devDependencies: '@remix-run/dev': + specifier: 2.16.7 + version: 2.16.7(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.7(typescript@5.8.3))(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))(yaml@2.8.0) + '@remix-run/eslint-config': + specifier: 2.16.7 + version: 2.16.7(eslint@8.57.1)(react@18.3.1)(typescript@5.8.3) + '@remix-run/testing': specifier: ^2.16.7 - version: 2.16.7(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.2))(@remix-run/serve@2.16.7(typescript@5.8.2))(@types/node@22.15.3)(jiti@1.21.7)(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))(typescript@5.8.2)(vite@6.3.5(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0))(yaml@2.8.0) + version: 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) '@tailwindcss/forms': - specifier: ^0.5.3 - version: 0.5.10(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))) + specifier: ^0.5.10 + version: 0.5.10(tailwindcss@4.1.7) '@tailwindcss/typography': - specifier: ^0.5.9 - version: 0.5.16(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))) + specifier: ^0.5.16 + version: 0.5.16(tailwindcss@4.1.7) + '@tailwindcss/vite': + specifier: ^4.1.7 + version: 4.1.7(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + '@types/compression': + specifier: ^1.7.2 + version: 1.8.0 + '@types/express': + specifier: ^4.17.13 + version: 4.17.22 + '@types/morgan': + specifier: ^1.9.3 + version: 1.9.9 '@types/react': specifier: ^18.2.20 - version: 18.3.22 + version: 18.3.23 '@types/react-dom': specifier: ^18.2.7 - version: 18.3.7(@types/react@18.3.22) + version: 18.3.7(@types/react@18.3.23) '@typescript-eslint/eslint-plugin': specifier: ^6.7.4 - version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2) + version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3) '@typescript-eslint/parser': specifier: ^6.7.4 - version: 6.21.0(eslint@8.57.1)(typescript@5.8.2) + version: 6.21.0(eslint@8.57.1)(typescript@5.8.3) autoprefixer: specifier: ^10.4.19 version: 10.4.21(postcss@8.5.3) + css-loader: + specifier: ^6.10.0 + version: 6.11.0 esbuild: - specifier: 0.25.5 + specifier: ^0.25.5 version: 0.25.5 eslint: - specifier: ^8.38.0 + specifier: ^8.24.0 version: 8.57.1 + eslint-config-prettier: + specifier: ^8.5.0 + version: 8.10.0(eslint@8.57.1) eslint-import-resolver-typescript: specifier: ^3.6.1 version: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) eslint-plugin-import: - specifier: ^2.28.1 - version: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + specifier: ^2.29.1 + version: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) eslint-plugin-jsx-a11y: specifier: ^6.7.1 version: 6.10.2(eslint@8.57.1) eslint-plugin-react: specifier: ^7.33.2 - version: 7.37.4(eslint@8.57.1) + version: 7.37.5(eslint@8.57.1) eslint-plugin-react-hooks: - specifier: ^4.6.0 + specifier: ^4.6.2 version: 4.6.2(eslint@8.57.1) + eslint-plugin-turbo: + specifier: ^2.0.4 + version: 2.5.3(eslint@8.57.1)(turbo@2.5.3) postcss: specifier: ^8.4.38 version: 8.5.3 + postcss-import: + specifier: ^16.0.1 + version: 16.1.0(postcss@8.5.3) + postcss-loader: + specifier: ^8.1.1 + version: 8.1.1(postcss@8.5.3)(typescript@5.8.3) prettier: - specifier: ^2.8.8 - version: 2.8.8 + specifier: ^3.5.3 + version: 3.5.3 prettier-plugin-tailwindcss: - specifier: ^0.3.0 - version: 0.3.0(prettier@2.8.8) + specifier: ^0.6.11 + version: 0.6.11(prettier@3.5.3) tailwind-scrollbar: - specifier: ^3.0.1 - version: 3.1.0(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))) + specifier: ^4.0.2 + version: 4.0.2(react@18.3.1)(tailwindcss@4.1.7) tailwindcss: - specifier: 3.4.1 - version: 3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)) + specifier: 4.1.7 + version: 4.1.7 typescript: - specifier: ^5.1.6 - version: 5.8.2 + specifier: 5.8.3 + version: 5.8.3 vite: specifier: ^6.0.0 - version: 6.3.5(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0) + version: 6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) vite-tsconfig-paths: specifier: ^4.2.1 - version: 4.3.2(typescript@5.8.2)(vite@6.3.5(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0)) + version: 4.3.2(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) packages/database: dependencies: @@ -164,6 +254,9 @@ importers: specifier: 5.4.1 version: 5.4.1(prisma@5.4.1) devDependencies: + esbuild: + specifier: ^0.15.10 + version: 0.15.18 prisma: specifier: 5.4.1 version: 5.4.1 @@ -185,20 +278,27 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.27.2': - resolution: {integrity: sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==} + '@babel/compat-data@7.27.3': + resolution: {integrity: sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==} engines: {node: '>=6.9.0'} - '@babel/core@7.27.1': - resolution: {integrity: sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==} + '@babel/core@7.27.3': + resolution: {integrity: sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.27.1': - resolution: {integrity: sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==} + '@babel/eslint-parser@7.27.1': + resolution: {integrity: sha512-q8rjOuadH0V6Zo4XLMkJ3RMQ9MSBqwaDByyYB0izsYdaIWGNLmEblbCOf1vyFHICcg16CD7Fsi51vcQnYxmt6Q==} + engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} + peerDependencies: + '@babel/core': ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + + '@babel/generator@7.27.3': + resolution: {integrity: sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.27.1': - resolution: {integrity: sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==} + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.27.2': @@ -219,8 +319,8 @@ packages: resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.27.1': - resolution: {integrity: sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==} + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -255,12 +355,12 @@ packages: resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.27.1': - resolution: {integrity: sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==} + '@babel/helpers@7.27.3': + resolution: {integrity: sha512-h/eKy9agOya1IGuLaZ9tEUgz+uIRXcbtOhRtUyyMf8JFmn1iT13vnl/IGVWSkdOCG/pC57U4S1jnAabAavTMwg==} engines: {node: '>=6.9.0'} - '@babel/parser@7.27.2': - resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==} + '@babel/parser@7.27.3': + resolution: {integrity: sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==} engines: {node: '>=6.0.0'} hasBin: true @@ -288,32 +388,62 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-display-name@7.27.1': + resolution: {integrity: sha512-p9+Vl3yuHPmkirRrg021XiP+EETmPMQTLr6Ayjj85RLNEbb3Eya/4VI0vAdzQG9SEAl2Lnt7fy5lZyMzjYoZQQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-development@7.27.1': + resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx@7.27.1': + resolution: {integrity: sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-pure-annotations@7.27.1': + resolution: {integrity: sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-typescript@7.27.1': resolution: {integrity: sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/preset-react@7.27.1': + resolution: {integrity: sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/preset-typescript@7.27.1': resolution: {integrity: sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.27.1': - resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==} + '@babel/runtime@7.27.3': + resolution: {integrity: sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw==} engines: {node: '>=6.9.0'} '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.27.1': - resolution: {integrity: sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==} + '@babel/traverse@7.27.3': + resolution: {integrity: sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.27.1': - resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} + '@babel/types@7.27.3': + resolution: {integrity: sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==} engines: {node: '>=6.9.0'} '@changesets/apply-release-plan@6.1.4': @@ -371,10 +501,6 @@ packages: '@changesets/write@0.2.3': resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==} - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - '@emnapi/core@1.4.3': resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} @@ -417,6 +543,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm@0.15.18': + resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.17.6': resolution: {integrity: sha512-bSC9YVUjADDy1gae8RrioINU6e1lCkg3VGVwm0QQ2E1CWcC4gnMce9+B6RpxuSsrsXsk1yojn7sp1fnG8erE2g==} engines: {node: '>=12'} @@ -579,6 +711,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-loong64@0.15.18': + resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.17.6': resolution: {integrity: sha512-y2NX1+X/Nt+izj9bLoiaYB9YXT/LoaQFYvCkVD77G/4F+/yuVXYCWz4SE9yr5CBMbOxOfBcy/xFL4LlOeNlzYQ==} engines: {node: '>=12'} @@ -845,6 +983,10 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -863,9 +1005,6 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@jspm/core@2.1.0': resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} @@ -881,6 +1020,9 @@ packages: '@napi-rs/wasm-runtime@0.2.10': resolution: {integrity: sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==} + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -913,6 +1055,10 @@ packages: resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -932,6 +1078,24 @@ packages: '@prisma/engines@5.4.1': resolution: {integrity: sha512-vJTdY4la/5V3N7SFvWRmSMUh4mIQnyb/MNoDjzVbh9iLmEC+uEykj/1GPviVsorvfz7DbYSQC4RiwmlEpTEvGA==} + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@remix-run/changelog-github@0.0.5': resolution: {integrity: sha512-43tqwUqWqirbv6D9uzo55ASPsCJ61Ein1k/M8qn+Qpros0MmbmuzjLVPmtaxfxfe2ANX0LefLvCD0pAgr1tp4g==} @@ -955,6 +1119,17 @@ packages: wrangler: optional: true + '@remix-run/eslint-config@2.16.7': + resolution: {integrity: sha512-Q9y1IBSlphRR8xRSrFoCNwx6/YqbLL5tqZNwcn72Pciww5U13sVUA0EU5eNBT0zOUTY6NVGhKMhEs1jHBk3zuw==} + engines: {node: '>=18.0.0'} + peerDependencies: + eslint: ^8.0.0 + react: ^18.0.0 + typescript: ^5.1.0 + peerDependenciesMeta: + typescript: + optional: true + '@remix-run/express@2.16.7': resolution: {integrity: sha512-bvEsB+Dghd+97olvnANnXymqsVq5V4YN2YAlEcVA2f2mJxer2FQMXPP8yQsqnOHOjIkPRCKnB5I+jLpesCs0rA==} engines: {node: '>=18.0.0'} @@ -965,6 +1140,15 @@ packages: typescript: optional: true + '@remix-run/node@2.1.0': + resolution: {integrity: sha512-TeSgjXnZUUlmw5FVpBVnXY7MLpracjdnwFNwoJE5NQkiUEFnGD/Yhvk4F2fOCkszqc2Z25KRclc5noweyiFu6Q==} + engines: {node: '>=18.0.0'} + peerDependencies: + typescript: ^5.1.0 + peerDependenciesMeta: + typescript: + optional: true + '@remix-run/node@2.16.7': resolution: {integrity: sha512-7NSK9WM8te9sqvrKkJi9OQEO/ga/Idyr1aBMY5KMMaZmb7DH/qjaIfI/4nEHZ127dPS1hzlS+Vev+qAT8XyjvA==} engines: {node: '>=18.0.0'} @@ -985,6 +1169,10 @@ packages: typescript: optional: true + '@remix-run/router@1.10.0': + resolution: {integrity: sha512-Lm+fYpMfZoEucJ7cMxgt4dYt8jLfbpwRCzAjm9UgSLOkmlqo9gupxt6YX3DY0Fk155NT9l17d/ydi+964uS9Lw==} + engines: {node: '>=14.0.0'} + '@remix-run/router@1.23.0': resolution: {integrity: sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==} engines: {node: '>=14.0.0'} @@ -994,6 +1182,15 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + '@remix-run/server-runtime@2.1.0': + resolution: {integrity: sha512-Uz69yF4Gu6F3VYQub3JgDo9godN8eDMeZclkadBTAWN7bYLonu0ChR/GlFxS35OLeF7BDgudxOSZob0nE1WHNg==} + engines: {node: '>=18.0.0'} + peerDependencies: + typescript: ^5.1.0 + peerDependenciesMeta: + typescript: + optional: true + '@remix-run/server-runtime@2.16.7': resolution: {integrity: sha512-3aZZG8KBUQTenscOnV68AEwStRgx/rVvD8tkxwm92Zx7QMO/UZhhuNcZE9bvD5zTpp2sLwjwCTUK1eEJgTpKfg==} engines: {node: '>=18.0.0'} @@ -1003,6 +1200,22 @@ packages: typescript: optional: true + '@remix-run/testing@2.16.7': + resolution: {integrity: sha512-P0whGOX9NfxOzAqjLxHoK8u3fDr5YpxajdE7DQ/H0q99n9ebJ9wj1kxgeBzurt6Jpyqgk5y6ZvF8WR0o23kTFw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^18.0.0 + typescript: ^5.1.0 + peerDependenciesMeta: + typescript: + optional: true + + '@remix-run/v1-meta@0.1.3': + resolution: {integrity: sha512-pYTJSrT8ouipv9gL7sqk4hjgVrfj6Jcp9KDnjZKPFUF+91S1J5PNjipAHE1aXh0LyHo2rDbTW/OjtFeJ6BKhYg==} + peerDependencies: + '@remix-run/react': ^1.15.0 || ^2.0.0 + '@remix-run/server-runtime': ^1.15.0 || ^2.0.0 + '@remix-run/web-blob@3.1.0': resolution: {integrity: sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==} @@ -1122,6 +1335,9 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@rushstack/eslint-patch@1.11.0': + resolution: {integrity: sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==} + '@tailwindcss/container-queries@0.1.1': resolution: {integrity: sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==} peerDependencies: @@ -1132,22 +1348,107 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1' + '@tailwindcss/node@4.1.7': + resolution: {integrity: sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==} + + '@tailwindcss/oxide-android-arm64@4.1.7': + resolution: {integrity: sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.7': + resolution: {integrity: sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.7': + resolution: {integrity: sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.7': + resolution: {integrity: sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.7': + resolution: {integrity: sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.7': + resolution: {integrity: sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.7': + resolution: {integrity: sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.7': + resolution: {integrity: sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.1.7': + resolution: {integrity: sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.1.7': + resolution: {integrity: sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.7': + resolution: {integrity: sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.7': + resolution: {integrity: sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.7': + resolution: {integrity: sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==} + engines: {node: '>= 10'} + + '@tailwindcss/postcss@4.1.7': + resolution: {integrity: sha512-88g3qmNZn7jDgrrcp3ZXEQfp9CVox7xjP1HN2TFKI03CltPVd/c61ydn5qJJL8FYunn0OqBaW5HNUga0kmPVvw==} + '@tailwindcss/typography@0.5.16': resolution: {integrity: sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==} peerDependencies: tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + '@tailwindcss/vite@4.1.7': + resolution: {integrity: sha512-tYa2fO3zDe41I7WqijyVbRd8oWT0aEID1Eokz5hMT6wShLIHj3yvwj9XbfuloHP9glZ6H+aG2AN/+ZrxJ1Y5RQ==} + peerDependencies: + vite: ^5.2.0 || ^6 - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@testing-library/dom@8.20.1': + resolution: {integrity: sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==} + engines: {node: '>=12'} '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} @@ -1155,6 +1456,21 @@ packages: '@types/acorn@4.0.6': resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + + '@types/compression@1.8.0': + resolution: {integrity: sha512-g4vmPIwbTii9dX1HVioHbOolubEaf4re4vDxuzpKrzz9uI7uarBExi9begX0cXyIB85jXZ5X2A/v8rsHZxSAPw==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/cookie@0.4.1': + resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -1167,9 +1483,18 @@ packages: '@types/estree@1.0.7': resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} + + '@types/express@4.17.22': + resolution: {integrity: sha512-eZUmSnhRX9YRSkplpz0N+k6NljUUn5l3EWZIKZvYzhvMphEuNiyyy1viH/ejgt66JWgALwC/gtSUAeQKtSwW/w==} + '@types/hast@2.3.10': resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + '@types/is-ci@3.0.4': resolution: {integrity: sha512-AkCYCmwlXeuH89DagDCzvCAyltI2v9lh3U3DqSg/GrBYoReAaWwxfXCqMx9UV5MajLZ4ZFwZzV4cABGIxk2XRw==} @@ -1185,38 +1510,70 @@ packages: '@types/mdx@2.0.13': resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/minimist@1.2.5': resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + '@types/morgan@1.9.9': + resolution: {integrity: sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@22.15.3': - resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==} + '@types/node@22.15.21': + resolution: {integrity: sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/prismjs@1.26.5': + resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==} + '@types/prop-types@15.7.14': resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} + '@types/qs@6.14.0': + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/react-dom@18.3.7': resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} peerDependencies: '@types/react': ^18.0.0 - '@types/react@18.3.22': - resolution: {integrity: sha512-vUhG0YmQZ7kL/tmKLrD3g5zXbXXreZXB3pmROW8bg3CnLnpjkRVwUlLne7Ufa2r9yJ8+/6B73RzhAek5TBKh2Q==} + '@types/react@18.3.23': + resolution: {integrity: sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==} '@types/semver@7.7.0': resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + + '@types/serve-static@1.15.7': + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + '@typescript-eslint/eslint-plugin@5.62.0': + resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/eslint-plugin@6.21.0': resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1228,6 +1585,16 @@ packages: typescript: optional: true + '@typescript-eslint/parser@5.62.0': + resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/parser@6.21.0': resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1238,10 +1605,24 @@ packages: typescript: optional: true + '@typescript-eslint/scope-manager@5.62.0': + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/scope-manager@6.21.0': resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/type-utils@5.62.0': + resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/type-utils@6.21.0': resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1252,10 +1633,23 @@ packages: typescript: optional: true + '@typescript-eslint/types@5.62.0': + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/types@6.21.0': resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/typescript-estree@5.62.0': + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/typescript-estree@6.21.0': resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1265,12 +1659,22 @@ packages: typescript: optional: true + '@typescript-eslint/utils@5.62.0': + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@typescript-eslint/utils@6.21.0': resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 + '@typescript-eslint/visitor-keys@5.62.0': + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/visitor-keys@6.21.0': resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1401,10 +1805,6 @@ packages: resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} engines: {node: '>=0.4.0'} - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - acorn@7.4.1: resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} engines: {node: '>=0.4.0'} @@ -1413,6 +1813,7 @@ packages: acorn@8.14.1: resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} engines: {node: '>=0.4.0'} + hasBin: true aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} @@ -1441,20 +1842,18 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -1464,6 +1863,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -1680,6 +2082,10 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -1736,10 +2142,6 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - commander@5.1.0: resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} engines: {node: '>= 6'} @@ -1779,6 +2181,10 @@ packages: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} + cookie@0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + cookie@0.7.1: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} @@ -1787,11 +2193,25 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} + core-js@3.42.0: + resolution: {integrity: sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} @@ -1800,6 +2220,18 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-loader@6.11.0: + resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==} + engines: {node: '>= 12.13.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + css-unit-converter@1.1.2: resolution: {integrity: sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==} @@ -1894,6 +2326,10 @@ packages: babel-plugin-macros: optional: true + deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1934,18 +2370,15 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-libc@2.0.4: + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + engines: {node: '>=8'} + detective@5.2.1: resolution: {integrity: sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==} engines: {node: '>=0.8.0'} hasBin: true - didyoumean@1.2.2: - resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - - diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} @@ -1954,9 +2387,6 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - dlv@1.1.3: - resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -1965,10 +2395,25 @@ packages: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dotenv-cli@7.4.4: + resolution: {integrity: sha512-XkBYCG0tPIes+YZr4SpfFv76SQrV/LeCE8CI7JSEMi3VR9MvTihCGTOtbIexD6i2mXF+6px7trb1imVCXSNMDw==} + hasBin: true + + dotenv-expand@10.0.0: + resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} + engines: {node: '>=12'} + dotenv@16.0.3: resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} engines: {node: '>=12'} + dotenv@16.5.0: + resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} + engines: {node: '>=12'} + dotenv@8.6.0: resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} engines: {node: '>=10'} @@ -2006,18 +2451,26 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + enquirer@2.4.1: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + err-code@2.0.3: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.23.9: - resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + es-abstract@1.23.10: + resolution: {integrity: sha512-MtUbM072wlJNyeYAe0mhzrD+M6DIJa96CZAOBBrhDbgKnB4MApIKefcyAB1eOdYn8cUNZgvwBvEzdoAYsxgEIw==} engines: {node: '>= 0.4'} es-define-property@1.0.1: @@ -2028,6 +2481,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + es-iterator-helpers@1.2.1: resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} engines: {node: '>= 0.4'} @@ -2051,12 +2507,137 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + esbuild-android-64@0.15.18: + resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + esbuild-android-arm64@0.15.18: + resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + esbuild-darwin-64@0.15.18: + resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + esbuild-darwin-arm64@0.15.18: + resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + esbuild-freebsd-64@0.15.18: + resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + esbuild-freebsd-arm64@0.15.18: + resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + esbuild-linux-32@0.15.18: + resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + esbuild-linux-64@0.15.18: + resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + esbuild-linux-arm64@0.15.18: + resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + esbuild-linux-arm@0.15.18: + resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + esbuild-linux-mips64le@0.15.18: + resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + esbuild-linux-ppc64le@0.15.18: + resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + esbuild-linux-riscv64@0.15.18: + resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + esbuild-linux-s390x@0.15.18: + resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + esbuild-netbsd-64@0.15.18: + resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + esbuild-openbsd-64@0.15.18: + resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + esbuild-plugins-node-modules-polyfill@1.7.0: resolution: {integrity: sha512-Z81w5ReugIBAgufGeGWee+Uxzgs5Na4LprUAK3XlJEh2ktY3LkNuEGMaZyBXxQxGK8SQDS5yKLW5QKGF5qLjYA==} engines: {node: '>=14.0.0'} peerDependencies: esbuild: '>=0.14.0 <=0.25.x' + esbuild-sunos-64@0.15.18: + resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + esbuild-windows-32@0.15.18: + resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + esbuild-windows-64@0.15.18: + resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + esbuild-windows-arm64@0.15.18: + resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + esbuild@0.15.18: + resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} + engines: {node: '>=12'} + hasBin: true + esbuild@0.17.6: resolution: {integrity: sha512-TKFRp9TxrJDdRWfSsSERKEovm6v30iHnrjlcGhLBOtReE28Yp1VSBRfO3GTaOFMoxsNerx4TjrhzSuma9ha83Q==} engines: {node: '>=12'} @@ -2087,6 +2668,15 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + eslint-config-prettier@8.10.0: + resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-import-resolver-node@0.3.7: + resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} + eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} @@ -2124,6 +2714,12 @@ packages: eslint-import-resolver-webpack: optional: true + eslint-plugin-es@3.0.1: + resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' + eslint-plugin-import@2.31.0: resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} engines: {node: '>=4'} @@ -2134,28 +2730,81 @@ packages: '@typescript-eslint/parser': optional: true + eslint-plugin-jest-dom@4.0.3: + resolution: {integrity: sha512-9j+n8uj0+V0tmsoS7bYC7fLhQmIvjRqRYEcbDSi+TKPsTThLLXCyj5swMSSf/hTleeMktACnn+HFqXBr5gbcbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6', yarn: '>=1'} + peerDependencies: + eslint: ^6.8.0 || ^7.0.0 || ^8.0.0 + + eslint-plugin-jest@26.9.0: + resolution: {integrity: sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + jest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + jest: + optional: true + eslint-plugin-jsx-a11y@6.10.2: resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} engines: {node: '>=4.0'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + eslint-plugin-node@11.1.0: + resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=5.16.0' + eslint-plugin-react-hooks@4.6.2: resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - eslint-plugin-react@7.37.4: - resolution: {integrity: sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==} + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + eslint-plugin-testing-library@5.11.1: + resolution: {integrity: sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} + peerDependencies: + eslint: ^7.5.0 || ^8.0.0 + + eslint-plugin-turbo@2.5.3: + resolution: {integrity: sha512-DlXZd+LgpDlxH/6IsiAXLhy82x0jeJDm0XBEqP6Le08uy0HBQkjCUt7SmXNp8esAtX9RYe6oDClbNbmI1jtK5g==} + peerDependencies: + eslint: '>6.6.0' + turbo: '>2.0.0' + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-utils@2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + + eslint-visitor-keys@1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + + eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2173,6 +2822,7 @@ packages: esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} + hasBin: true esquery@1.6.0: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} @@ -2182,6 +2832,10 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -2279,6 +2933,9 @@ packages: picomatch: optional: true + fflate@0.4.8: + resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2558,6 +3215,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -2787,6 +3445,10 @@ packages: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2796,6 +3458,7 @@ packages: js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} @@ -2859,9 +3522,69 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} + lightningcss-darwin-arm64@1.30.1: + resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.1: + resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.1: + resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.1: + resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.1: + resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.1: + resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.1: + resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.1: + resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.1: + resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.1: + resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.1: + resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} + engines: {node: '>= 12.0.0'} lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} @@ -2920,6 +3643,7 @@ packages: loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -2943,8 +3667,12 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} @@ -3190,6 +3918,10 @@ packages: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} + minizlib@3.0.2: + resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==} + engines: {node: '>= 18'} + mixme@0.5.10: resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} engines: {node: '>= 8.0.0'} @@ -3202,6 +3934,11 @@ packages: engines: {node: '>=10'} hasBin: true + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + mlly@1.7.4: resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} @@ -3226,11 +3963,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -3239,6 +3973,9 @@ packages: engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} hasBin: true + natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -3317,14 +4054,14 @@ packages: resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} engines: {node: '>= 6'} - object-hash@3.0.0: - resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} - engines: {node: '>= 6'} - object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -3333,8 +4070,8 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} engines: {node: '>= 0.4'} object.fromentries@2.0.8: @@ -3516,10 +4253,6 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} - pirates@4.0.7: - resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} - engines: {node: '>= 6'} - pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -3543,21 +4276,15 @@ packages: postcss-functions@3.0.0: resolution: {integrity: sha512-N5yWXWKA+uhpLQ9ZhBRl2bIAdM6oVJYpDojuI1nF2SzXBimJcdjFwiAouBVbO5VuOF3qA6BSFWFc3wXbbj72XQ==} - postcss-import@15.1.0: - resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} - engines: {node: '>=14.0.0'} + postcss-import@16.1.0: + resolution: {integrity: sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==} + engines: {node: '>=18.0.0'} peerDependencies: postcss: ^8.0.0 postcss-js@2.0.3: resolution: {integrity: sha512-zS59pAk3deu6dVHyrGqmC3oDXBdNdajk4k1RyxeVXCrcEDBUBHoIhE4QTsmhxgzXxsaqFDAkUZfmMa5f/N/79w==} - postcss-js@4.0.1: - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} - engines: {node: ^12 || ^14 || >= 16} - peerDependencies: - postcss: ^8.4.21 - postcss-load-config@4.0.2: resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} engines: {node: '>= 14'} @@ -3570,6 +4297,19 @@ packages: ts-node: optional: true + postcss-loader@8.1.1: + resolution: {integrity: sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + postcss-modules-extract-imports@3.1.0: resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} engines: {node: ^10 || ^12 || >= 14} @@ -3602,12 +4342,6 @@ packages: postcss-nested@4.2.3: resolution: {integrity: sha512-rOv0W1HquRCamWy2kFl3QazJMMe1ku6rCFoAAH+9AcxdbpDeBr6k968MLWuLjvjMcGEip01ak09hKOEgpK9hvw==} - postcss-nested@6.2.0: - resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.2.14 - postcss-selector-parser@6.0.10: resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} engines: {node: '>=4'} @@ -3642,6 +4376,20 @@ packages: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} + posthog-js@1.246.0: + resolution: {integrity: sha512-5lN/UMqDfxsLeSnT3LsY4P+eD1H+P9qxgN/iUk473LmhCM7IV8TAfdjJj23nnXk/euGNQtvyINYoD2DG+d4eEw==} + peerDependencies: + '@rrweb/types': 2.0.0-alpha.17 + rrweb-snapshot: 2.0.0-alpha.17 + peerDependenciesMeta: + '@rrweb/types': + optional: true + rrweb-snapshot: + optional: true + + preact@10.26.7: + resolution: {integrity: sha512-43xS+QYc1X1IPbw03faSgY6I6OYWcLrJRv3hU0+qMOfh/XCHcP0MX2CVjNARYR2cC/guu975sta4OcjlczxD7g==} + preferred-pm@3.1.4: resolution: {integrity: sha512-lEHd+yEm22jXdCphDrkvIJQU66EuLojPPtvZkpKIkiD+l0DMThF/niqZKJSoU8Vl7iuvtmzyMhir9LdVy5WMnA==} engines: {node: '>=10'} @@ -3650,26 +4398,27 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier-plugin-tailwindcss@0.3.0: - resolution: {integrity: sha512-009/Xqdy7UmkcTBpwlq7jsViDqXAYSOMLDrHAdTMlVZOrKfM2o9Ci7EMWTMZ7SkKBFTG04UM9F9iM2+4i6boDA==} - engines: {node: '>=12.17.0'} + prettier-plugin-tailwindcss@0.6.11: + resolution: {integrity: sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==} + engines: {node: '>=14.21.3'} peerDependencies: '@ianvs/prettier-plugin-sort-imports': '*' '@prettier/plugin-pug': '*' '@shopify/prettier-plugin-liquid': '*' - '@shufo/prettier-plugin-blade': '*' '@trivago/prettier-plugin-sort-imports': '*' - prettier: '>=2.2.0' + '@zackad/prettier-plugin-twig': '*' + prettier: ^3.0 prettier-plugin-astro: '*' prettier-plugin-css-order: '*' prettier-plugin-import-sort: '*' prettier-plugin-jsdoc: '*' prettier-plugin-marko: '*' + prettier-plugin-multiline-arrays: '*' prettier-plugin-organize-attributes: '*' prettier-plugin-organize-imports: '*' + prettier-plugin-sort-imports: '*' prettier-plugin-style-order: '*' prettier-plugin-svelte: '*' - prettier-plugin-twig-melody: '*' peerDependenciesMeta: '@ianvs/prettier-plugin-sort-imports': optional: true @@ -3677,10 +4426,10 @@ packages: optional: true '@shopify/prettier-plugin-liquid': optional: true - '@shufo/prettier-plugin-blade': - optional: true '@trivago/prettier-plugin-sort-imports': optional: true + '@zackad/prettier-plugin-twig': + optional: true prettier-plugin-astro: optional: true prettier-plugin-css-order: @@ -3691,16 +4440,18 @@ packages: optional: true prettier-plugin-marko: optional: true + prettier-plugin-multiline-arrays: + optional: true prettier-plugin-organize-attributes: optional: true prettier-plugin-organize-imports: optional: true + prettier-plugin-sort-imports: + optional: true prettier-plugin-style-order: optional: true prettier-plugin-svelte: optional: true - prettier-plugin-twig-melody: - optional: true prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} @@ -3710,6 +4461,11 @@ packages: prettier@3.5.3: resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} engines: {node: '>=14'} + hasBin: true + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} pretty-hrtime@1.0.3: resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} @@ -3719,6 +4475,11 @@ packages: resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==} engines: {node: '>=10'} + prism-react-renderer@2.4.1: + resolution: {integrity: sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig==} + peerDependencies: + react: '>=16.0.0' + prisma@5.4.1: resolution: {integrity: sha512-op9PmU8Bcw5dNAas82wBYTG0yHnpq9/O3bhxbDBrNzwZTwBqsVCxxYRLf6wHNh9HVaDGhgjjHlu1+BcW8qdnBg==} engines: {node: '>=16.13'} @@ -3803,6 +4564,9 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} @@ -3865,6 +4629,10 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} + regexpp@3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + remark-frontmatter@4.0.1: resolution: {integrity: sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==} @@ -3881,6 +4649,30 @@ packages: remark-rehype@10.1.0: resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} + remix-auth-google@2.0.0: + resolution: {integrity: sha512-qP38N1ZJADz+HlH2lrEn/rSL6m5Dwcnz8xUFDhbHecDMl9FU/UpkUx3w8jj5XhNSnkSue/GWT+p7OEkatgbXNA==} + peerDependencies: + '@remix-run/server-runtime': ^2.0.1 + remix-auth: ^3.2.1 + + remix-auth-oauth2@1.11.2: + resolution: {integrity: sha512-5ORP+LMi5CVCA/Wb8Z+FCAJ73Uiy4uyjEzhlVwNBfdAkPOnfxzoi+q/pY/CrueYv3OniCXRM35ZYqkVi3G1UPw==} + peerDependencies: + '@remix-run/server-runtime': ^1.0.0 || ^2.0.0 + remix-auth: ^3.6.0 + + remix-auth@3.7.0: + resolution: {integrity: sha512-2QVjp2nJVaYxuFBecMQwzixCO7CLSssttLBU5eVlNcNlVeNMmY1g7OkmZ1Ogw9sBcoMXZ18J7xXSK0AISVFcfQ==} + peerDependencies: + '@remix-run/react': ^1.0.0 || ^2.0.0 + '@remix-run/server-runtime': ^1.0.0 || ^2.0.0 + + remix-themes@1.6.1: + resolution: {integrity: sha512-wqJyNKJ2hiOweycQzsAk7CZm+2mKNAbW2QZcX0riw52XepAxf9R2v8NYyeUz+uWmb3Fulyi71s4aipNRTxCysw==} + peerDependencies: + '@remix-run/react': '>= 1' + '@remix-run/server-runtime': '>= 1' + remix-typedjson@0.3.1: resolution: {integrity: sha512-XaLU3slWaUXTWPQe6u5rX4xJuqr665+wk1mRmepFu5Hn4DTP9V0zGOkCqCphCExxZ2Kqg5u+uZbas6AZRaxQzA==} peerDependencies: @@ -3888,6 +4680,39 @@ packages: '@remix-run/server-runtime': ^1.16.0 || ^2.0 react: ^17.0.2 || ^18.0.0 + remix-utils@7.7.0: + resolution: {integrity: sha512-J8NhP044nrNIam/xOT1L9a4RQ9FSaA2wyrUwmN8ZT+c/+CdAAf70yfaLnvMyKcV5U+8BcURQ/aVbth77sT6jGA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@remix-run/cloudflare': ^2.0.0 + '@remix-run/node': ^2.0.0 + '@remix-run/react': ^2.0.0 + '@remix-run/router': ^1.7.2 + crypto-js: ^4.1.1 + intl-parse-accept-language: ^1.0.0 + is-ip: ^5.0.1 + react: ^18.0.0 + zod: ^3.22.4 + peerDependenciesMeta: + '@remix-run/cloudflare': + optional: true + '@remix-run/node': + optional: true + '@remix-run/react': + optional: true + '@remix-run/router': + optional: true + crypto-js: + optional: true + intl-parse-accept-language: + optional: true + is-ip: + optional: true + react: + optional: true + zod: + optional: true + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -3898,6 +4723,10 @@ packages: require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + requireindex@1.2.0: + resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} + engines: {node: '>=0.10.5'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -3916,9 +4745,11 @@ packages: resolve@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} + hasBin: true resolve@2.0.0-next.5: resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} @@ -3984,10 +4815,12 @@ packages: semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true - semver@7.7.1: - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} engines: {node: '>=10'} + hasBin: true send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} @@ -4116,6 +4949,10 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + stream-shift@1.0.3: resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} @@ -4195,11 +5032,6 @@ packages: style-to-object@0.4.4: resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} - sucrase@3.35.0: - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -4216,19 +5048,19 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tailwind-merge@1.14.0: - resolution: {integrity: sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==} + tailwind-merge@2.6.0: + resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==} - tailwind-scrollbar-hide@1.3.1: - resolution: {integrity: sha512-eUAvPTltKnAGHbCBRpOk5S7+UZTkFZgDKmZLZ6jZXXs4V7mRXvwshBjeMwrv3vmiWqm3IGEDFVKzUSm1JuoXKw==} + tailwind-scrollbar-hide@2.0.0: + resolution: {integrity: sha512-lqiIutHliEiODwBRHy4G2+Tcayo2U7+3+4frBmoMETD72qtah+XhOk5XcPzC1nJvXhXUdfl2ajlMhUc2qC6CIg==} peerDependencies: tailwindcss: '>=3.0.0 || >= 4.0.0 || >= 4.0.0-beta.8 || >= 4.0.0-alpha.20' - tailwind-scrollbar@3.1.0: - resolution: {integrity: sha512-pmrtDIZeHyu2idTejfV59SbaJyvp1VRjYxAjZBH0jnyrPRo6HL1kD5Glz8VPagasqr6oAx6M05+Tuw429Z8jxg==} + tailwind-scrollbar@4.0.2: + resolution: {integrity: sha512-wAQiIxAPqk0MNTPptVe/xoyWi27y+NRGnTwvn4PQnbvB9kp8QUBiGl/wsfoVBHnQxTmhXJSNt9NHTmcz9EivFA==} engines: {node: '>=12.13.0'} peerDependencies: - tailwindcss: 3.x + tailwindcss: 4.x tailwindcss-animate@1.0.7: resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} @@ -4243,10 +5075,12 @@ packages: engines: {node: '>=8.9.0'} hasBin: true - tailwindcss@3.4.1: - resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==} - engines: {node: '>=14.0.0'} - hasBin: true + tailwindcss@4.1.7: + resolution: {integrity: sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==} + + tapable@2.2.2: + resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==} + engines: {node: '>=6'} tar-fs@2.1.3: resolution: {integrity: sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==} @@ -4259,6 +5093,10 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + tar@7.4.3: + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + engines: {node: '>=18'} + term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -4266,16 +5104,12 @@ packages: text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - - thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + tinyglobby@0.2.14: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} @@ -4314,23 +5148,6 @@ packages: peerDependencies: typescript: '>=4.2.0' - ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - - ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - tsconfck@3.1.6: resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} engines: {node: ^18 || >=20} @@ -4348,9 +5165,18 @@ packages: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsutils@3.21.0: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + tty-table@4.2.3: resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} engines: {node: '>=8.0.0'} @@ -4413,6 +5239,10 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -4433,9 +5263,15 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typescript@5.8.2: - resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} engines: {node: '>=14.17'} + hasBin: true + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true ufo@1.6.1: resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} @@ -4520,14 +5356,19 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + uvu@0.5.6: resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} engines: {node: '>=8'} hasBin: true - v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - valibot@0.41.0: resolution: {integrity: sha512-igDBb8CTYr8YTQlOKgaN9nSS0Be7z+WRuaeYqGf3Cjz3aKmSnqEmYnkfVjzIuumGqfHpa3fLIvMEAfhrpqN8ng==} peerDependencies: @@ -4652,6 +5493,9 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} + web-vitals@4.2.4: + resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -4677,8 +5521,8 @@ packages: resolution: {integrity: sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==} engines: {node: '>=8.15'} - which-typed-array@1.1.18: - resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} engines: {node: '>= 0.4'} which@1.3.1: @@ -4688,6 +5532,7 @@ packages: which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} + hasBin: true which@3.0.1: resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} @@ -4745,6 +5590,10 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + yaml@2.8.0: resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} engines: {node: '>= 14.6'} @@ -4766,10 +5615,6 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -4804,20 +5649,20 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.27.2': {} + '@babel/compat-data@7.27.3': {} - '@babel/core@7.27.1': + '@babel/core@7.27.3': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.1 + '@babel/generator': 7.27.3 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) - '@babel/helpers': 7.27.1 - '@babel/parser': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.3) + '@babel/helpers': 7.27.3 + '@babel/parser': 7.27.3 '@babel/template': 7.27.2 - '@babel/traverse': 7.27.1 - '@babel/types': 7.27.1 + '@babel/traverse': 7.27.3 + '@babel/types': 7.27.3 convert-source-map: 2.0.0 debug: 4.4.1 gensync: 1.0.0-beta.2 @@ -4826,81 +5671,89 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.27.1': + '@babel/eslint-parser@7.27.1(@babel/core@7.27.3)(eslint@8.57.1)': dependencies: - '@babel/parser': 7.27.2 - '@babel/types': 7.27.1 + '@babel/core': 7.27.3 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 + eslint: 8.57.1 + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + + '@babel/generator@7.27.3': + dependencies: + '@babel/parser': 7.27.3 + '@babel/types': 7.27.3 '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.0.2 - '@babel/helper-annotate-as-pure@7.27.1': + '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.27.1 + '@babel/types': 7.27.3 '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.27.2 + '@babel/compat-data': 7.27.3 '@babel/helper-validator-option': 7.27.1 browserslist: 4.24.5 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.27.1)': + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.27.1 - '@babel/helper-annotate-as-pure': 7.27.1 + '@babel/core': 7.27.3 + '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.1) + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.3) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.27.1 + '@babel/traverse': 7.27.3 semver: 6.3.1 transitivePeerDependencies: - supports-color '@babel/helper-member-expression-to-functions@7.27.1': dependencies: - '@babel/traverse': 7.27.1 - '@babel/types': 7.27.1 + '@babel/traverse': 7.27.3 + '@babel/types': 7.27.3 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.27.1 - '@babel/types': 7.27.1 + '@babel/traverse': 7.27.3 + '@babel/types': 7.27.3 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.27.1(@babel/core@7.27.1)': + '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.27.1 + '@babel/core': 7.27.3 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.27.1 + '@babel/traverse': 7.27.3 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.27.1 + '@babel/types': 7.27.3 '@babel/helper-plugin-utils@7.27.1': {} - '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.1)': + '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.27.1 + '@babel/core': 7.27.3 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.27.1 + '@babel/traverse': 7.27.3 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.27.1 - '@babel/types': 7.27.1 + '@babel/traverse': 7.27.3 + '@babel/types': 7.27.3 transitivePeerDependencies: - supports-color @@ -4910,88 +5763,129 @@ snapshots: '@babel/helper-validator-option@7.27.1': {} - '@babel/helpers@7.27.1': + '@babel/helpers@7.27.3': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.27.1 + '@babel/types': 7.27.3 - '@babel/parser@7.27.2': + '@babel/parser@7.27.3': dependencies: - '@babel/types': 7.27.1 + '@babel/types': 7.27.3 - '@babel/plugin-syntax-decorators@7.27.1(@babel/core@7.27.1)': + '@babel/plugin-syntax-decorators@7.27.1(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.27.1 + '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.1)': + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.27.1 + '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.1)': + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.27.1 + '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.27.1)': + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.27.1 - '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) + '@babel/core': 7.27.3 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.3) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-typescript@7.27.1(@babel/core@7.27.1)': + '@babel/plugin-transform-react-display-name@7.27.1(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.27.1 - '@babel/helper-annotate-as-pure': 7.27.1 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/core': 7.27.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.27.3)': + dependencies: + '@babel/core': 7.27.3 + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.27.3) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.27.3)': + dependencies: + '@babel/core': 7.27.3 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.3) + '@babel/types': 7.27.3 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.27.3)': + dependencies: + '@babel/core': 7.27.3 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-typescript@7.27.1(@babel/core@7.27.3)': + dependencies: + '@babel/core': 7.27.3 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.3) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.3) transitivePeerDependencies: - supports-color - '@babel/preset-typescript@7.27.1(@babel/core@7.27.1)': + '@babel/preset-react@7.27.1(@babel/core@7.27.3)': dependencies: - '@babel/core': 7.27.1 + '@babel/core': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.1) - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.27.1) - '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-transform-react-display-name': 7.27.1(@babel/core@7.27.3) + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.27.3) + '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.27.3) + '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.27.3) transitivePeerDependencies: - supports-color - '@babel/runtime@7.27.1': {} + '@babel/preset-typescript@7.27.1(@babel/core@7.27.3)': + dependencies: + '@babel/core': 7.27.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.3) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.27.3) + '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.3) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.27.3': {} '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.27.2 - '@babel/types': 7.27.1 + '@babel/parser': 7.27.3 + '@babel/types': 7.27.3 - '@babel/traverse@7.27.1': + '@babel/traverse@7.27.3': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.1 - '@babel/parser': 7.27.2 + '@babel/generator': 7.27.3 + '@babel/parser': 7.27.3 '@babel/template': 7.27.2 - '@babel/types': 7.27.1 + '@babel/types': 7.27.3 debug: 4.4.1 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.27.1': + '@babel/types@7.27.3': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 '@changesets/apply-release-plan@6.1.4': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@changesets/config': 2.3.1 '@changesets/get-version-range-type': 0.3.2 '@changesets/git': 2.0.0 @@ -5003,16 +5897,16 @@ snapshots: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.7.1 + semver: 7.7.2 '@changesets/assemble-release-plan@5.2.4': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@changesets/errors': 0.1.4 '@changesets/get-dependents-graph': 1.3.6 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 - semver: 7.7.1 + semver: 7.7.2 '@changesets/changelog-git@0.1.14': dependencies: @@ -5020,7 +5914,7 @@ snapshots: '@changesets/cli@2.26.2': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@changesets/apply-release-plan': 6.1.4 '@changesets/assemble-release-plan': 5.2.4 '@changesets/changelog-git': 0.1.14 @@ -5049,7 +5943,7 @@ snapshots: p-limit: 2.3.0 preferred-pm: 3.1.4 resolve-from: 5.0.0 - semver: 7.7.1 + semver: 7.7.2 spawndamnit: 2.0.0 term-size: 2.2.1 tty-table: 4.2.3 @@ -5074,7 +5968,7 @@ snapshots: '@manypkg/get-packages': 1.1.3 chalk: 2.4.2 fs-extra: 7.0.1 - semver: 7.7.1 + semver: 7.7.2 '@changesets/get-github-info@0.5.2': dependencies: @@ -5085,7 +5979,7 @@ snapshots: '@changesets/get-release-plan@3.0.17': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@changesets/assemble-release-plan': 5.2.4 '@changesets/config': 2.3.1 '@changesets/pre': 1.0.14 @@ -5097,7 +5991,7 @@ snapshots: '@changesets/git@2.0.0': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 @@ -5116,7 +6010,7 @@ snapshots: '@changesets/pre@1.0.14': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 @@ -5124,7 +6018,7 @@ snapshots: '@changesets/read@0.5.9': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@changesets/git': 2.0.0 '@changesets/logger': 0.0.5 '@changesets/parse': 0.3.16 @@ -5139,17 +6033,12 @@ snapshots: '@changesets/write@0.2.3': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@changesets/types': 5.2.1 fs-extra: 7.0.1 human-id: 1.0.2 prettier: 2.8.8 - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - optional: true - '@emnapi/core@1.4.3': dependencies: '@emnapi/wasi-threads': 1.0.2 @@ -5183,6 +6072,9 @@ snapshots: '@esbuild/android-arm64@0.25.5': optional: true + '@esbuild/android-arm@0.15.18': + optional: true + '@esbuild/android-arm@0.17.6': optional: true @@ -5264,6 +6156,9 @@ snapshots: '@esbuild/linux-ia32@0.25.5': optional: true + '@esbuild/linux-loong64@0.15.18': + optional: true + '@esbuild/linux-loong64@0.17.6': optional: true @@ -5427,6 +6322,10 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -5444,24 +6343,18 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping@0.3.9': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - optional: true - '@jspm/core@2.1.0': {} '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -5497,6 +6390,10 @@ snapshots: '@tybys/wasm-util': 0.9.0 optional: true + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + dependencies: + eslint-scope: 5.1.1 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -5513,7 +6410,7 @@ snapshots: '@npmcli/fs@3.1.1': dependencies: - semver: 7.7.1 + semver: 7.7.2 '@npmcli/git@4.1.0': dependencies: @@ -5523,7 +6420,7 @@ snapshots: proc-log: 3.0.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.7.1 + semver: 7.7.2 which: 3.0.1 transitivePeerDependencies: - bluebird @@ -5536,7 +6433,7 @@ snapshots: json-parse-even-better-errors: 3.0.2 normalize-package-data: 5.0.0 proc-log: 3.0.0 - semver: 7.7.1 + semver: 7.7.2 transitivePeerDependencies: - bluebird @@ -5544,6 +6441,8 @@ snapshots: dependencies: which: 3.0.1 + '@opentelemetry/api@1.9.0': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -5557,6 +6456,19 @@ snapshots: '@prisma/engines@5.4.1': {} + '@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.23)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + + '@radix-ui/react-slot@1.2.3(@types/react@18.3.23)(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.23)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.23 + '@remix-run/changelog-github@0.0.5': dependencies: '@changesets/errors': 0.1.4 @@ -5566,30 +6478,30 @@ snapshots: transitivePeerDependencies: - encoding - '@remix-run/dev@2.16.7(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.2))(@remix-run/serve@2.16.7(typescript@5.8.2))(@types/node@22.15.3)(jiti@1.21.7)(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))(typescript@5.8.2)(vite@6.3.5(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0))(yaml@2.8.0)': + '@remix-run/dev@2.16.7(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.7(typescript@5.8.3))(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))(yaml@2.8.0)': dependencies: - '@babel/core': 7.27.1 - '@babel/generator': 7.27.1 - '@babel/parser': 7.27.2 - '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.27.1) - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.1) - '@babel/preset-typescript': 7.27.1(@babel/core@7.27.1) - '@babel/traverse': 7.27.1 - '@babel/types': 7.27.1 + '@babel/core': 7.27.3 + '@babel/generator': 7.27.3 + '@babel/parser': 7.27.3 + '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.27.3) + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.3) + '@babel/preset-typescript': 7.27.1(@babel/core@7.27.3) + '@babel/traverse': 7.27.3 + '@babel/types': 7.27.3 '@mdx-js/mdx': 2.3.0 '@npmcli/package-json': 4.0.1 - '@remix-run/node': 2.16.7(typescript@5.8.2) - '@remix-run/react': 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.2) + '@remix-run/node': 2.16.7(typescript@5.8.3) + '@remix-run/react': 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) '@remix-run/router': 1.23.0 - '@remix-run/server-runtime': 2.16.7(typescript@5.8.2) + '@remix-run/server-runtime': 2.16.7(typescript@5.8.3) '@types/mdx': 2.0.13 - '@vanilla-extract/integration': 6.5.0(@types/node@22.15.3) + '@vanilla-extract/integration': 6.5.0(@types/node@22.15.21)(lightningcss@1.30.1) arg: 5.0.2 cacache: 17.1.4 chalk: 4.1.2 chokidar: 3.6.0 cross-spawn: 7.0.6 - dotenv: 16.0.3 + dotenv: 16.5.0 es-module-lexer: 1.7.0 esbuild: 0.17.6 esbuild-plugins-node-modules-polyfill: 1.7.0(esbuild@0.17.6) @@ -5611,24 +6523,24 @@ snapshots: pidtree: 0.6.0 postcss: 8.5.3 postcss-discard-duplicates: 5.1.0(postcss@8.5.3) - postcss-load-config: 4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)) + postcss-load-config: 4.0.2(postcss@8.5.3) postcss-modules: 6.0.1(postcss@8.5.3) prettier: 2.8.8 pretty-ms: 7.0.1 react-refresh: 0.14.2 remark-frontmatter: 4.0.1 remark-mdx-frontmatter: 1.1.1 - semver: 7.7.1 + semver: 7.7.2 set-cookie-parser: 2.7.1 tar-fs: 2.1.3 tsconfig-paths: 4.2.0 - valibot: 0.41.0(typescript@5.8.2) - vite-node: 3.1.4(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0) + valibot: 0.41.0(typescript@5.8.3) + vite-node: 3.1.4(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) ws: 7.5.10 optionalDependencies: - '@remix-run/serve': 2.16.7(typescript@5.8.2) - typescript: 5.8.2 - vite: 6.3.5(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0) + '@remix-run/serve': 2.16.7(typescript@5.8.3) + typescript: 5.8.3 + vite: 6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -5648,16 +6560,57 @@ snapshots: - utf-8-validate - yaml - '@remix-run/express@2.16.7(express@4.21.2)(typescript@5.8.2)': + '@remix-run/eslint-config@2.16.7(eslint@8.57.1)(react@18.3.1)(typescript@5.8.3)': dependencies: - '@remix-run/node': 2.16.7(typescript@5.8.2) + '@babel/core': 7.27.3 + '@babel/eslint-parser': 7.27.1(@babel/core@7.27.3)(eslint@8.57.1) + '@babel/preset-react': 7.27.1(@babel/core@7.27.3) + '@rushstack/eslint-patch': 1.11.0 + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.8.3) + eslint: 8.57.1 + eslint-import-resolver-node: 0.3.7 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + eslint-plugin-jest: 26.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3) + eslint-plugin-jest-dom: 4.0.3(eslint@8.57.1) + eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) + eslint-plugin-node: 11.1.0(eslint@8.57.1) + eslint-plugin-react: 7.37.5(eslint@8.57.1) + eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) + eslint-plugin-testing-library: 5.11.1(eslint@8.57.1)(typescript@5.8.3) + react: 18.3.1 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - jest + - supports-color + + '@remix-run/express@2.16.7(express@4.21.2)(typescript@5.8.3)': + dependencies: + '@remix-run/node': 2.16.7(typescript@5.8.3) express: 4.21.2 optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 - '@remix-run/node@2.16.7(typescript@5.8.2)': + '@remix-run/node@2.1.0(typescript@5.8.3)': dependencies: - '@remix-run/server-runtime': 2.16.7(typescript@5.8.2) + '@remix-run/server-runtime': 2.1.0(typescript@5.8.3) + '@remix-run/web-fetch': 4.4.2 + '@remix-run/web-file': 3.1.0 + '@remix-run/web-stream': 1.1.0 + '@web3-storage/multipart-parser': 1.0.0 + cookie-signature: 1.2.2 + source-map-support: 0.5.21 + stream-slice: 0.1.2 + optionalDependencies: + typescript: 5.8.3 + + '@remix-run/node@2.16.7(typescript@5.8.3)': + dependencies: + '@remix-run/server-runtime': 2.16.7(typescript@5.8.3) '@remix-run/web-fetch': 4.4.2 '@web3-storage/multipart-parser': 1.0.0 cookie-signature: 1.2.2 @@ -5665,26 +6618,28 @@ snapshots: stream-slice: 0.1.2 undici: 6.21.3 optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 - '@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.2)': + '@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)': dependencies: '@remix-run/router': 1.23.0 - '@remix-run/server-runtime': 2.16.7(typescript@5.8.2) + '@remix-run/server-runtime': 2.16.7(typescript@5.8.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-router: 6.30.0(react@18.3.1) react-router-dom: 6.30.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) turbo-stream: 2.4.1 optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 + + '@remix-run/router@1.10.0': {} '@remix-run/router@1.23.0': {} - '@remix-run/serve@2.16.7(typescript@5.8.2)': + '@remix-run/serve@2.16.7(typescript@5.8.3)': dependencies: - '@remix-run/express': 2.16.7(express@4.21.2)(typescript@5.8.2) - '@remix-run/node': 2.16.7(typescript@5.8.2) + '@remix-run/express': 2.16.7(express@4.21.2)(typescript@5.8.3) + '@remix-run/node': 2.16.7(typescript@5.8.3) chokidar: 3.6.0 compression: 1.8.0 express: 4.21.2 @@ -5695,7 +6650,18 @@ snapshots: - supports-color - typescript - '@remix-run/server-runtime@2.16.7(typescript@5.8.2)': + '@remix-run/server-runtime@2.1.0(typescript@5.8.3)': + dependencies: + '@remix-run/router': 1.10.0 + '@types/cookie': 0.4.1 + '@web3-storage/multipart-parser': 1.0.0 + cookie: 0.4.2 + set-cookie-parser: 2.7.1 + source-map: 0.7.4 + optionalDependencies: + typescript: 5.8.3 + + '@remix-run/server-runtime@2.16.7(typescript@5.8.3)': dependencies: '@remix-run/router': 1.23.0 '@types/cookie': 0.6.0 @@ -5705,7 +6671,24 @@ snapshots: source-map: 0.7.4 turbo-stream: 2.4.1 optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 + + '@remix-run/testing@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)': + dependencies: + '@remix-run/node': 2.16.7(typescript@5.8.3) + '@remix-run/react': 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) + '@remix-run/router': 1.23.0 + react: 18.3.1 + react-router-dom: 6.30.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - react-dom + + '@remix-run/v1-meta@0.1.3(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3))': + dependencies: + '@remix-run/react': 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) + '@remix-run/server-runtime': 2.16.7(typescript@5.8.3) '@remix-run/web-blob@3.1.0': dependencies: @@ -5797,34 +6780,114 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)))': - dependencies: - tailwindcss: 3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)) + '@rushstack/eslint-patch@1.11.0': {} - '@tailwindcss/forms@0.5.10(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)))': + '@tailwindcss/container-queries@0.1.1(tailwindcss@4.1.7)': + dependencies: + tailwindcss: 4.1.7 + + '@tailwindcss/forms@0.5.10(tailwindcss@4.1.7)': dependencies: mini-svg-data-uri: 1.4.4 - tailwindcss: 3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)) + tailwindcss: 4.1.7 - '@tailwindcss/typography@0.5.16(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)))': + '@tailwindcss/node@4.1.7': + dependencies: + '@ampproject/remapping': 2.3.0 + enhanced-resolve: 5.18.1 + jiti: 2.4.2 + lightningcss: 1.30.1 + magic-string: 0.30.17 + source-map-js: 1.2.1 + tailwindcss: 4.1.7 + + '@tailwindcss/oxide-android-arm64@4.1.7': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.7': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.7': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.7': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.7': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.7': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.7': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.7': + optional: true + + '@tailwindcss/oxide@4.1.7': + dependencies: + detect-libc: 2.0.4 + tar: 7.4.3 + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.7 + '@tailwindcss/oxide-darwin-arm64': 4.1.7 + '@tailwindcss/oxide-darwin-x64': 4.1.7 + '@tailwindcss/oxide-freebsd-x64': 4.1.7 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.7 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.7 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.7 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.7 + '@tailwindcss/oxide-linux-x64-musl': 4.1.7 + '@tailwindcss/oxide-wasm32-wasi': 4.1.7 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.7 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.7 + + '@tailwindcss/postcss@4.1.7': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.1.7 + '@tailwindcss/oxide': 4.1.7 + postcss: 8.5.3 + tailwindcss: 4.1.7 + + '@tailwindcss/typography@0.5.16(tailwindcss@4.1.7)': dependencies: lodash.castarray: 4.4.0 lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 - tailwindcss: 3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)) + tailwindcss: 4.1.7 - '@tsconfig/node10@1.0.11': - optional: true + '@tailwindcss/vite@4.1.7(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))': + dependencies: + '@tailwindcss/node': 4.1.7 + '@tailwindcss/oxide': 4.1.7 + tailwindcss: 4.1.7 + vite: 6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) - '@tsconfig/node12@1.0.11': - optional: true - - '@tsconfig/node14@1.0.3': - optional: true - - '@tsconfig/node16@1.0.4': - optional: true + '@testing-library/dom@8.20.1': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/runtime': 7.27.3 + '@types/aria-query': 5.0.4 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 '@tybys/wasm-util@0.9.0': dependencies: @@ -5835,6 +6898,24 @@ snapshots: dependencies: '@types/estree': 1.0.7 + '@types/aria-query@5.0.4': {} + + '@types/body-parser@1.19.5': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.15.21 + + '@types/compression@1.8.0': + dependencies: + '@types/express': 4.17.22 + '@types/node': 22.15.21 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 22.15.21 + + '@types/cookie@0.4.1': {} + '@types/cookie@0.6.0': {} '@types/debug@4.1.12': @@ -5847,10 +6928,26 @@ snapshots: '@types/estree@1.0.7': {} + '@types/express-serve-static-core@4.19.6': + dependencies: + '@types/node': 22.15.21 + '@types/qs': 6.14.0 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express@4.17.22': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.14.0 + '@types/serve-static': 1.15.7 + '@types/hast@2.3.10': dependencies: '@types/unist': 2.0.11 + '@types/http-errors@2.0.4': {} + '@types/is-ci@3.0.4': dependencies: ci-info: 3.9.0 @@ -5865,86 +6962,173 @@ snapshots: '@types/mdx@2.0.13': {} + '@types/mime@1.3.5': {} + '@types/minimist@1.2.5': {} + '@types/morgan@1.9.9': + dependencies: + '@types/node': 22.15.21 + '@types/ms@2.1.0': {} '@types/node@12.20.55': {} - '@types/node@22.15.3': + '@types/node@22.15.21': dependencies: undici-types: 6.21.0 '@types/normalize-package-data@2.4.4': {} + '@types/prismjs@1.26.5': {} + '@types/prop-types@15.7.14': {} - '@types/react-dom@18.3.7(@types/react@18.3.22)': - dependencies: - '@types/react': 18.3.22 + '@types/qs@6.14.0': {} - '@types/react@18.3.22': + '@types/range-parser@1.2.7': {} + + '@types/react-dom@18.3.7(@types/react@18.3.23)': + dependencies: + '@types/react': 18.3.23 + + '@types/react@18.3.23': dependencies: '@types/prop-types': 15.7.14 csstype: 3.1.3 '@types/semver@7.7.0': {} + '@types/send@0.17.4': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.15.21 + + '@types/serve-static@1.15.7': + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 22.15.21 + '@types/send': 0.17.4 + '@types/unist@2.0.11': {} - '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1)(typescript@5.8.2)': + '@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.2) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.8.3) + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) + debug: 4.4.1 + eslint: 8.57.1 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare-lite: 1.4.0 + semver: 7.7.2 + tsutils: 3.21.0(typescript@5.8.3) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.3) '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.8.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.8.2) + '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.8.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.8.3) '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.4.1 eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - semver: 7.7.1 - ts-api-utils: 1.4.3(typescript@5.8.2) + semver: 7.7.2 + ts-api-utils: 1.4.3(typescript@5.8.3) optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2)': + '@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.3) + debug: 4.4.1 + eslint: 8.57.1 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3)': dependencies: '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.8.2) + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.8.3) '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.4.1 eslint: 8.57.1 optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 transitivePeerDependencies: - supports-color + '@typescript-eslint/scope-manager@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + '@typescript-eslint/scope-manager@6.21.0': dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@5.8.2)': + '@typescript-eslint/type-utils@5.62.0(eslint@8.57.1)(typescript@5.8.3)': dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.8.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.8.2) + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.3) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) debug: 4.4.1 eslint: 8.57.1 - ts-api-utils: 1.4.3(typescript@5.8.2) + tsutils: 3.21.0(typescript@5.8.3) optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@5.8.3)': + dependencies: + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.8.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.8.3) + debug: 4.4.1 + eslint: 8.57.1 + ts-api-utils: 1.4.3(typescript@5.8.3) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@5.62.0': {} + '@typescript-eslint/types@6.21.0': {} - '@typescript-eslint/typescript-estree@6.21.0(typescript@5.8.2)': + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.8.3)': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.4.1 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.7.2 + tsutils: 3.21.0(typescript@5.8.3) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@6.21.0(typescript@5.8.3)': dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 @@ -5952,27 +7136,47 @@ snapshots: globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 - semver: 7.7.1 - ts-api-utils: 1.4.3(typescript@5.8.2) + semver: 7.7.2 + ts-api-utils: 1.4.3(typescript@5.8.3) optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.8.2)': + '@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.1) + '@types/json-schema': 7.0.15 + '@types/semver': 7.7.0 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.3) + eslint: 8.57.1 + eslint-scope: 5.1.1 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.8.3)': dependencies: '@eslint-community/eslint-utils': 4.7.0(eslint@8.57.1) '@types/json-schema': 7.0.15 '@types/semver': 7.7.0 '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.8.2) + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.8.3) eslint: 8.57.1 - semver: 7.7.1 + semver: 7.7.2 transitivePeerDependencies: - supports-color - typescript + '@typescript-eslint/visitor-keys@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@6.21.0': dependencies: '@typescript-eslint/types': 6.21.0 @@ -6035,7 +7239,7 @@ snapshots: '@vanilla-extract/babel-plugin-debug-ids@1.2.0': dependencies: - '@babel/core': 7.27.1 + '@babel/core': 7.27.3 transitivePeerDependencies: - supports-color @@ -6056,10 +7260,10 @@ snapshots: transitivePeerDependencies: - babel-plugin-macros - '@vanilla-extract/integration@6.5.0(@types/node@22.15.3)': + '@vanilla-extract/integration@6.5.0(@types/node@22.15.21)(lightningcss@1.30.1)': dependencies: - '@babel/core': 7.27.1 - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.1) + '@babel/core': 7.27.3 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.3) '@vanilla-extract/babel-plugin-debug-ids': 1.2.0 '@vanilla-extract/css': 1.17.2 esbuild: 0.17.6 @@ -6069,8 +7273,8 @@ snapshots: lodash: 4.17.21 mlly: 1.7.4 outdent: 0.8.0 - vite: 5.4.19(@types/node@22.15.3) - vite-node: 1.6.1(@types/node@22.15.3) + vite: 5.4.19(@types/node@22.15.21)(lightningcss@1.30.1) + vite-node: 1.6.1(@types/node@22.15.21)(lightningcss@1.30.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -6111,11 +7315,6 @@ snapshots: acorn-walk@7.2.0: {} - acorn-walk@8.3.4: - dependencies: - acorn: 8.14.1 - optional: true - acorn@7.4.1: {} acorn@8.14.1: {} @@ -6146,18 +7345,15 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.1: {} + ansi-styles@5.2.0: {} - any-promise@1.3.0: {} + ansi-styles@6.2.1: {} anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - arg@4.1.3: - optional: true - arg@5.0.2: {} argparse@1.0.10: @@ -6166,6 +7362,10 @@ snapshots: argparse@2.0.1: {} + aria-query@5.1.3: + dependencies: + deep-equal: 2.2.3 + aria-query@5.3.2: {} array-buffer-byte-length@1.0.2: @@ -6179,7 +7379,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 is-string: 1.1.1 @@ -6190,7 +7390,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -6200,7 +7400,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -6209,21 +7409,21 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-shim-unscopables: 1.1.0 array.prototype.flatmap@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-shim-unscopables: 1.1.0 array.prototype.tosorted@1.1.4: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-errors: 1.3.0 es-shim-unscopables: 1.1.0 @@ -6232,7 +7432,7 @@ snapshots: array-buffer-byte-length: 1.0.2 call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-errors: 1.3.0 get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 @@ -6436,6 +7636,8 @@ snapshots: chownr@2.0.0: {} + chownr@3.0.0: {} + ci-info@3.9.0: {} class-variance-authority@0.7.1: @@ -6490,8 +7692,6 @@ snapshots: comma-separated-tokens@2.0.3: {} - commander@4.1.1: {} - commander@5.1.0: {} compressible@2.0.18: @@ -6528,14 +7728,28 @@ snapshots: cookie-signature@1.2.2: {} + cookie@0.4.2: {} + cookie@0.7.1: {} cookie@0.7.2: {} + core-js@3.42.0: {} + core-util-is@1.0.3: {} - create-require@1.1.1: - optional: true + cosmiconfig@9.0.0(typescript@5.8.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.8.3 + + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.6 cross-spawn@5.1.0: dependencies: @@ -6549,6 +7763,17 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-loader@6.11.0: + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.3) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.3) + postcss-modules-scope: 3.2.1(postcss@8.5.3) + postcss-modules-values: 4.0.0(postcss@8.5.3) + postcss-value-parser: 4.2.0 + semver: 7.7.2 + css-unit-converter@1.1.2: {} css-what@6.1.0: {} @@ -6619,6 +7844,27 @@ snapshots: dedent@1.6.0: {} + deep-equal@2.2.3: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + es-get-iterator: 1.1.3 + get-intrinsic: 1.3.0 + is-arguments: 1.2.0 + is-array-buffer: 3.0.5 + is-date-object: 1.1.0 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.7 + regexp.prototype.flags: 1.5.4 + side-channel: 1.1.0 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + deep-is@0.1.4: {} deep-object-diff@1.1.9: {} @@ -6651,25 +7897,20 @@ snapshots: detect-indent@6.1.0: {} + detect-libc@2.0.4: {} + detective@5.2.1: dependencies: acorn-node: 1.8.2 defined: 1.0.1 minimist: 1.2.8 - didyoumean@1.2.2: {} - - diff@4.0.2: - optional: true - diff@5.2.0: {} dir-glob@3.0.1: dependencies: path-type: 4.0.0 - dlv@1.1.3: {} - doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -6678,8 +7919,21 @@ snapshots: dependencies: esutils: 2.0.3 + dom-accessibility-api@0.5.16: {} + + dotenv-cli@7.4.4: + dependencies: + cross-spawn: 7.0.6 + dotenv: 16.5.0 + dotenv-expand: 10.0.0 + minimist: 1.2.8 + + dotenv-expand@10.0.0: {} + dotenv@16.0.3: {} + dotenv@16.5.0: {} + dotenv@8.6.0: {} dunder-proto@1.0.1: @@ -6713,18 +7967,25 @@ snapshots: dependencies: once: 1.4.0 + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.2 + enquirer@2.4.1: dependencies: ansi-colors: 4.1.3 strip-ansi: 6.0.1 + env-paths@2.2.1: {} + err-code@2.0.3: {} error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - es-abstract@1.23.9: + es-abstract@1.23.10: dependencies: array-buffer-byte-length: 1.0.2 arraybuffer.prototype.slice: 1.0.4 @@ -6776,18 +8037,30 @@ snapshots: typed-array-byte-offset: 1.0.4 typed-array-length: 1.0.7 unbox-primitive: 1.1.0 - which-typed-array: 1.1.18 + which-typed-array: 1.1.19 es-define-property@1.0.1: {} es-errors@1.3.0: {} + es-get-iterator@1.1.3: + dependencies: + call-bind: 1.0.8 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + is-arguments: 1.2.0 + is-map: 2.0.3 + is-set: 2.0.3 + is-string: 1.1.1 + isarray: 2.0.5 + stop-iteration-iterator: 1.1.0 + es-iterator-helpers@1.2.1: dependencies: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-errors: 1.3.0 es-set-tostringtag: 2.1.0 function-bind: 1.1.2 @@ -6824,6 +8097,54 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + esbuild-android-64@0.15.18: + optional: true + + esbuild-android-arm64@0.15.18: + optional: true + + esbuild-darwin-64@0.15.18: + optional: true + + esbuild-darwin-arm64@0.15.18: + optional: true + + esbuild-freebsd-64@0.15.18: + optional: true + + esbuild-freebsd-arm64@0.15.18: + optional: true + + esbuild-linux-32@0.15.18: + optional: true + + esbuild-linux-64@0.15.18: + optional: true + + esbuild-linux-arm64@0.15.18: + optional: true + + esbuild-linux-arm@0.15.18: + optional: true + + esbuild-linux-mips64le@0.15.18: + optional: true + + esbuild-linux-ppc64le@0.15.18: + optional: true + + esbuild-linux-riscv64@0.15.18: + optional: true + + esbuild-linux-s390x@0.15.18: + optional: true + + esbuild-netbsd-64@0.15.18: + optional: true + + esbuild-openbsd-64@0.15.18: + optional: true + esbuild-plugins-node-modules-polyfill@1.7.0(esbuild@0.17.6): dependencies: '@jspm/core': 2.1.0 @@ -6831,6 +8152,43 @@ snapshots: local-pkg: 1.1.1 resolve.exports: 2.0.3 + esbuild-sunos-64@0.15.18: + optional: true + + esbuild-windows-32@0.15.18: + optional: true + + esbuild-windows-64@0.15.18: + optional: true + + esbuild-windows-arm64@0.15.18: + optional: true + + esbuild@0.15.18: + optionalDependencies: + '@esbuild/android-arm': 0.15.18 + '@esbuild/linux-loong64': 0.15.18 + esbuild-android-64: 0.15.18 + esbuild-android-arm64: 0.15.18 + esbuild-darwin-64: 0.15.18 + esbuild-darwin-arm64: 0.15.18 + esbuild-freebsd-64: 0.15.18 + esbuild-freebsd-arm64: 0.15.18 + esbuild-linux-32: 0.15.18 + esbuild-linux-64: 0.15.18 + esbuild-linux-arm: 0.15.18 + esbuild-linux-arm64: 0.15.18 + esbuild-linux-mips64le: 0.15.18 + esbuild-linux-ppc64le: 0.15.18 + esbuild-linux-riscv64: 0.15.18 + esbuild-linux-s390x: 0.15.18 + esbuild-netbsd-64: 0.15.18 + esbuild-openbsd-64: 0.15.18 + esbuild-sunos-64: 0.15.18 + esbuild-windows-32: 0.15.18 + esbuild-windows-64: 0.15.18 + esbuild-windows-arm64: 0.15.18 + esbuild@0.17.6: optionalDependencies: '@esbuild/android-arm': 0.17.6 @@ -6918,6 +8276,18 @@ snapshots: escape-string-regexp@4.0.0: {} + eslint-config-prettier@8.10.0(eslint@8.57.1): + dependencies: + eslint: 8.57.1 + + eslint-import-resolver-node@0.3.7: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 @@ -6937,22 +8307,39 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.7.2 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.2) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.8.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.3) + eslint: 8.57.1 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) + transitivePeerDependencies: + - supports-color + + eslint-plugin-es@3.0.1(eslint@8.57.1): + dependencies: + eslint: 8.57.1 + eslint-utils: 2.1.0 + regexpp: 3.2.0 + + eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -6963,7 +8350,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -6975,12 +8362,58 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.2) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.8.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color + eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.57.1 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jest-dom@4.0.3(eslint@8.57.1): + dependencies: + '@babel/runtime': 7.27.3 + '@testing-library/dom': 8.20.1 + eslint: 8.57.1 + requireindex: 1.2.0 + + eslint-plugin-jest@26.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3): + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) + eslint: 8.57.1 + optionalDependencies: + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3) + transitivePeerDependencies: + - supports-color + - typescript + eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1): dependencies: aria-query: 5.3.2 @@ -7000,11 +8433,21 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 + eslint-plugin-node@11.1.0(eslint@8.57.1): + dependencies: + eslint: 8.57.1 + eslint-plugin-es: 3.0.1(eslint@8.57.1) + eslint-utils: 2.1.0 + ignore: 5.3.2 + minimatch: 3.1.2 + resolve: 1.22.10 + semver: 6.3.1 + eslint-plugin-react-hooks@4.6.2(eslint@8.57.1): dependencies: eslint: 8.57.1 - eslint-plugin-react@7.37.4(eslint@8.57.1): + eslint-plugin-react@7.37.5(eslint@8.57.1): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -7017,7 +8460,7 @@ snapshots: hasown: 2.0.2 jsx-ast-utils: 3.3.5 minimatch: 3.1.2 - object.entries: 1.1.8 + object.entries: 1.1.9 object.fromentries: 2.0.8 object.values: 1.2.1 prop-types: 15.8.1 @@ -7026,11 +8469,38 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-testing-library@5.11.1(eslint@8.57.1)(typescript@5.8.3): + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) + eslint: 8.57.1 + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-turbo@2.5.3(eslint@8.57.1)(turbo@2.5.3): + dependencies: + dotenv: 16.0.3 + eslint: 8.57.1 + turbo: 2.5.3 + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-utils@2.1.0: + dependencies: + eslint-visitor-keys: 1.3.0 + + eslint-visitor-keys@1.3.0: {} + + eslint-visitor-keys@2.1.0: {} + eslint-visitor-keys@3.4.3: {} eslint@8.57.1: @@ -7092,6 +8562,8 @@ snapshots: dependencies: estraverse: 5.3.0 + estraverse@4.3.0: {} + estraverse@5.3.0: {} estree-util-attach-comments@2.1.1: @@ -7133,7 +8605,7 @@ snapshots: eval@0.1.8: dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.21 require-like: 0.1.2 event-target-shim@5.0.1: {} @@ -7226,6 +8698,8 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fflate@0.4.8: {} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -7599,7 +9073,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.1 + semver: 7.7.2 is-callable@1.2.7: {} @@ -7704,7 +9178,7 @@ snapshots: is-typed-array@1.1.15: dependencies: - which-typed-array: 1.1.18 + which-typed-array: 1.1.19 is-unicode-supported@0.1.0: {} @@ -7752,6 +9226,8 @@ snapshots: jiti@1.21.7: {} + jiti@2.4.2: {} + js-tokens@4.0.0: {} js-yaml@3.14.1: @@ -7817,7 +9293,50 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lilconfig@2.1.0: {} + lightningcss-darwin-arm64@1.30.1: + optional: true + + lightningcss-darwin-x64@1.30.1: + optional: true + + lightningcss-freebsd-x64@1.30.1: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.1: + optional: true + + lightningcss-linux-arm64-gnu@1.30.1: + optional: true + + lightningcss-linux-arm64-musl@1.30.1: + optional: true + + lightningcss-linux-x64-gnu@1.30.1: + optional: true + + lightningcss-linux-x64-musl@1.30.1: + optional: true + + lightningcss-win32-arm64-msvc@1.30.1: + optional: true + + lightningcss-win32-x64-msvc@1.30.1: + optional: true + + lightningcss@1.30.1: + dependencies: + detect-libc: 2.0.4 + optionalDependencies: + lightningcss-darwin-arm64: 1.30.1 + lightningcss-darwin-x64: 1.30.1 + lightningcss-freebsd-x64: 1.30.1 + lightningcss-linux-arm-gnueabihf: 1.30.1 + lightningcss-linux-arm64-gnu: 1.30.1 + lightningcss-linux-arm64-musl: 1.30.1 + lightningcss-linux-x64-gnu: 1.30.1 + lightningcss-linux-x64-musl: 1.30.1 + lightningcss-win32-arm64-msvc: 1.30.1 + lightningcss-win32-x64-msvc: 1.30.1 lilconfig@3.1.3: {} @@ -7890,8 +9409,11 @@ snapshots: dependencies: react: 18.3.1 - make-error@1.3.6: - optional: true + lz-string@1.5.0: {} + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 map-obj@1.0.1: {} @@ -8010,7 +9532,7 @@ snapshots: media-query-parser@2.0.2: dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.27.3 media-typer@0.3.0: {} @@ -8319,12 +9841,18 @@ snapshots: minipass: 3.3.6 yallist: 4.0.0 + minizlib@3.0.2: + dependencies: + minipass: 7.1.2 + mixme@0.5.10: {} mkdirp-classic@0.5.3: {} mkdirp@1.0.4: {} + mkdirp@3.0.1: {} + mlly@1.7.4: dependencies: acorn: 8.14.1 @@ -8352,16 +9880,12 @@ snapshots: ms@2.1.3: {} - mz@2.7.0: - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - - nanoid@3.3.11: {} + nanoid@3.3.8: {} napi-postinstall@0.2.4: {} + natural-compare-lite@1.4.0: {} + natural-compare@1.4.0: {} negotiator@0.6.3: {} @@ -8391,7 +9915,7 @@ snapshots: dependencies: hosted-git-info: 6.1.3 is-core-module: 2.16.1 - semver: 7.7.1 + semver: 7.7.2 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} @@ -8402,7 +9926,7 @@ snapshots: npm-install-checks@6.3.0: dependencies: - semver: 7.7.1 + semver: 7.7.2 npm-normalize-package-bin@3.0.1: {} @@ -8410,7 +9934,7 @@ snapshots: dependencies: hosted-git-info: 6.1.3 proc-log: 3.0.0 - semver: 7.7.1 + semver: 7.7.2 validate-npm-package-name: 5.0.1 npm-pick-manifest@8.0.2: @@ -8418,7 +9942,7 @@ snapshots: npm-install-checks: 6.3.0 npm-normalize-package-bin: 3.0.1 npm-package-arg: 10.1.0 - semver: 7.7.1 + semver: 7.7.2 npm-run-path@4.0.1: dependencies: @@ -8430,10 +9954,13 @@ snapshots: object-hash@2.2.0: {} - object-hash@3.0.0: {} - object-inspect@1.13.4: {} + object-is@1.1.6: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + object-keys@1.1.1: {} object.assign@4.1.7: @@ -8445,9 +9972,10 @@ snapshots: has-symbols: 1.1.0 object-keys: 1.1.1 - object.entries@1.1.8: + object.entries@1.1.9: dependencies: call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 es-object-atoms: 1.1.1 @@ -8455,14 +9983,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-object-atoms: 1.1.1 object.groupby@1.0.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 object.values@1.2.1: dependencies: @@ -8631,8 +10159,6 @@ snapshots: pify@4.0.1: {} - pirates@4.0.7: {} - pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -8662,7 +10188,7 @@ snapshots: postcss: 6.0.23 postcss-value-parser: 3.3.1 - postcss-import@15.1.0(postcss@8.5.3): + postcss-import@16.1.0(postcss@8.5.3): dependencies: postcss: 8.5.3 postcss-value-parser: 4.2.0 @@ -8674,18 +10200,21 @@ snapshots: camelcase-css: 2.0.1 postcss: 7.0.39 - postcss-js@4.0.1(postcss@8.5.3): - dependencies: - camelcase-css: 2.0.1 - postcss: 8.5.3 - - postcss-load-config@4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)): + postcss-load-config@4.0.2(postcss@8.5.3): dependencies: lilconfig: 3.1.3 yaml: 2.8.0 optionalDependencies: postcss: 8.5.3 - ts-node: 10.9.2(@types/node@22.15.3)(typescript@5.8.2) + + postcss-loader@8.1.1(postcss@8.5.3)(typescript@5.8.3): + dependencies: + cosmiconfig: 9.0.0(typescript@5.8.3) + jiti: 1.21.7 + postcss: 8.5.3 + semver: 7.7.2 + transitivePeerDependencies: + - typescript postcss-modules-extract-imports@3.1.0(postcss@8.5.3): dependencies: @@ -8725,11 +10254,6 @@ snapshots: postcss: 7.0.39 postcss-selector-parser: 6.1.2 - postcss-nested@6.2.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-selector-parser: 6.1.2 - postcss-selector-parser@6.0.10: dependencies: cssesc: 3.0.0 @@ -8768,10 +10292,19 @@ snapshots: postcss@8.5.3: dependencies: - nanoid: 3.3.11 + nanoid: 3.3.8 picocolors: 1.1.1 source-map-js: 1.2.1 + posthog-js@1.246.0: + dependencies: + core-js: 3.42.0 + fflate: 0.4.8 + preact: 10.26.7 + web-vitals: 4.2.4 + + preact@10.26.7: {} + preferred-pm@3.1.4: dependencies: find-up: 5.0.0 @@ -8781,20 +10314,32 @@ snapshots: prelude-ls@1.2.1: {} - prettier-plugin-tailwindcss@0.3.0(prettier@2.8.8): + prettier-plugin-tailwindcss@0.6.11(prettier@3.5.3): dependencies: - prettier: 2.8.8 + prettier: 3.5.3 prettier@2.8.8: {} prettier@3.5.3: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + pretty-hrtime@1.0.3: {} pretty-ms@7.0.1: dependencies: parse-ms: 2.1.0 + prism-react-renderer@2.4.1(react@18.3.1): + dependencies: + '@types/prismjs': 1.26.5 + clsx: 2.1.1 + react: 18.3.1 + prisma@5.4.1: dependencies: '@prisma/engines': 5.4.1 @@ -8877,6 +10422,8 @@ snapshots: react-is@16.13.1: {} + react-is@17.0.2: {} + react-refresh@0.14.2: {} react-router-dom@6.30.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -8953,7 +10500,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-errors: 1.3.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 @@ -8969,6 +10516,8 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 + regexpp@3.2.0: {} + remark-frontmatter@4.0.1: dependencies: '@types/mdast': 3.0.15 @@ -9005,18 +10554,58 @@ snapshots: mdast-util-to-hast: 12.3.0 unified: 10.1.2 - remix-typedjson@0.3.1(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.2))(@remix-run/server-runtime@2.16.7(typescript@5.8.2))(react@18.3.1): + remix-auth-google@2.0.0(@remix-run/server-runtime@2.16.7(typescript@5.8.3))(remix-auth@3.7.0(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3))): dependencies: - '@remix-run/react': 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.2) - '@remix-run/server-runtime': 2.16.7(typescript@5.8.2) + '@remix-run/server-runtime': 2.16.7(typescript@5.8.3) + remix-auth: 3.7.0(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3)) + remix-auth-oauth2: 1.11.2(@remix-run/server-runtime@2.16.7(typescript@5.8.3))(remix-auth@3.7.0(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3))) + transitivePeerDependencies: + - supports-color + + remix-auth-oauth2@1.11.2(@remix-run/server-runtime@2.16.7(typescript@5.8.3))(remix-auth@3.7.0(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3))): + dependencies: + '@remix-run/server-runtime': 2.16.7(typescript@5.8.3) + debug: 4.4.1 + remix-auth: 3.7.0(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3)) + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color + + remix-auth@3.7.0(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3)): + dependencies: + '@remix-run/react': 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) + '@remix-run/server-runtime': 2.16.7(typescript@5.8.3) + uuid: 8.3.2 + + remix-themes@1.6.1(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3)): + dependencies: + '@remix-run/react': 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) + '@remix-run/server-runtime': 2.16.7(typescript@5.8.3) + + remix-typedjson@0.3.1(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/server-runtime@2.16.7(typescript@5.8.3))(react@18.3.1): + dependencies: + '@remix-run/react': 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) + '@remix-run/server-runtime': 2.16.7(typescript@5.8.3) react: 18.3.1 + remix-utils@7.7.0(@remix-run/node@2.1.0(typescript@5.8.3))(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/router@1.23.0)(react@18.3.1)(zod@3.23.8): + dependencies: + type-fest: 4.41.0 + optionalDependencies: + '@remix-run/node': 2.1.0(typescript@5.8.3) + '@remix-run/react': 2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) + '@remix-run/router': 1.23.0 + react: 18.3.1 + zod: 3.23.8 + require-directory@2.1.1: {} require-like@0.1.2: {} require-main-filename@2.0.0: {} + requireindex@1.2.0: {} + resolve-from@4.0.0: {} resolve-from@5.0.0: {} @@ -9122,7 +10711,7 @@ snapshots: semver@6.3.1: {} - semver@7.7.1: {} + semver@7.7.2: {} send@0.19.0: dependencies: @@ -9280,6 +10869,11 @@ snapshots: statuses@2.0.1: {} + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + stream-shift@1.0.3: {} stream-slice@0.1.2: {} @@ -9306,14 +10900,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 string.prototype.matchall@4.0.12: dependencies: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-errors: 1.3.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 @@ -9327,7 +10921,7 @@ snapshots: string.prototype.repeat@1.0.0: dependencies: define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 string.prototype.trim@1.2.10: dependencies: @@ -9335,7 +10929,7 @@ snapshots: call-bound: 1.0.4 define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.23.10 es-object-atoms: 1.1.1 has-property-descriptors: 1.0.2 @@ -9387,16 +10981,6 @@ snapshots: dependencies: inline-style-parser: 0.1.1 - sucrase@3.35.0: - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - commander: 4.1.1 - glob: 10.4.5 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.7 - ts-interface-checker: 0.1.13 - supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -9411,19 +10995,22 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tailwind-merge@1.14.0: {} + tailwind-merge@2.6.0: {} - tailwind-scrollbar-hide@1.3.1(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))): + tailwind-scrollbar-hide@2.0.0(tailwindcss@4.1.7): dependencies: - tailwindcss: 3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)) + tailwindcss: 4.1.7 - tailwind-scrollbar@3.1.0(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))): + tailwind-scrollbar@4.0.2(react@18.3.1)(tailwindcss@4.1.7): dependencies: - tailwindcss: 3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)) + prism-react-renderer: 2.4.1(react@18.3.1) + tailwindcss: 4.1.7 + transitivePeerDependencies: + - react - tailwindcss-animate@1.0.7(tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2))): + tailwindcss-animate@1.0.7(tailwindcss@4.1.7): dependencies: - tailwindcss: 3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)) + tailwindcss: 4.1.7 tailwindcss-textshadow@2.1.3: dependencies: @@ -9454,32 +11041,9 @@ snapshots: reduce-css-calc: 2.1.8 resolve: 1.22.10 - tailwindcss@3.4.1(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)): - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.3 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.7 - lilconfig: 2.1.0 - micromatch: 4.0.8 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.1.1 - postcss: 8.5.3 - postcss-import: 15.1.0(postcss@8.5.3) - postcss-js: 4.0.1(postcss@8.5.3) - postcss-load-config: 4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2)) - postcss-nested: 6.2.0(postcss@8.5.3) - postcss-selector-parser: 6.1.2 - resolve: 1.22.10 - sucrase: 3.35.0 - transitivePeerDependencies: - - ts-node + tailwindcss@4.1.7: {} + + tapable@2.2.2: {} tar-fs@2.1.3: dependencies: @@ -9505,23 +11069,26 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 + tar@7.4.3: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.0.2 + mkdirp: 3.0.1 + yallist: 5.0.0 + term-size@2.2.1: {} text-table@0.2.0: {} - thenify-all@1.6.0: - dependencies: - thenify: 3.3.1 - - thenify@3.3.1: - dependencies: - any-promise: 1.3.0 - through2@2.0.5: dependencies: readable-stream: 2.3.8 xtend: 4.0.2 + tiny-invariant@1.3.3: {} + tinyglobby@0.2.14: dependencies: fdir: 6.4.4(picomatch@4.0.2) @@ -9547,34 +11114,13 @@ snapshots: trough@2.2.0: {} - ts-api-utils@1.4.3(typescript@5.8.2): + ts-api-utils@1.4.3(typescript@5.8.3): dependencies: - typescript: 5.8.2 + typescript: 5.8.3 - ts-interface-checker@0.1.13: {} - - ts-node@10.9.2(@types/node@22.15.3)(typescript@5.8.2): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 22.15.3 - acorn: 8.14.1 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.8.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - optional: true - - tsconfck@3.1.6(typescript@5.8.2): + tsconfck@3.1.6(typescript@5.8.3): optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 tsconfig-paths@3.15.0: dependencies: @@ -9589,9 +11135,16 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 + tslib@1.14.1: {} + tslib@2.8.1: optional: true + tsutils@3.21.0(typescript@5.8.3): + dependencies: + tslib: 1.14.1 + typescript: 5.8.3 + tty-table@4.2.3: dependencies: chalk: 4.1.2 @@ -9643,6 +11196,8 @@ snapshots: type-fest@0.8.1: {} + type-fest@4.41.0: {} + type-is@1.6.18: dependencies: media-typer: 0.3.0 @@ -9681,7 +11236,9 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript@5.8.2: {} + typescript@5.5.4: {} + + typescript@5.8.3: {} ufo@1.6.1: {} @@ -9794,10 +11351,14 @@ snapshots: is-arguments: 1.2.0 is-generator-function: 1.1.0 is-typed-array: 1.1.15 - which-typed-array: 1.1.18 + which-typed-array: 1.1.19 utils-merge@1.0.1: {} + uuid@8.3.2: {} + + uuid@9.0.1: {} + uvu@0.5.6: dependencies: dequal: 2.0.3 @@ -9805,12 +11366,9 @@ snapshots: kleur: 4.1.5 sade: 1.8.1 - v8-compile-cache-lib@3.0.1: - optional: true - - valibot@0.41.0(typescript@5.8.2): + valibot@0.41.0(typescript@5.8.3): optionalDependencies: - typescript: 5.8.2 + typescript: 5.8.3 validate-npm-package-license@3.0.4: dependencies: @@ -9833,13 +11391,13 @@ snapshots: unist-util-stringify-position: 3.0.3 vfile-message: 3.1.4 - vite-node@1.6.1(@types/node@22.15.3): + vite-node@1.6.1(@types/node@22.15.21)(lightningcss@1.30.1): dependencies: cac: 6.7.14 debug: 4.4.1 pathe: 1.1.2 picocolors: 1.1.1 - vite: 5.4.19(@types/node@22.15.3) + vite: 5.4.19(@types/node@22.15.21)(lightningcss@1.30.1) transitivePeerDependencies: - '@types/node' - less @@ -9851,13 +11409,13 @@ snapshots: - supports-color - terser - vite-node@3.1.4(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0): + vite-node@3.1.4(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -9872,27 +11430,28 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@4.3.2(typescript@5.8.2)(vite@6.3.5(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0)): + vite-tsconfig-paths@4.3.2(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)): dependencies: debug: 4.4.1 globrex: 0.1.2 - tsconfck: 3.1.6(typescript@5.8.2) + tsconfck: 3.1.6(typescript@5.8.3) optionalDependencies: - vite: 6.3.5(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) transitivePeerDependencies: - supports-color - typescript - vite@5.4.19(@types/node@22.15.3): + vite@5.4.19(@types/node@22.15.21)(lightningcss@1.30.1): dependencies: esbuild: 0.21.5 postcss: 8.5.3 rollup: 4.41.1 optionalDependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.21 fsevents: 2.3.3 + lightningcss: 1.30.1 - vite@6.3.5(@types/node@22.15.3)(jiti@1.21.7)(yaml@2.8.0): + vite@6.3.5(@types/node@22.15.21)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0): dependencies: esbuild: 0.25.5 fdir: 6.4.4(picomatch@4.0.2) @@ -9901,9 +11460,10 @@ snapshots: rollup: 4.41.1 tinyglobby: 0.2.14 optionalDependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.21 fsevents: 2.3.3 - jiti: 1.21.7 + jiti: 2.4.2 + lightningcss: 1.30.1 yaml: 2.8.0 wcwidth@1.0.1: @@ -9918,6 +11478,8 @@ snapshots: web-streams-polyfill@3.3.3: {} + web-vitals@4.2.4: {} + webidl-conversions@3.0.1: {} whatwg-url@5.0.0: @@ -9947,7 +11509,7 @@ snapshots: isarray: 2.0.5 which-boxed-primitive: 1.1.1 which-collection: 1.0.2 - which-typed-array: 1.1.18 + which-typed-array: 1.1.19 which-collection@1.0.2: dependencies: @@ -9963,12 +11525,13 @@ snapshots: load-yaml-file: 0.2.0 path-exists: 4.0.0 - which-typed-array@1.1.18: + which-typed-array@1.1.19: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.8 call-bound: 1.0.4 for-each: 0.3.5 + get-proto: 1.0.1 gopd: 1.2.0 has-tostringtag: 1.0.2 @@ -10020,6 +11583,8 @@ snapshots: yallist@4.0.0: {} + yallist@5.0.0: {} + yaml@2.8.0: {} yargs-parser@18.1.3: @@ -10053,9 +11618,6 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yn@3.1.1: - optional: true - yocto-queue@0.1.0: {} zod-error@1.5.0: diff --git a/turbo.json b/turbo.json index 6eabee3..4ef0762 100644 --- a/turbo.json +++ b/turbo.json @@ -5,7 +5,13 @@ "build": { "dependsOn": [ "^build" ], "inputs": [ "$TURBO_DEFAULT$", ".env*" ], - "outputs": [ ".next/**", "!.next/cache/**" ] + "outputs": [ + "dist/**", + "public/build/**", + "build/**", + "app/styles/tailwind.css", + ".cache" + ] }, "lint": { "dependsOn": [ "^lint" ] @@ -14,8 +20,7 @@ "dependsOn": [ "^check-types" ] }, "dev": { - "cache": false, - "persistent": true + "cache": false }, "db:generate": { "cache": false @@ -23,6 +28,10 @@ "db:migrate:deploy": { "cache": false }, + "db:migrate:create": { + "cache": false, + "interactive": true + }, "db:studio": { "cache": false }, @@ -31,5 +40,23 @@ "^generate" ] } - } + }, + "globalDependencies": [ + ".env" + ], + "globalEnv": [ + "NODE_ENV", + "REMIX_APP_PORT", + "CI", + "DATABASE_URL", + "DIRECT_URL", + "SESSION_SECRET", + "APP_ORIGIN", + "LOGIN_ORIGIN", + "POSTHOG_PROJECT_KEY", + "AUTH_GOOGLE_CLIENT_ID", + "AUTH_GOOGLE_CLIENT_SECRET", + "APP_ENV", + "APP_LOG_LEVEL" + ] }