diff --git a/apps/web/.gitignore b/apps/web/.gitignore new file mode 100644 index 000000000..5cc3fcc7b --- /dev/null +++ b/apps/web/.gitignore @@ -0,0 +1,5 @@ +.output +.nitro +.tanstack +.vite +*.tsbuildinfo diff --git a/apps/web/eslint.config.mjs b/apps/web/eslint.config.mjs new file mode 100644 index 000000000..7c2c6398a --- /dev/null +++ b/apps/web/eslint.config.mjs @@ -0,0 +1,22 @@ +import eslintVitNode from "@vitnode/config/eslint"; +import eslintVitNodeReact from "@vitnode/config/eslint.react"; +import { dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +export default [ + ...eslintVitNode, + ...eslintVitNodeReact, + { + ignores: ["src/routeTree.gen.ts", ".output", ".nitro", ".tanstack"], + }, + { + languageOptions: { + parserOptions: { + project: "./tsconfig.json", + tsconfigRootDir: __dirname, + }, + }, + }, +]; diff --git a/apps/web/package.json b/apps/web/package.json new file mode 100644 index 000000000..879035833 --- /dev/null +++ b/apps/web/package.json @@ -0,0 +1,37 @@ +{ + "name": "web", + "version": "1.2.0-canary.78", + "private": true, + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "start": "node .output/server/index.mjs", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@fontsource-variable/geist": "^5.3.0", + "@tanstack/react-query": "^5.101.4", + "@tanstack/react-router": "1.170.31", + "@tanstack/react-start": "1.168.48", + "@vitnode/i18n": "workspace:*", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "use-intl": "^4.13.7" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.3.3", + "@types/node": "^26.1.1", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "6.0.4", + "@vitnode/config": "workspace:*", + "eslint": "^10.7.0", + "nitro": "^3.0.260610-beta", + "tailwindcss": "^4.3.3", + "typescript": "^6.0.3", + "vite": "8.1.5" + } +} diff --git a/apps/web/src/routeTree.gen.ts b/apps/web/src/routeTree.gen.ts new file mode 100644 index 000000000..219a365aa --- /dev/null +++ b/apps/web/src/routeTree.gen.ts @@ -0,0 +1,87 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +import { Route as rootRouteImport } from './routes/__root' +import { Route as IndexRouteImport } from './routes/index' +import { Route as AdminRouteImport } from './routes/admin' + +const IndexRoute = IndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any) +const AdminRoute = AdminRouteImport.update({ + id: '/admin', + path: '/admin', + getParentRoute: () => rootRouteImport, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '/admin': typeof AdminRoute +} +export interface FileRoutesByTo { + '/': typeof IndexRoute + '/admin': typeof AdminRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/': typeof IndexRoute + '/admin': typeof AdminRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: '/' | '/admin' + fileRoutesByTo: FileRoutesByTo + to: '/' | '/admin' + id: '__root__' | '/' | '/admin' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + AdminRoute: typeof AdminRoute +} + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + '/admin': { + id: '/admin' + path: '/admin' + fullPath: '/admin' + preLoaderRoute: typeof AdminRouteImport + parentRoute: typeof rootRouteImport + } + } +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + AdminRoute: AdminRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() + +import type { getRouter } from './router.tsx' +import type { startInstance } from './start.ts' +declare module '@tanstack/react-start' { + interface Register { + ssr: true + router: Awaited> + config: Awaited> + } +} diff --git a/apps/web/src/router.tsx b/apps/web/src/router.tsx new file mode 100644 index 000000000..2bf335896 --- /dev/null +++ b/apps/web/src/router.tsx @@ -0,0 +1,47 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { createRouter } from "@tanstack/react-router"; +import { deLocalizeUrl, localizeUrl } from "@vitnode/i18n/client"; +import { useTranslations } from "use-intl"; + +import { routeTree } from "./routeTree.gen"; + +export interface RouterAppContext { + queryClient: QueryClient; +} + +const NotFound = () => { + const t = useTranslations("notFound"); + + return ( +
+

{t("title")}

+
+ ); +}; + +export const getRouter = () => { + const queryClient = new QueryClient(); + + return createRouter({ + routeTree, + context: { queryClient } satisfies RouterAppContext, + scrollRestoration: true, + defaultPreload: "intent", + defaultNotFoundComponent: NotFound, + // The locale lives only in the public URL: the router matches, and app code + // links against, paths with no locale segment at all. + rewrite: { + input: ({ url }) => deLocalizeUrl(url), + output: ({ url }) => localizeUrl(url), + }, + Wrap: ({ children }) => ( + {children} + ), + }); +}; + +declare module "@tanstack/react-router" { + interface Register { + router: ReturnType; + } +} diff --git a/apps/web/src/routes/__root.tsx b/apps/web/src/routes/__root.tsx new file mode 100644 index 000000000..b780e5e0d --- /dev/null +++ b/apps/web/src/routes/__root.tsx @@ -0,0 +1,57 @@ +import type { QueryClient } from "@tanstack/react-query"; + +import { + createRootRouteWithContext, + HeadContent, + Scripts, +} from "@tanstack/react-router"; +import { + getCurrentLocale, + I18nProvider, + messagesQueryOptions, +} from "@vitnode/i18n/client"; + +import appCss from "../styles/globals.css?url"; + +export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()( + { + // The locale comes from the request, not from a route param, so the loader + // is what resolves it - and returning the messages hands them to the client + // through the router's own SSR payload, with nothing to re-fetch on hydrate. + loader: async ({ context }) => { + const locale = getCurrentLocale(); + + return { + locale, + messages: await context.queryClient.ensureQueryData( + messagesQueryOptions(locale), + ), + }; + }, + head: () => ({ + meta: [ + { charSet: "utf-8" }, + { name: "viewport", content: "width=device-width, initial-scale=1" }, + { title: "VitNode" }, + ], + links: [{ rel: "stylesheet", href: appCss }], + }), + shellComponent: RootDocument, + }, +); + +function RootDocument({ children }: { children: React.ReactNode }) { + const initial = Route.useLoaderData(); + + return ( + + + + + + {children} + + + + ); +} diff --git a/apps/web/src/routes/admin.tsx b/apps/web/src/routes/admin.tsx new file mode 100644 index 000000000..918d0394e --- /dev/null +++ b/apps/web/src/routes/admin.tsx @@ -0,0 +1,23 @@ +import { createFileRoute, Link } from "@tanstack/react-router"; +import { useTranslations } from "use-intl"; + +export const Route = createFileRoute("/admin")({ + component: Admin, +}); + +function Admin() { + const t = useTranslations("admin"); + + return ( +
+

{t("title")}

+

+ {t("description")} +

+ {/* Never localized, so a plain Link rather than a LocalizedLink. */} + + {t("title")} + +
+ ); +} diff --git a/apps/web/src/routes/index.tsx b/apps/web/src/routes/index.tsx new file mode 100644 index 000000000..479c922de --- /dev/null +++ b/apps/web/src/routes/index.tsx @@ -0,0 +1,31 @@ +import { createFileRoute, Link } from "@tanstack/react-router"; +import { LocaleSwitcher, LocalizedLink } from "@vitnode/i18n/client"; +import { useTranslations } from "use-intl"; + +export const Route = createFileRoute("/")({ + component: Home, +}); + +function Home() { + const t = useTranslations("home"); + + return ( +
+

{t("title")}

+

+ {t("description")} +

+ +
+ {/* Localized: picks up the current locale's prefix. */} + + {t("title")} + + {/* Never localized, so a plain Link. */} + + {t("admin")} + +
+
+ ); +} diff --git a/apps/web/src/start.ts b/apps/web/src/start.ts new file mode 100644 index 000000000..d28ada435 --- /dev/null +++ b/apps/web/src/start.ts @@ -0,0 +1,6 @@ +import { createStart } from "@tanstack/react-start"; +import { localeRequestMiddleware } from "@vitnode/i18n/server"; + +export const startInstance = createStart(() => ({ + requestMiddleware: [localeRequestMiddleware], +})); diff --git a/apps/web/src/styles/globals.css b/apps/web/src/styles/globals.css new file mode 100644 index 000000000..1267eec5b --- /dev/null +++ b/apps/web/src/styles/globals.css @@ -0,0 +1,132 @@ +@import "tailwindcss"; +@import "@fontsource-variable/geist"; + +:root:not(.dark) { + --background: oklch(0.97 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.51 0.16 262.61); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.967 0.001 286.375); + --secondary-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.967 0.001 286.375); + --muted-foreground: oklch(0.552 0.016 285.938); + --accent: oklch(0.967 0.001 286.375); + --accent-foreground: oklch(0.21 0.006 285.885); + --destructive: oklch(0.577 0.245 27.325); + --warn: oklch(0.54 0.12 82.58); + --border: oklch(0.92 0.004 286.32); + --input: oklch(0.92 0.004 286.32); + --ring: oklch(0.705 0.015 286.067); + --chart-1: oklch(0.871 0.006 286.286); + --chart-2: oklch(0.552 0.016 285.938); + --chart-3: oklch(0.442 0.017 285.786); + --chart-4: oklch(0.37 0.013 285.805); + --chart-5: oklch(0.274 0.006 286.033); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.141 0.005 285.823); + --sidebar-primary: oklch(0.21 0.006 285.885); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.967 0.001 286.375); + --sidebar-accent-foreground: oklch(0.21 0.006 285.885); + --sidebar-border: oklch(0.92 0.004 286.32); + --sidebar-ring: oklch(0.705 0.015 286.067); +} + +.dark { + --background: oklch(0.14 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.21 0.006 285.885); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.21 0.006 285.885); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.6 0.18 262.65); + --primary-foreground: oklch(0.98 0 0); + --secondary: oklch(0.274 0.006 286.033); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.274 0.006 286.033); + --muted-foreground: oklch(0.705 0.015 286.067); + --accent: oklch(0.274 0.006 286.033); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --warn: oklch(0.76 0.18 81.84); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.552 0.016 285.938); + --chart-1: oklch(0.871 0.006 286.286); + --chart-2: oklch(0.552 0.016 285.938); + --chart-3: oklch(0.442 0.017 285.786); + --chart-4: oklch(0.37 0.013 285.805); + --chart-5: oklch(0.274 0.006 286.033); + --sidebar: oklch(0.21 0.006 285.885); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.274 0.006 286.033); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.552 0.016 285.938); +} + +:root { + --radius: 0.625rem; + --font-sans: + "Geist Variable", ui-sans-serif, system-ui, -apple-system, sans-serif; +} + +@theme inline { + --font-heading: var(--font-sans); + --font-sans: var(--font-sans); + --color-sidebar-ring: var(--sidebar-ring); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar: var(--sidebar); + --color-chart-5: var(--chart-5); + --color-chart-4: var(--chart-4); + --color-chart-3: var(--chart-3); + --color-chart-2: var(--chart-2); + --color-chart-1: var(--chart-1); + --color-ring: var(--ring); + --color-input: var(--input); + --color-border: var(--border); + --color-warn: var(--warn); + --color-destructive: var(--destructive); + --color-accent-foreground: var(--accent-foreground); + --color-accent: var(--accent); + --color-muted-foreground: var(--muted-foreground); + --color-muted: var(--muted); + --color-secondary-foreground: var(--secondary-foreground); + --color-secondary: var(--secondary); + --color-primary-foreground: var(--primary-foreground); + --color-primary: var(--primary); + --color-popover-foreground: var(--popover-foreground); + --color-popover: var(--popover); + --color-card-foreground: var(--card-foreground); + --color-card: var(--card); + --color-foreground: var(--foreground); + --color-background: var(--background); + --radius-sm: calc(var(--radius) * 0.6); + --radius-md: calc(var(--radius) * 0.8); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) * 1.4); + --radius-2xl: calc(var(--radius) * 1.8); + --radius-3xl: calc(var(--radius) * 2.2); + --radius-4xl: calc(var(--radius) * 2.6); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json new file mode 100644 index 000000000..88c9f3ef4 --- /dev/null +++ b/apps/web/tsconfig.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vitnode/config/tsconfig", + "compilerOptions": { + "target": "ESNext", + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "noEmit": true, + "types": ["vite/client"], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts new file mode 100644 index 000000000..b0a4e445b --- /dev/null +++ b/apps/web/vite.config.ts @@ -0,0 +1,23 @@ +import tailwindcss from "@tailwindcss/vite"; +import { tanstackStart } from "@tanstack/react-start/plugin/vite"; +import viteReact from "@vitejs/plugin-react"; +import { nitro } from "nitro/vite"; +import { defineConfig } from "vite"; + +export default defineConfig({ + server: { port: 3000 }, + resolve: { tsconfigPaths: true }, + ssr: { + // Workspace packages must be bundled, not externalized. + noExternal: [/^@vitnode\//], + }, + plugins: [ + tailwindcss(), + tanstackStart({ + srcDirectory: "src", + router: { routesDirectory: "routes" }, + }), + viteReact(), + nitro(), + ], +}); diff --git a/packages/i18n/.gitignore b/packages/i18n/.gitignore new file mode 100644 index 000000000..43370fa91 --- /dev/null +++ b/packages/i18n/.gitignore @@ -0,0 +1 @@ +*.tsbuildinfo diff --git a/packages/i18n/eslint.config.mjs b/packages/i18n/eslint.config.mjs new file mode 100644 index 000000000..13497eb72 --- /dev/null +++ b/packages/i18n/eslint.config.mjs @@ -0,0 +1,19 @@ +import eslintVitNode from "@vitnode/config/eslint"; +import eslintVitNodeReact from "@vitnode/config/eslint.react"; +import { dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +export default [ + ...eslintVitNode, + ...eslintVitNodeReact, + { + languageOptions: { + parserOptions: { + project: "./tsconfig.json", + tsconfigRootDir: __dirname, + }, + }, + }, +]; diff --git a/packages/i18n/package.json b/packages/i18n/package.json new file mode 100644 index 000000000..36374caf2 --- /dev/null +++ b/packages/i18n/package.json @@ -0,0 +1,58 @@ +{ + "name": "@vitnode/i18n", + "version": "1.2.0-canary.78", + "description": "Locale routing and translations for VitNode on TanStack Start.", + "author": "VitNode Team", + "license": "MIT", + "homepage": "https://vitnode.com", + "repository": { + "type": "git", + "url": "git+https://github.com/aXenDeveloper/vitnode.git", + "directory": "packages/i18n" + }, + "keywords": [ + "vitnode", + "i18n", + "tanstack-start", + "use-intl" + ], + "type": "module", + "exports": { + "./client": { + "import": "./src/entry-client.tsx", + "default": "./src/entry-client.tsx" + }, + "./server": { + "import": "./src/entry-server.ts", + "default": "./src/entry-server.ts" + }, + "./messages": { + "import": "./src/messages/index.ts", + "default": "./src/messages/index.ts" + } + }, + "scripts": { + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "use-intl": "^4.13.7" + }, + "devDependencies": { + "@tanstack/react-query": "^5.101.4", + "@tanstack/react-router": "1.170.31", + "@tanstack/react-start": "1.168.48", + "@types/react": "^19.2.17", + "@vitnode/config": "workspace:*", + "eslint": "^10.7.0", + "react": "^19.2.8", + "typescript": "^6.0.3" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.x.x", + "@tanstack/react-router": "^1.x.x", + "@tanstack/react-start": "^1.x.x", + "react": "^19.2.x" + } +} diff --git a/packages/i18n/src/core/client.ts b/packages/i18n/src/core/client.ts new file mode 100644 index 000000000..d97a2ef48 --- /dev/null +++ b/packages/i18n/src/core/client.ts @@ -0,0 +1,104 @@ +import { createIsomorphicFn } from "@tanstack/react-start"; +import { getRequest } from "@tanstack/react-start/server"; + +import type { Locale } from "./shared"; + +import { + defaultLocale, + extractLocaleFromPath, + isValidLocale, + LOCALE_COOKIE, + shouldIgnorePath, + stripLocaleSegment, +} from "./shared"; + +/** + * The locale for the current request or document. + * + * Both branches follow the same rule so server and client always agree - a + * disagreement here surfaces as a hydration mismatch: + * + * - ignored paths (`/admin`, `/api`) carry no prefix, so the cookie decides + * - every other path is described entirely by its URL + * + * `createIsomorphicFn` is compiled away per environment, which is what keeps + * the server-only `getRequest` import out of the browser bundle. + */ +export const getCurrentLocale = createIsomorphicFn() + .server((): Locale => { + const url = new URL(getRequest().url); + + if (shouldIgnorePath(url.pathname)) { + return readCookieLocale(getRequest().headers.get("cookie")); + } + + return extractLocaleFromPath(url.pathname) ?? defaultLocale; + }) + .client((): Locale => { + const { pathname } = window.location; + + if (shouldIgnorePath(pathname)) { + return readCookieLocale(document.cookie); + } + + return extractLocaleFromPath(pathname) ?? defaultLocale; + }); + +/** Reads `LOCALE_COOKIE` out of a `Cookie` header or `document.cookie`. */ +export const readCookieLocale = (header: null | string): Locale => { + const value = header + ?.split(";") + .map(part => part.trim()) + .find(part => part.startsWith(`${LOCALE_COOKIE}=`)) + ?.slice(LOCALE_COOKIE.length + 1); + + return isValidLocale(value) ? value : defaultLocale; +}; + +/** + * Turns a public URL into the one the router matches against: `/pl/about` + * becomes `/about`, so the route tree never carries a locale segment. + */ +export const deLocalizeUrl = (url: URL): URL => { + if (shouldIgnorePath(url.pathname)) return url; + + const locale = extractLocaleFromPath(url.pathname); + + if (!locale) return url; + + const next = new URL(url); + next.pathname = stripLocaleSegment(url.pathname, locale); + + return next; +}; + +/** + * The inverse: turns a router URL into the public one, so `` + * renders `/pl/about` while the visitor is reading Polish. + * + * The router derives every href it commits to history through this, so it has + * to stay an exact inverse of `deLocalizeUrl` or navigation will bounce. + */ +export const localizeUrl = (url: URL): URL => { + if (shouldIgnorePath(url.pathname)) return url; + + const locale = getCurrentLocale(); + + if (locale === defaultLocale) return url; + + const next = new URL(url); + next.pathname = `/${locale}${url.pathname === "/" ? "" : url.pathname}`; + + return next; +}; + +/** The public path a given locale would serve `pathname` at. */ +export const localizedPath = (pathname: string, locale: Locale): string => { + if (shouldIgnorePath(pathname)) return pathname; + + const base = deLocalizeUrl(new URL(pathname, "http://localhost")).pathname; + + if (locale === defaultLocale) return base; + + return `/${locale}${base === "/" ? "" : base}`; +}; diff --git a/packages/i18n/src/core/server.ts b/packages/i18n/src/core/server.ts new file mode 100644 index 000000000..0648542de --- /dev/null +++ b/packages/i18n/src/core/server.ts @@ -0,0 +1,100 @@ +import { createMiddleware } from "@tanstack/react-start"; +import { setCookie } from "@tanstack/react-start/server"; + +import type { Locale } from "./shared"; + +import { + defaultLocale, + isValidLocale, + LOCALE_COOKIE, + shouldIgnorePath, + stripLocaleSegment, +} from "./shared"; + +/** A year, in seconds. */ +const COOKIE_MAX_AGE = 60 * 60 * 24 * 365; + +export interface LocaleResolution { + /** Where to send the visitor instead of rendering, if anywhere. */ + redirect?: string; + /** The locale the URL states outright, which the cookie should catch up to. */ + setCookie?: Locale; +} + +/** + * Decides what a request's URL means for the locale, before React renders. + * + * This has to run at the request layer rather than in a route: a route can + * throw `notFound()`, but by the time it runs the response has already started + * streaming, so it can no longer answer with a redirect. + * + * In order: + * + * 1. ignored paths are left alone - they are never prefixed + * 2. `/en/*` is not canonical, since the default locale has no prefix + * 3. a prefix in front of an ignored path is dropped (`/pl/admin` -> `/admin`) + * 4. otherwise the URL names a locale, so the cookie is brought in line + */ +const serializeLocaleCookie = (locale: Locale): string => + `${LOCALE_COOKIE}=${locale}; Path=/; Max-Age=${COOKIE_MAX_AGE}; SameSite=Lax`; + +export const handleLocaleMiddleware = (request: Request): LocaleResolution => { + const { pathname, search } = new URL(request.url); + + if (shouldIgnorePath(pathname)) return {}; + + const segment = pathname.split("/")[1]; + + if (segment === defaultLocale) { + return { + redirect: stripLocaleSegment(pathname, defaultLocale) + search, + setCookie: defaultLocale, + }; + } + + // An unprefixed public path is the default locale stated outright, so the + // cookie follows it too - otherwise switching back to English would leave + // `/admin` reading a stale locale. + if (!isValidLocale(segment)) return { setCookie: defaultLocale }; + + const stripped = stripLocaleSegment(pathname, segment); + + if (shouldIgnorePath(stripped)) { + return { redirect: stripped + search, setCookie: segment }; + } + + return { setCookie: segment }; +}; + +/** + * Applies `handleLocaleMiddleware` to every incoming request. + * + * Registered through `createStart` so it runs ahead of the router, which is the + * only place a redirect is still possible. + */ +export const localeRequestMiddleware = createMiddleware({ + type: "request", +}).server(async ({ next, request }) => { + const { redirect, setCookie: locale } = handleLocaleMiddleware(request); + + // A redirect is returned as its own Response, which never passes through the + // response context `setCookie` writes to - so it carries the header itself. + if (redirect !== undefined) { + const headers = new Headers({ location: redirect }); + + if (locale) headers.append("set-cookie", serializeLocaleCookie(locale)); + + return new Response(null, { headers, status: 301 }); + } + + if (locale) { + setCookie(LOCALE_COOKIE, locale, { + httpOnly: false, + maxAge: COOKIE_MAX_AGE, + path: "/", + sameSite: "lax", + }); + } + + return await next(); +}); diff --git a/packages/i18n/src/core/shared.ts b/packages/i18n/src/core/shared.ts new file mode 100644 index 000000000..345478d0e --- /dev/null +++ b/packages/i18n/src/core/shared.ts @@ -0,0 +1,58 @@ +/** + * Configuration and pure helpers shared by the client and the server. + * + * Nothing here may import an environment-specific module: both `./client` and + * `./server` pull this file in, so a `node:*` or a `window` reference would + * leak into whichever bundle it does not belong to. + */ + +export const defaultLocale = "en"; +export const supportedLocales = ["en", "pl"] as const; +export const LOCALE_COOKIE = "locale"; + +/** + * Formatting time zone. + * + * Pinned rather than left to the environment: `use-intl` would otherwise fall + * back to the host's zone, which differs between the server and the browser and + * makes every formatted date a hydration mismatch waiting to happen. + */ +export const defaultTimeZone = "UTC"; + +/** `/api/*` and `/admin/*` are never localized - they read the cookie. */ +export const ignoredPathsRegex = /^\/(?:api|admin)(?:\/|$)/; + +export type Locale = (typeof supportedLocales)[number]; + +export const isValidLocale = (locale: string | undefined): locale is Locale => + locale !== undefined && + (supportedLocales as readonly string[]).includes(locale); + +export const shouldIgnorePath = (pathname: string): boolean => + ignoredPathsRegex.test(pathname); + +/** + * The locale a pathname carries as its first segment, or `null` when it carries + * none. + * + * The default locale is deliberately reported as `null`: it is served without a + * prefix, so `/en/about` is not a canonical URL and gets redirected rather than + * treated as English. + */ +export const extractLocaleFromPath = (pathname: string): Locale | null => { + const segment = pathname.split("/")[1]; + + if (!isValidLocale(segment) || segment === defaultLocale) return null; + + return segment; +}; + +/** Drops the leading locale segment, keeping the result rooted at `/`. */ +export const stripLocaleSegment = ( + pathname: string, + locale: string, +): string => { + const rest = pathname.slice(locale.length + 1); + + return rest === "" ? "/" : rest; +}; diff --git a/packages/i18n/src/entry-client.tsx b/packages/i18n/src/entry-client.tsx new file mode 100644 index 000000000..f092b0001 --- /dev/null +++ b/packages/i18n/src/entry-client.tsx @@ -0,0 +1,173 @@ +import type { ComponentProps, ReactNode } from "react"; + +import { + keepPreviousData, + queryOptions, + useQuery, +} from "@tanstack/react-query"; +import { + Link, + type RegisteredRouter, + useRouterState, +} from "@tanstack/react-router"; +import { IntlProvider } from "use-intl"; + +import type { Locale } from "./core/shared"; +import type { Messages } from "./messages"; + +import { getCurrentLocale, localizedPath } from "./core/client"; +import { + defaultLocale, + defaultTimeZone, + isValidLocale, + shouldIgnorePath, + supportedLocales, +} from "./core/shared"; +import { loadMessages } from "./messages"; + +export { + deLocalizeUrl, + getCurrentLocale, + localizedPath, + localizeUrl, + readCookieLocale, +} from "./core/client"; +export { + defaultLocale, + defaultTimeZone, + extractLocaleFromPath, + ignoredPathsRegex, + isValidLocale, + type Locale, + LOCALE_COOKIE, + shouldIgnorePath, + supportedLocales, +} from "./core/shared"; +export { loadMessages, type Messages } from "./messages"; + +/** + * Messages never change for the lifetime of the tab, so once a locale has been + * fetched there is nothing to revalidate or evict. + */ +export const messagesQueryOptions = (locale: Locale) => + queryOptions({ + gcTime: Infinity, + queryFn: async () => await loadMessages(locale), + queryKey: ["i18n", "messages", locale] as const, + staleTime: Infinity, + }); + +/** The public pathname currently on screen, locale prefix included. */ +const usePublicPathname = (): string => + useRouterState({ + select: state => + new URL(state.location.publicHref, "http://localhost").pathname, + }); + +/** + * The locale currently on screen. + * + * `useRouterState` is what makes this reactive: the locale lives in the public + * URL rather than in the router's own path space, so a navigation is what has + * to trigger the re-read. + * + * Ignored paths carry no prefix, so there the cookie is the only source - which + * is exactly what `getCurrentLocale` reads on both sides of the wire. + */ +export const useLocale = (): Locale => { + const pathname = usePublicPathname(); + + if (shouldIgnorePath(pathname)) return getCurrentLocale(); + + const segment = pathname.split("/")[1]; + + return isValidLocale(segment) ? segment : defaultLocale; +}; + +export interface I18nProviderProps { + children: ReactNode; + /** + * The locale and messages the server rendered with. + * + * Passing them in is what keeps the first client render identical to the SSR + * output: the query starts already resolved instead of suspending and + * swapping the strings in afterwards. + */ + initial: { locale: Locale; messages: Messages }; +} + +export const I18nProvider = ({ children, initial }: I18nProviderProps) => { + const locale = useLocale(); + const { data } = useQuery({ + ...messagesQueryOptions(locale), + initialData: locale === initial.locale ? initial.messages : undefined, + // Keeps the previous locale's strings up for the one render a newly chosen + // locale takes to load, rather than blanking the page. + placeholderData: keepPreviousData, + }); + + return ( + + {children} + + ); +}; + +type AppFileRouteTypes = + RegisteredRouter["routeTree"]["types"]["fileRouteTypes"]; + +type AppTo = AppFileRouteTypes extends { to: infer TTo extends string } + ? TTo + : never; + +/** Every route target except the ones that are never given a locale prefix. */ +export type LocalizedTo = Exclude; + +export type LocalizedLinkProps = Omit, "to"> & { + to: LocalizedTo; +}; + +/** + * `Link`, narrowed to the routes that actually get localized. + * + * Targets are inferred from the app's generated `FileRouteTypes`, so an unknown + * path is a type error - and so is `/admin`, which stays a plain ``. + * + * The href itself needs no work here: the router's `output` rewrite is what + * turns `/about` into `/pl/about`. + */ +export const LocalizedLink = ({ to, ...props }: LocalizedLinkProps) => ( + +); + +/** + * Switches locale. + * + * This navigates the document rather than the router on purpose. The locale is + * server-owned state - it lives in the URL prefix and in the cookie - so a real + * request is what moves all of it at once, and it keeps working with JavaScript + * disabled. The request middleware syncs the cookie on the way through. + */ +export const LocaleSwitcher = () => { + const locale = useLocale(); + const pathname = usePublicPathname(); + + return ( + + ); +}; diff --git a/packages/i18n/src/entry-server.ts b/packages/i18n/src/entry-server.ts new file mode 100644 index 000000000..aac6b1caa --- /dev/null +++ b/packages/i18n/src/entry-server.ts @@ -0,0 +1,16 @@ +export { + handleLocaleMiddleware, + localeRequestMiddleware, + type LocaleResolution, +} from "./core/server"; +export { + defaultLocale, + defaultTimeZone, + extractLocaleFromPath, + ignoredPathsRegex, + isValidLocale, + type Locale, + LOCALE_COOKIE, + shouldIgnorePath, + supportedLocales, +} from "./core/shared"; diff --git a/packages/i18n/src/messages/en.ts b/packages/i18n/src/messages/en.ts new file mode 100644 index 000000000..d7a9ab514 --- /dev/null +++ b/packages/i18n/src/messages/en.ts @@ -0,0 +1,21 @@ +export const en = { + admin: { + description: "This area is never localized through the URL.", + title: "Admin", + }, + home: { + admin: "Admin", + description: "A TanStack Start application.", + title: "VitNode", + }, + notFound: { + title: "Page not found", + }, + locale: { + en: "English", + label: "Language", + pl: "Polski", + }, +}; + +export type Messages = typeof en; diff --git a/packages/i18n/src/messages/index.ts b/packages/i18n/src/messages/index.ts new file mode 100644 index 000000000..2366b4b14 --- /dev/null +++ b/packages/i18n/src/messages/index.ts @@ -0,0 +1,19 @@ +import type { Locale } from "../core/shared"; +import type { Messages } from "./en"; + +export type { Messages } from "./en"; + +/** + * Loads one locale's messages. + * + * The imports are dynamic so each locale becomes its own chunk - an English + * visitor never downloads the Polish strings. + */ +export const loadMessages = async (locale: Locale): Promise => { + switch (locale) { + case "en": + return (await import("./en")).en; + case "pl": + return (await import("./pl")).pl; + } +}; diff --git a/packages/i18n/src/messages/pl.ts b/packages/i18n/src/messages/pl.ts new file mode 100644 index 000000000..ce79e517b --- /dev/null +++ b/packages/i18n/src/messages/pl.ts @@ -0,0 +1,21 @@ +import type { Messages } from "./en"; + +export const pl: Messages = { + admin: { + description: "Ta sekcja nigdy nie jest tłumaczona przez adres URL.", + title: "Panel administracyjny", + }, + home: { + admin: "Panel administracyjny", + description: "Aplikacja oparta na TanStack Start.", + title: "VitNode", + }, + notFound: { + title: "Nie znaleziono strony", + }, + locale: { + en: "English", + label: "Język", + pl: "Polski", + }, +}; diff --git a/packages/i18n/tsconfig.json b/packages/i18n/tsconfig.json new file mode 100644 index 000000000..1167de4de --- /dev/null +++ b/packages/i18n/tsconfig.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vitnode/config/tsconfig", + "compilerOptions": { + "target": "ESNext", + "module": "esnext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "noEmit": true + }, + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aeb2bd21f..7346a49f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -155,13 +155,13 @@ importers: version: 1.0.0-rc.4(@opentelemetry/api@1.9.1)(postgres@3.4.9)(zod@4.4.3) fumadocs-core: specifier: ^16.11.5 - version: 16.11.5(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3) + version: 16.11.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3) fumadocs-mdx: specifier: ^15.2.0 - version: 15.2.0(@types/mdast@4.0.4)(@types/mdx@2.0.14)(@types/react@19.2.17)(fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 15.2.0(@types/mdast@4.0.4)(@types/mdx@2.0.14)(@types/react@19.2.17)(fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) fumadocs-ui: specifier: ^16.11.5 - version: 16.11.5(@types/mdx@2.0.14)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(tailwindcss@4.3.3) + version: 16.11.5(@types/mdx@2.0.14)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(tailwindcss@4.3.3) hono: specifier: ^4.12.31 version: 4.12.31 @@ -266,6 +266,67 @@ importers: specifier: ^4.4.3 version: 4.4.3 + apps/web: + dependencies: + '@fontsource-variable/geist': + specifier: ^5.3.0 + version: 5.3.0 + '@tanstack/react-query': + specifier: ^5.101.4 + version: 5.101.4(react@19.2.8) + '@tanstack/react-router': + specifier: 1.170.31 + version: 1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/react-start': + specifier: 1.168.48 + version: 1.168.48(crossws@0.4.12(srvx@0.11.22))(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@vitnode/i18n': + specifier: workspace:* + version: link:../../packages/i18n + react: + specifier: ^19.2.8 + version: 19.2.8 + react-dom: + specifier: ^19.2.8 + version: 19.2.8(react@19.2.8) + use-intl: + specifier: ^4.13.7 + version: 4.13.7(react@19.2.8) + devDependencies: + '@tailwindcss/vite': + specifier: ^4.3.3 + version: 4.3.3(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@types/node': + specifier: ^26.1.1 + version: 26.1.1 + '@types/react': + specifier: ^19.2.17 + version: 19.2.17 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.17) + '@vitejs/plugin-react': + specifier: 6.0.4 + version: 6.0.4(babel-plugin-react-compiler@1.0.0)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@vitnode/config': + specifier: workspace:* + version: link:../../packages/config + eslint: + specifier: ^10.7.0 + version: 10.7.0(jiti@2.7.0) + nitro: + specifier: ^3.0.260610-beta + version: 3.0.260610-beta(chokidar@5.0.0)(dotenv@17.4.2)(jiti@2.7.0)(lru-cache@11.5.2)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + tailwindcss: + specifier: ^4.3.3 + version: 4.3.3 + typescript: + specifier: ^6.0.3 + version: 6.0.3 + vite: + specifier: 8.1.5 + version: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + packages/config: dependencies: '@eslint-react/eslint-plugin': @@ -374,6 +435,37 @@ importers: specifier: ^6.0.3 version: 6.0.3 + packages/i18n: + dependencies: + use-intl: + specifier: ^4.13.7 + version: 4.13.7(react@19.2.8) + devDependencies: + '@tanstack/react-query': + specifier: ^5.101.4 + version: 5.101.4(react@19.2.8) + '@tanstack/react-router': + specifier: 1.170.31 + version: 1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/react-start': + specifier: 1.168.48 + version: 1.168.48(crossws@0.4.12(srvx@0.11.22))(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@types/react': + specifier: ^19.2.17 + version: 19.2.17 + '@vitnode/config': + specifier: workspace:* + version: link:../config + eslint: + specifier: ^10.7.0 + version: 10.7.0(jiti@2.7.0) + react: + specifier: ^19.2.8 + version: 19.2.8 + typescript: + specifier: ^6.0.3 + version: 6.0.3 + packages/node-cron: dependencies: node-cron: @@ -608,7 +700,7 @@ importers: version: 4.12.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8) react-scan: specifier: ^0.5.7 - version: 0.5.7(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(esbuild@0.27.7)(eslint@10.7.0(jiti@2.7.0))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.27.7)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 0.5.7(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(esbuild@0.27.7)(eslint@10.7.0(jiti@2.7.0))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.27.7)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) recharts: specifier: ^3.10.0 version: 3.10.0(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react-is@17.0.2)(react@19.2.8)(redux@5.0.1) @@ -1044,6 +1136,10 @@ packages: resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} engines: {node: '>=18.0.0'} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -1337,9 +1433,15 @@ packages: '@emnapi/core@1.11.1': resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} + '@emnapi/runtime@1.11.1': resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + '@emnapi/wasi-threads@1.2.2': resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} @@ -1923,6 +2025,9 @@ packages: '@floating-ui/utils@0.2.12': resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} + '@fontsource-variable/geist@5.3.0': + resolution: {integrity: sha512-j0m+vLQuG5XAYoHtGCVu0spvlGreR3EzpECUVzkFmI1mTVnAO38l/NEPDCFgZ177JxzYJCLSmTQibIiYPilGrA==} + '@formatjs/fast-memoize@3.1.7': resolution: {integrity: sha512-zXfhLpvA6T7+efdt9JLbBwZ00tT7NsBMDVnDu8rpHeNNv8KfRZAMo2gkG0k9lK/Nzc//3kJ9pImsfuJxk3KhUA==} @@ -2736,6 +2841,22 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@oozcitak/dom@2.0.2': + resolution: {integrity: sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w==} + engines: {node: '>=20.0'} + + '@oozcitak/infra@2.0.2': + resolution: {integrity: sha512-2g+E7hoE2dgCz/APPOEK5s3rMhJvNxSMBrP+U+j1OWsIbtSpWxxlUjq1lU8RIsFJNYv7NMlnVsCuHcUzJW+8vA==} + engines: {node: '>=20.0'} + + '@oozcitak/url@3.0.0': + resolution: {integrity: sha512-ZKfET8Ak1wsLAiLWNfFkZc/BraDccuTJKR6svTYc7sVjbR+Iu0vtXdiDMY4o6jaFl5TW2TlS7jbLl4VovtAJWQ==} + engines: {node: '>=20.0'} + + '@oozcitak/util@10.0.0': + resolution: {integrity: sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA==} + engines: {node: '>=20.0'} + '@opentelemetry/api-logs@0.220.0': resolution: {integrity: sha512-CmVa4ImJ+ynfrPMNaAXHET6Bhb44SwzmfyVJFq9ni2jgXJR/l7C6gfVFddNmHP+ZOkP9cf4f9DBe68qVLTHc9w==} engines: {node: '>=8.0.0'} @@ -4053,18 +4174,36 @@ packages: cpu: [arm64] os: [darwin] + '@swc/core-darwin-arm64@1.15.47': + resolution: {integrity: sha512-GsoMtan3ojGGMGFbl31mmRu5ctZ56re8grGE8mO/OHJ8O+JRkzod02fe7X6ZQ8JvamA3imkEkx/h3u+vsOgPgA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + '@swc/core-darwin-x64@1.15.46': resolution: {integrity: sha512-4Tj4ppVIPCmUMpmGFiGtyEriwLyJ+yi/US4WfBrP/ok8COGddDZXLEzQETnKyK46mjvr1v0jevrS23zjoff7vA==} engines: {node: '>=10'} cpu: [x64] os: [darwin] + '@swc/core-darwin-x64@1.15.47': + resolution: {integrity: sha512-leTi7Rx3KF4zcC637iqWgk9SoV8VXAD8ppQYXsep63px5A/UftOcxLN1pmr8Z1si/YvX90ompP/rHgpYkgwXWg==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + '@swc/core-linux-arm-gnueabihf@1.15.46': resolution: {integrity: sha512-i8tUGnNjyOgMmfmgFSg4aeJLQoFyfpIHK5FjpQAwpRyQIqEUB2w1e8zIDQzY1WhOxx8NoS1S5iUL813Un4Sf5A==} engines: {node: '>=10'} cpu: [arm] os: [linux] + '@swc/core-linux-arm-gnueabihf@1.15.47': + resolution: {integrity: sha512-hBqHuoWKKIsKmDBn9qVeWqj5GWZhtlcczVaqQmNRXsDfq+voR5CxKRfamA367QjJXtceYuliLFfEL8QsskRM2g==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + '@swc/core-linux-arm64-gnu@1.15.46': resolution: {integrity: sha512-c0OnhqzdhfOvv6qhNCcByepB+sNYOGZyhtr2Qa6ZCHvAWTYhSRw4j/u92Stue9PbZ/6q74b9nHzi76+kVzqQHQ==} engines: {node: '>=10'} @@ -4072,6 +4211,13 @@ packages: os: [linux] libc: [glibc] + '@swc/core-linux-arm64-gnu@1.15.47': + resolution: {integrity: sha512-TBxvRz+B4K205TWHHZxWVxkC2RFNP/Mz3PNcECBos5PsKwxjg3QSJzdoebr0VCf0Bfh8HOPldKxAP/8XkFe9gA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@swc/core-linux-arm64-musl@1.15.46': resolution: {integrity: sha512-imyRpNEcUzFQFV2LE4jL68ErvmKEuZCbvZru77iQREunJ+bR4i658cupTgtG1mLYM3F1Tzy3Sb9xYb02KghWTg==} engines: {node: '>=10'} @@ -4079,6 +4225,13 @@ packages: os: [linux] libc: [musl] + '@swc/core-linux-arm64-musl@1.15.47': + resolution: {integrity: sha512-3Yu3Uq/VgytqsPjTMbkPU1ExADytbdWbruJYhA584E9jrpE2Ki+R6VVPoZCeAVk1Cb7QxcRTgblw6bSa6a/R+w==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [musl] + '@swc/core-linux-ppc64-gnu@1.15.46': resolution: {integrity: sha512-ctEfcl/HcUeomK33cbySiHZm98GEDIxTm1EkpBsYCiHxElYBzvTXVeuQT2YwbUXn9XCrjiw4ipyUNk33k26qRg==} engines: {node: '>=10'} @@ -4086,6 +4239,13 @@ packages: os: [linux] libc: [glibc] + '@swc/core-linux-ppc64-gnu@1.15.47': + resolution: {integrity: sha512-wfdMi5IaOaNtmh2/6geRoxIdNfqylUZFdtzTKS655y1axWfIWyx7As74vv0wVdjeCIZ3WmCI9odDd4rUttXOSQ==} + engines: {node: '>=10'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@swc/core-linux-s390x-gnu@1.15.46': resolution: {integrity: sha512-DxlMdnt84TtRVTv7WL/thWyz9+QU8QZNNoAP9rrk0P68LziuhfePp8MjQ44zIprpTHTsEwyziIuGUUN5iSC1bQ==} engines: {node: '>=10'} @@ -4093,6 +4253,13 @@ packages: os: [linux] libc: [glibc] + '@swc/core-linux-s390x-gnu@1.15.47': + resolution: {integrity: sha512-3hHYBY0yx8Ez7GMRrkhXHQzMdR5IZA6Wq5Ee4svlgwvSECLpnAJ9+0AimEGUFDvuLwE7nV/2+PYe8+Nm4rvNcQ==} + engines: {node: '>=10'} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@swc/core-linux-x64-gnu@1.15.46': resolution: {integrity: sha512-SKxI7J6t90XPl8hRUqtJi9NfGdunN/E/vZMc7Bc0figeRdOPDBT+Tm8g7cx9xM0T0mewh2l+8dewa3Am27/P+A==} engines: {node: '>=10'} @@ -4100,6 +4267,13 @@ packages: os: [linux] libc: [glibc] + '@swc/core-linux-x64-gnu@1.15.47': + resolution: {integrity: sha512-TjfhjgP/jGCfFHYC3JQPhJA1HwErbIJ9JfREDc1KNkvY6P0LodCgKVIlQ5deeTbkG7ih3bF5PHJLuLpaZjdRyQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [glibc] + '@swc/core-linux-x64-musl@1.15.46': resolution: {integrity: sha512-qj9T6B7bosI0VEsrWOVXZN1OXxS8Tp63ywyrLxNdOycnUtLdkgYcoBsN5y8ImnDDsnwrEWZOy1e+J4xSe7mA3Q==} engines: {node: '>=10'} @@ -4107,24 +4281,49 @@ packages: os: [linux] libc: [musl] + '@swc/core-linux-x64-musl@1.15.47': + resolution: {integrity: sha512-CQpS8Ge/avfjZd0UEwG/sds83Uu32deQXcV1Jo3jD0mmvQQqtYAjpsDZXugmheeAwmt+YIuoVtVHro8LMYHqsQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [musl] + '@swc/core-win32-arm64-msvc@1.15.46': resolution: {integrity: sha512-8p7l4c3LU+eA5g9Et1JPhNeMC1oQwXTGU+uah8DPIBX7YXzqswvaBtyKVmXefVGi/DJU1x3YJsc3mbAp9aWzSQ==} engines: {node: '>=10'} cpu: [arm64] os: [win32] + '@swc/core-win32-arm64-msvc@1.15.47': + resolution: {integrity: sha512-0W8IKHsUTYiT7G2RqtOoVWk+89yzZikIiDUb/sCK6BmQDBhN91hQSfyUtW12jhEWLzYgcfmisfsZrmZE+84U1A==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + '@swc/core-win32-ia32-msvc@1.15.46': resolution: {integrity: sha512-tUEnfr3Bn9u6FOjUb3PN9p+09qZC2j+wNDLKHzXXZn22rqGcUqR/ohCRSS+nG9B9+X+U+3FewNEHJkTmdIvMjQ==} engines: {node: '>=10'} cpu: [ia32] os: [win32] + '@swc/core-win32-ia32-msvc@1.15.47': + resolution: {integrity: sha512-ZIp49d2Z4/ka2jO9otOg4hDvTdPmp86kVOgS2M5FCPI7eKKZ1W0boxWn+8XeZrfERtFGW0AlMRm4JhlJa7l3NA==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + '@swc/core-win32-x64-msvc@1.15.46': resolution: {integrity: sha512-Vux7UDzBJYQggSuPfcl2w9iu+IJpgpRCxHzgCaVkELnAXAE4XZMOTX9HNcaNiwfeIDqdu2rkr69RuDm6wY8neA==} engines: {node: '>=10'} cpu: [x64] os: [win32] + '@swc/core-win32-x64-msvc@1.15.47': + resolution: {integrity: sha512-2h8Iek95vnixkBRCo+H8p09+Q5ll2NgSMFrWTy0iKt7+/t+8/T5mBpiT6c0ZxSS7wcWjwZ9sGZkK70tTSYHdDw==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + '@swc/core@1.15.46': resolution: {integrity: sha512-Ri3em2mBpq3h2zSPliCYl63otDGqek8PPEfv2nWgRQEbZ/VBCNyypVTVQ6cEbTCXBhy+WE2T3fQb08moIyuYaw==} engines: {node: '>=10'} @@ -4247,6 +4446,15 @@ packages: '@tailwindcss/postcss@4.3.3': resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==} + '@tailwindcss/vite@4.3.3': + resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + + '@tanstack/history@1.162.1': + resolution: {integrity: sha512-DR9t6lfLVdrjgCwpglrR9DR7Ok8/HlXjcOE+goWXF3zyuLUO/ug7vMbSFxTqrQTtbRghJfyhmIZ0S6LhPIy44w==} + engines: {node: '>=20.19'} + '@tanstack/query-core@5.101.4': resolution: {integrity: sha512-gNwcvOJcRbLWPOLG/2OBm+zM+Yv+MKsXKEOWC57USuZDEsI71hEErQsiEGx5wX9rzWWkfwM0fVSPoiIFSsxfiw==} @@ -4255,6 +4463,135 @@ packages: peerDependencies: react: ^18 || ^19 + '@tanstack/react-router@1.170.31': + resolution: {integrity: sha512-jqITLcf9Y+es9Wm7fD7XfXFGKk1Fujm+okGqHtr+UhISnQuyLQ8d3frsJlIN0Np1doYoeb5weozSkv72+EZ5bw==} + engines: {node: '>=20.19'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-start-client@1.168.29': + resolution: {integrity: sha512-YhEtx3EwbsLUWXSdwclz/C/AlDqPNoNMoNTEHulYDruaMAKNbFeWsDgBbHv/aE6P2P3shAMFYAT1cVHZM1WcJQ==} + engines: {node: '>=22.12.0'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-start-rsc@0.1.47': + resolution: {integrity: sha512-Tr01FbuRRpHSwkLjyfg7OotXgrJ4ufDjGKuk9HpLe7a2ouEs1Iq/kC2RKY0alvCYX+cpYFVayoyxNZCeybCTNQ==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@rspack/core': '>=2.0.0-0' + '@vitejs/plugin-rsc': '>=0.5.30' + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + react-server-dom-rspack: '>=0.0.2' + peerDependenciesMeta: + '@rspack/core': + optional: true + '@vitejs/plugin-rsc': + optional: true + react-server-dom-rspack: + optional: true + + '@tanstack/react-start-server@1.167.36': + resolution: {integrity: sha512-v22xUhNENr0u67AIDbfbJgmQwMGqcrwdqqNI44Nd605G4DGTA7W1KPbea8bBjPkHxf5I+FTKL8Nb56w2Sb/Gpw==} + engines: {node: '>=22.12.0'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-start@1.168.48': + resolution: {integrity: sha512-ANBtq/phgjPzfwgnB40kyREQGhrLONueJg9y+oFuGIuUVaTfqWjX5y820jsJ0FiZ94JU+WIV6GebVhphNhuYjg==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@rsbuild/core': ^2.0.0 + '@vitejs/plugin-rsc': '*' + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + vite: '>=7.0.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + '@vitejs/plugin-rsc': + optional: true + vite: + optional: true + + '@tanstack/react-store@0.9.3': + resolution: {integrity: sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@tanstack/router-core@1.171.26': + resolution: {integrity: sha512-VymmPSs/93szHur/7PBygT6tRbmfcNO1xR46Wn/JVHeBqVduLPCuxBeJEgfVmVq8E4hSklPEh8i6qGXQd6WRqA==} + engines: {node: '>=20.19'} + + '@tanstack/router-generator@1.167.32': + resolution: {integrity: sha512-KKPWUMUda7JYil+uDQPrX4ecyoXP9J3DesdpavOWpGCavsiAd6cxH6yq18krLGa1j20qmPJc10LJSLOOFia5tQ==} + engines: {node: '>=20.19'} + + '@tanstack/router-plugin@1.168.34': + resolution: {integrity: sha512-WsXLQU8tQmoTyoQRB1JI3lGg5wnwo6VB2R8D2RQbtCVlUi3bjreSNgZSJ7Ghw06ZoUyNMO+Csiqf679nNnzN+w==} + engines: {node: '>=20.19'} + peerDependencies: + '@rsbuild/core': '>=1.0.2 || ^2.0.0' + '@tanstack/react-router': ^1.170.31 + vite: '>=5.0.0 || >=6.0.0 || >=7.0.0 || >=8.0.0' + vite-plugin-solid: ^2.11.10 || ^3.0.0-0 + webpack: '>=5.92.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + '@tanstack/react-router': + optional: true + vite: + optional: true + vite-plugin-solid: + optional: true + webpack: + optional: true + + '@tanstack/router-utils@1.162.2': + resolution: {integrity: sha512-hTWqJtqIFFdvuCl8WXNyrodp2L9zo2G37xKRrcVmVRWpAB2h+U1LuRAfS4tsFTiWOIoE/B+WDVFB8JpoEdw6jQ==} + engines: {node: '>=20.19'} + + '@tanstack/start-client-core@1.170.26': + resolution: {integrity: sha512-a8SmEQ4gIeWDHBSqy1ePFNwXu0kHTPCoMiEdE0eKRBITVsexfEX8yKvqxLi66cF6aGCmDIkndbth3yB7R344zQ==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-fn-stubs@1.162.0': + resolution: {integrity: sha512-QWfUZ3Yo923tdQn38LyKMU8rcTw69zc+T4dAvgTWV4O56SqFRsGfS0lSWIMhJRwXIx/bvdi7nTUBDdZtTHtpTQ==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-plugin-core@1.171.38': + resolution: {integrity: sha512-ldRjxosoTyWG0xP6CLo/DkiuENt668se7oZwAJuRMtRBGBDzhMVMwFnS86P2qgnpj/BQVFebVpXMVfzeH7tvDw==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@rsbuild/core': ^2.0.0 + vite: '>=7.0.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + vite: + optional: true + + '@tanstack/start-server-core@1.169.30': + resolution: {integrity: sha512-knlKOPsHyDbGKgP1pfUowtObZIKS9zRI6vl7dzbA8D/NJo6dMdDdqGcDf4PINqREW8hCHdkB4At0y1/Mk+L2SQ==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-storage-context@1.167.28': + resolution: {integrity: sha512-ZGl6bEXW5m77VVtWMt/naEBVoIeQkXYgF4UgiJM/3z3e1wbRzaoW7Dnc4HW+hoBPOOdfiVVNx31RT2ARnXWAiQ==} + engines: {node: '>=22.12.0'} + + '@tanstack/store@0.9.3': + resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==} + + '@tanstack/virtual-file-routes@1.162.0': + resolution: {integrity: sha512-uhOeFyxLcU41HzvrxsGpiWdcMbScY1EDgbZ5K7DVRMYInbLYWAC0EA/kx9wXAoSM8q82bUG2hRl8+EAjE6XAbA==} + engines: {node: '>=20.19'} + '@tiptap/core@3.28.0': resolution: {integrity: sha512-gUuD5WAYfbDxNSSJya/emh2KSzXZXLUYKW4fEnc1AQ5FE2twzh4LJ9UlKFIawigrUCAksWI5Fy1hRbv+5m4ZdQ==} peerDependencies: @@ -4857,6 +5194,10 @@ packages: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} + ansis@4.3.1: + resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==} + engines: {node: '>=14'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -4952,6 +5293,9 @@ packages: react-native-b4a: optional: true + babel-dead-code-elimination@1.0.12: + resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==} + babel-plugin-react-compiler@1.0.0: resolution: {integrity: sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==} @@ -5270,6 +5614,9 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-es@3.1.1: + resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==} + cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} @@ -5303,6 +5650,14 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + crossws@0.4.12: + resolution: {integrity: sha512-aypfsr6t0uNvkqaZc6zvBfXzC6pLI0/sIulpkV6RwCVtZqG5ebBzv4weImKK0VNCj91Wl9F5j7p5WU4MNrybng==} + peerDependencies: + srvx: '>=0.11.5' + peerDependenciesMeta: + srvx: + optional: true + css-in-js-utils@3.1.0: resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} @@ -5388,6 +5743,29 @@ packages: date-fns@4.4.0: resolution: {integrity: sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w==} + db0@0.3.4: + resolution: {integrity: sha512-RiXXi4WaNzPTHEOu8UPQKMooIbqOEyqA1t7Z6MsdxSCeb8iUC9ko3LcmsLmeUt2SM5bctfArZKkRQggKZz7JNw==} + peerDependencies: + '@electric-sql/pglite': '*' + '@libsql/client': '*' + better-sqlite3: '*' + drizzle-orm: '*' + mysql2: '*' + sqlite3: '*' + peerDependenciesMeta: + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + better-sqlite3: + optional: true + drizzle-orm: + optional: true + mysql2: + optional: true + sqlite3: + optional: true + debounce-fn@4.0.0: resolution: {integrity: sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==} engines: {node: '>=10'} @@ -5740,6 +6118,24 @@ packages: resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + env-runner@0.1.16: + resolution: {integrity: sha512-2LRJM4P2KLX6J83QZZrMqvgCDt/D5ea7wPcI3yYiy5cG/9rX5QwdwZFx0D7ktWnjdRyZxYjttGGorb5nFqb1CA==} + hasBin: true + peerDependencies: + '@netlify/runtime': ^4.1.23 + '@vercel/queue': '>=0.2.0' + miniflare: ^4.20260515.0 + wrangler: ^4.0.0 + peerDependenciesMeta: + '@netlify/runtime': + optional: true + '@vercel/queue': + optional: true + miniflare: + optional: true + wrangler: + optional: true + error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} @@ -6024,6 +6420,9 @@ packages: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} + exsolve@1.1.1: + resolution: {integrity: sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g==} + ext-list@2.2.2: resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} engines: {node: '>=0.10.0'} @@ -6091,6 +6490,9 @@ packages: picomatch: optional: true + fetchdts@0.1.7: + resolution: {integrity: sha512-YoZjBdafyLIop9lSxXVI33oLD5kN31q4Td+CasofLLYeLXRFeOsuOw0Uo+XNRi9PZlbfdlN2GmRtm4tCEQ9/KA==} + figures@6.1.0: resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} engines: {node: '>=18'} @@ -6410,6 +6812,26 @@ packages: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} engines: {node: '>=10'} + h3@2.0.1-rc.20: + resolution: {integrity: sha512-28ljodXuUp0fZovdiSRq4G9OgrxCztrJe5VdYzXAB7ueRvI7pIUqLU14Xi3XqdYJ/khXjfpUOOD2EQa6CmBgsg==} + engines: {node: '>=20.11.1'} + hasBin: true + peerDependencies: + crossws: ^0.4.1 + peerDependenciesMeta: + crossws: + optional: true + + h3@2.0.1-rc.22: + resolution: {integrity: sha512-Esv0DMIuPkCTSWCA0vO73vcTqwzH1wjSrAO1TXNu/K3up1sZHa9EKMapbmxCDYBeymC3fVTk4qxp7ogQWQ+KgA==} + engines: {node: '>=20.11.1'} + hasBin: true + peerDependencies: + crossws: ^0.4.1 + peerDependenciesMeta: + crossws: + optional: true + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -6474,6 +6896,9 @@ packages: resolution: {integrity: sha512-zJIHFrl6bq3RDd2YusFNCDlM8qUprxKswyi/OPzPyzKDdyBXDqWx8bZlZ7R+saTdSTatUmb3O7K4SspGPaEOQg==} engines: {node: '>=16.9.0'} + hookable@6.1.1: + resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==} + hpagent@1.2.0: resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} engines: {node: '>=14'} @@ -6509,6 +6934,9 @@ packages: resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} engines: {node: '>=10.19.0'} + httpxy@0.5.5: + resolution: {integrity: sha512-uDjmnPyp1q4Sgzf3w+J/Fc6UqcCEj0x4Wjp7OqK5dGhNeDgpyrAmnS6ey8QWrX3SWDon2DMKf9sBa5X9+CVyMA==} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -6801,6 +7229,10 @@ packages: isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + isbot@5.2.1: + resolution: {integrity: sha512-dJ+LpKyClQZ7NG+j3OensC/mAZkGpukE9YUrgPYvAZj2doVL0edfDgywTUh5CXa0o+nW9a1V9e5+CJTX8+SxRw==} + engines: {node: '>=18'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -7541,6 +7973,40 @@ packages: sass: optional: true + nf3@0.3.24: + resolution: {integrity: sha512-HxLK4bo+5jNsEETZp4w3tJblHOA9MCBY14IN9nZJJV8JDxt9yNIYxuBuLMjTAR5GFa3HL61+8VQDUrXv3/C8fw==} + + nitro@3.0.260610-beta: + resolution: {integrity: sha512-KPb4L5yaF/Rx/xoGMpgHRJvZhbhGiqbRKOwwPLCH9jKTKTsEUHLjnJas85AeCzaswqa8Wi52eQBtRsODC4PS0Q==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@vercel/queue': ^0.3.0 + dotenv: '*' + giget: '*' + jiti: ^2.7.0 + rollup: ^4.61.1 + vite: ^7 || ^8 + xml2js: ^0.6.2 + zephyr-agent: ^0.2.0 + peerDependenciesMeta: + '@vercel/queue': + optional: true + dotenv: + optional: true + giget: + optional: true + jiti: + optional: true + rollup: + optional: true + vite: + optional: true + xml2js: + optional: true + zephyr-agent: + optional: true + node-addon-api@7.1.1: resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} @@ -7613,6 +8079,15 @@ packages: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} + ocache@0.1.5: + resolution: {integrity: sha512-kNNnkkVQup/QDvmTz8Q84wc2ntiyoVHDxa6eHWKt5qdGAmFRBIxy83rxgCYEjW0x06UJ9E3P6VgM2yY4rOBH4w==} + + ofetch@2.0.0-alpha.3: + resolution: {integrity: sha512-zpYTCs2byOuft65vI3z43Dd6iSdFbOZZLb9/d21aCpx2rGastVU9dOCv0lu4ykc1Ur1anAYjDi3SUvR0vq50JA==} + + ohash@2.0.12: + resolution: {integrity: sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==} + on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -8341,6 +8816,9 @@ packages: rope-sequence@1.3.4: resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} + rou3@0.8.1: + resolution: {integrity: sha512-ePa+XGk00/3HuCqrEnK3LxJW7I0SdNg6EFzKUJG73hMAdDcOUC/i/aSz7LSDwLrGr33kal/rqOGydzwl6U7zBA==} + router@2.2.0: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} @@ -8418,6 +8896,16 @@ packages: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} + seroval-plugins@1.6.2: + resolution: {integrity: sha512-TfxuUjlbBESzUOWdTkTKqvSmav0ABym+itetDXLK6mDz8SmrpdI30aF8RTXE8Bvq+tH/1yIDkvy3W0lfQb1ipQ==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + + seroval@1.6.2: + resolution: {integrity: sha512-mPT+SD2TrlB6wvte1KkYOYUkubaTbd6pZ/6Kk3C9nxzrHmCZyhxOO7XGAeL7f+yLKZglzGtM9odUVvg/EhO+vQ==} + engines: {node: '>=10'} + serve-static@2.2.1: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} @@ -8555,6 +9043,11 @@ packages: space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + srvx@0.11.22: + resolution: {integrity: sha512-LqZxxBDMKuMAZzFzJnDCkFOrs9MZQZr0LvHiO/SuSZVdQaXD7xQ5UWTUxheJrQPve1qk9MG2B/yttUvJxw8egQ==} + engines: {node: '>=20.16.0'} + hasBin: true + stack-generator@2.0.10: resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} @@ -8955,6 +9448,9 @@ packages: resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} engines: {node: '>=20.18.1'} + unenv@2.0.0-rc.24: + resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} + unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} @@ -9024,6 +9520,80 @@ packages: webpack: optional: true + unstorage@2.0.0-alpha.7: + resolution: {integrity: sha512-ELPztchk2zgFJnakyodVY3vJWGW9jy//keJ32IOJVGUMyaPydwcA1FtVvWqT0TNRch9H+cMNEGllfVFfScImog==} + peerDependencies: + '@azure/app-configuration': ^1.11.0 + '@azure/cosmos': ^4.9.1 + '@azure/data-tables': ^13.3.2 + '@azure/identity': ^4.13.0 + '@azure/keyvault-secrets': ^4.10.0 + '@azure/storage-blob': ^12.31.0 + '@capacitor/preferences': ^6 || ^7 || ^8 + '@deno/kv': '>=0.13.0' + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 + '@planetscale/database': ^1.19.0 + '@upstash/redis': ^1.36.2 + '@vercel/blob': '>=0.27.3' + '@vercel/functions': ^2.2.12 || ^3.0.0 + '@vercel/kv': ^1.0.1 + aws4fetch: ^1.0.20 + chokidar: ^4 || ^5 + db0: '>=0.3.4' + idb-keyval: ^6.2.2 + ioredis: ^5.9.3 + lru-cache: ^11.2.6 + mongodb: ^6 || ^7 + ofetch: '*' + uploadthing: ^7.7.4 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@deno/kv': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/blob': + optional: true + '@vercel/functions': + optional: true + '@vercel/kv': + optional: true + aws4fetch: + optional: true + chokidar: + optional: true + db0: + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + lru-cache: + optional: true + mongodb: + optional: true + ofetch: + optional: true + uploadthing: + optional: true + update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -9145,6 +9715,14 @@ packages: yaml: optional: true + vitefu@1.1.3: + resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + vite: + optional: true + vitest@4.1.10: resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -9312,6 +9890,10 @@ packages: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} + xmlbuilder2@4.0.3: + resolution: {integrity: sha512-bx8Q1STctnNaaDymWnkfQLKofs0mGNN7rLLapJlGuV3VlvegD7Ls4ggMjE3aUSWItCCzU0PEv45lI87iSigiCA==} + engines: {node: '>=20.0'} + xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} @@ -9619,6 +10201,12 @@ snapshots: '@aws/lambda-invoke-store@0.3.0': {} + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -9983,11 +10571,22 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/core@1.11.2': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.11.1': dependencies: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/wasi-threads@1.2.2': dependencies: tslib: 2.8.1 @@ -10366,6 +10965,8 @@ snapshots: '@floating-ui/utils@0.2.12': {} + '@fontsource-variable/geist@5.3.0': {} + '@formatjs/fast-memoize@3.1.7': {} '@formatjs/icu-messageformat-parser@3.5.15': @@ -10912,6 +11513,13 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 + optional: true + '@next/bundle-analyzer@16.3.1': dependencies: webpack-bundle-analyzer: 4.10.1 @@ -10983,6 +11591,23 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@oozcitak/dom@2.0.2': + dependencies: + '@oozcitak/infra': 2.0.2 + '@oozcitak/url': 3.0.0 + '@oozcitak/util': 10.0.0 + + '@oozcitak/infra@2.0.2': + dependencies: + '@oozcitak/util': 10.0.0 + + '@oozcitak/url@3.0.0': + dependencies: + '@oozcitak/infra': 2.0.2 + '@oozcitak/util': 10.0.0 + + '@oozcitak/util@10.0.0': {} + '@opentelemetry/api-logs@0.220.0': dependencies: '@opentelemetry/api': 1.9.1 @@ -11137,12 +11762,11 @@ snapshots: '@oxc-resolver/binding-openharmony-arm64@11.24.2': optional: true - '@oxc-resolver/binding-wasm32-wasi@11.24.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@oxc-resolver/binding-wasm32-wasi@11.24.2': dependencies: - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) optional: true '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': @@ -12006,39 +12630,75 @@ snapshots: '@swc/core-darwin-arm64@1.15.46': optional: true + '@swc/core-darwin-arm64@1.15.47': + optional: true + '@swc/core-darwin-x64@1.15.46': optional: true + '@swc/core-darwin-x64@1.15.47': + optional: true + '@swc/core-linux-arm-gnueabihf@1.15.46': optional: true + '@swc/core-linux-arm-gnueabihf@1.15.47': + optional: true + '@swc/core-linux-arm64-gnu@1.15.46': optional: true + '@swc/core-linux-arm64-gnu@1.15.47': + optional: true + '@swc/core-linux-arm64-musl@1.15.46': optional: true + '@swc/core-linux-arm64-musl@1.15.47': + optional: true + '@swc/core-linux-ppc64-gnu@1.15.46': optional: true + '@swc/core-linux-ppc64-gnu@1.15.47': + optional: true + '@swc/core-linux-s390x-gnu@1.15.46': optional: true + '@swc/core-linux-s390x-gnu@1.15.47': + optional: true + '@swc/core-linux-x64-gnu@1.15.46': optional: true + '@swc/core-linux-x64-gnu@1.15.47': + optional: true + '@swc/core-linux-x64-musl@1.15.46': optional: true + '@swc/core-linux-x64-musl@1.15.47': + optional: true + '@swc/core-win32-arm64-msvc@1.15.46': optional: true + '@swc/core-win32-arm64-msvc@1.15.47': + optional: true + '@swc/core-win32-ia32-msvc@1.15.46': optional: true + '@swc/core-win32-ia32-msvc@1.15.47': + optional: true + '@swc/core-win32-x64-msvc@1.15.46': optional: true + '@swc/core-win32-x64-msvc@1.15.47': + optional: true + '@swc/core@1.15.46(@swc/helpers@0.5.23)': dependencies: '@swc/counter': 0.1.3 @@ -12063,6 +12723,18 @@ snapshots: '@swc/counter': 0.1.3 '@swc/types': 0.1.27 optionalDependencies: + '@swc/core-darwin-arm64': 1.15.47 + '@swc/core-darwin-x64': 1.15.47 + '@swc/core-linux-arm-gnueabihf': 1.15.47 + '@swc/core-linux-arm64-gnu': 1.15.47 + '@swc/core-linux-arm64-musl': 1.15.47 + '@swc/core-linux-ppc64-gnu': 1.15.47 + '@swc/core-linux-s390x-gnu': 1.15.47 + '@swc/core-linux-x64-gnu': 1.15.47 + '@swc/core-linux-x64-musl': 1.15.47 + '@swc/core-win32-arm64-msvc': 1.15.47 + '@swc/core-win32-ia32-msvc': 1.15.47 + '@swc/core-win32-x64-msvc': 1.15.47 '@swc/helpers': 0.5.23 '@swc/counter@0.1.3': {} @@ -12148,6 +12820,15 @@ snapshots: postcss: 8.5.22 tailwindcss: 4.3.3 + '@tailwindcss/vite@4.3.3(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': + dependencies: + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + tailwindcss: 4.3.3 + vite: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + + '@tanstack/history@1.162.1': {} + '@tanstack/query-core@5.101.4': {} '@tanstack/react-query@5.101.4(react@19.2.8)': @@ -12155,6 +12836,219 @@ snapshots: '@tanstack/query-core': 5.101.4 react: 19.2.8 + '@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + dependencies: + '@tanstack/history': 1.162.1 + '@tanstack/react-store': 0.9.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/router-core': 1.171.26 + isbot: 5.2.1 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + + '@tanstack/react-start-client@1.168.29(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + dependencies: + '@tanstack/react-router': 1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/router-core': 1.171.26 + '@tanstack/start-client-core': 1.170.26 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + + '@tanstack/react-start-rsc@0.1.47(crossws@0.4.12(srvx@0.11.22))(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': + dependencies: + '@tanstack/react-router': 1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/router-core': 1.171.26 + '@tanstack/router-utils': 1.162.2 + '@tanstack/start-client-core': 1.170.26 + '@tanstack/start-fn-stubs': 1.162.0 + '@tanstack/start-plugin-core': 1.171.38(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(crossws@0.4.12(srvx@0.11.22))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@tanstack/start-storage-context': 1.167.28 + pathe: 2.0.3 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + transitivePeerDependencies: + - '@farmfe/core' + - '@rsbuild/core' + - bun-types-no-globals + - crossws + - esbuild + - rolldown + - rollup + - supports-color + - unloader + - vite + - vite-plugin-solid + - webpack + + '@tanstack/react-start-server@1.167.36(crossws@0.4.12(srvx@0.11.22))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + dependencies: + '@tanstack/react-router': 1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/router-core': 1.171.26 + '@tanstack/start-server-core': 1.169.30(crossws@0.4.12(srvx@0.11.22)) + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + transitivePeerDependencies: + - crossws + + '@tanstack/react-start@1.168.48(crossws@0.4.12(srvx@0.11.22))(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': + dependencies: + '@tanstack/react-router': 1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/react-start-client': 1.168.29(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/react-start-rsc': 0.1.47(crossws@0.4.12(srvx@0.11.22))(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@tanstack/react-start-server': 1.167.36(crossws@0.4.12(srvx@0.11.22))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@tanstack/router-utils': 1.162.2 + '@tanstack/start-client-core': 1.170.26 + '@tanstack/start-plugin-core': 1.171.38(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(crossws@0.4.12(srvx@0.11.22))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@tanstack/start-server-core': 1.169.30(crossws@0.4.12(srvx@0.11.22)) + pathe: 2.0.3 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + optionalDependencies: + vite: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - crossws + - esbuild + - react-server-dom-rspack + - rolldown + - rollup + - supports-color + - unloader + - vite-plugin-solid + - webpack + + '@tanstack/react-store@0.9.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + dependencies: + '@tanstack/store': 0.9.3 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + use-sync-external-store: 1.6.0(react@19.2.8) + + '@tanstack/router-core@1.171.26': + dependencies: + '@tanstack/history': 1.162.1 + cookie-es: 3.1.1 + seroval: 1.6.2 + seroval-plugins: 1.6.2(seroval@1.6.2) + + '@tanstack/router-generator@1.167.32': + dependencies: + '@babel/types': 7.29.7 + '@tanstack/router-core': 1.171.26 + '@tanstack/router-utils': 1.162.2 + '@tanstack/virtual-file-routes': 1.162.0 + jiti: 2.7.0 + magic-string: 0.30.21 + prettier: 3.9.6 + zod: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@tanstack/router-plugin@1.168.34(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': + dependencies: + '@babel/core': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + '@tanstack/router-core': 1.171.26 + '@tanstack/router-generator': 1.167.32 + '@tanstack/router-utils': 1.162.2 + chokidar: 5.0.0 + unplugin: 3.3.0(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + zod: 4.4.3 + optionalDependencies: + '@tanstack/react-router': 1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + vite: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - rolldown + - rollup + - supports-color + - unloader + + '@tanstack/router-utils@1.162.2': + dependencies: + '@babel/generator': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + ansis: 4.3.1 + babel-dead-code-elimination: 1.0.12 + diff: 8.0.4 + pathe: 2.0.3 + tinyglobby: 0.2.17 + transitivePeerDependencies: + - supports-color + + '@tanstack/start-client-core@1.170.26': + dependencies: + '@tanstack/router-core': 1.171.26 + '@tanstack/start-fn-stubs': 1.162.0 + '@tanstack/start-storage-context': 1.167.28 + seroval: 1.6.2 + + '@tanstack/start-fn-stubs@1.162.0': {} + + '@tanstack/start-plugin-core@1.171.38(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(crossws@0.4.12(srvx@0.11.22))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/core': 7.29.7 + '@babel/types': 7.29.7 + '@tanstack/router-core': 1.171.26 + '@tanstack/router-generator': 1.167.32 + '@tanstack/router-plugin': 1.168.34(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + '@tanstack/router-utils': 1.162.2 + '@tanstack/start-server-core': 1.169.30(crossws@0.4.12(srvx@0.11.22)) + exsolve: 1.1.1 + lightningcss: 1.33.0 + pathe: 2.0.3 + picomatch: 4.0.5 + seroval: 1.6.2 + source-map: 0.7.6 + srvx: 0.11.22 + tinyglobby: 0.2.17 + ufo: 1.6.4 + vitefu: 1.1.3(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) + xmlbuilder2: 4.0.3 + zod: 4.4.3 + optionalDependencies: + vite: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - '@tanstack/react-router' + - bun-types-no-globals + - crossws + - esbuild + - rolldown + - rollup + - supports-color + - unloader + - vite-plugin-solid + - webpack + + '@tanstack/start-server-core@1.169.30(crossws@0.4.12(srvx@0.11.22))': + dependencies: + '@tanstack/history': 1.162.1 + '@tanstack/router-core': 1.171.26 + '@tanstack/start-client-core': 1.170.26 + '@tanstack/start-storage-context': 1.167.28 + fetchdts: 0.1.7 + h3-v2: h3@2.0.1-rc.20(crossws@0.4.12(srvx@0.11.22)) + seroval: 1.6.2 + transitivePeerDependencies: + - crossws + + '@tanstack/start-storage-context@1.167.28': + dependencies: + '@tanstack/router-core': 1.171.26 + + '@tanstack/store@0.9.3': {} + + '@tanstack/virtual-file-routes@1.162.0': {} + '@tiptap/core@3.28.0(@tiptap/pm@3.28.0)': dependencies: '@tiptap/pm': 3.28.0 @@ -12852,6 +13746,8 @@ snapshots: ansi-regex@6.2.2: {} + ansis@4.3.1: {} + any-promise@1.3.0: {} anymatch@3.1.3: @@ -12952,6 +13848,15 @@ snapshots: b4a@1.8.1: {} + babel-dead-code-elimination@1.0.12: + dependencies: + '@babel/core': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + babel-plugin-react-compiler@1.0.0: dependencies: '@babel/types': 7.29.7 @@ -13238,6 +14143,8 @@ snapshots: convert-source-map@2.0.0: {} + cookie-es@3.1.1: {} + cookie-signature@1.2.2: {} cookie@0.7.2: {} @@ -13270,6 +14177,10 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crossws@0.4.12(srvx@0.11.22): + optionalDependencies: + srvx: 0.11.22 + css-in-js-utils@3.1.0: dependencies: hyphenate-style-name: 1.1.0 @@ -13355,6 +14266,8 @@ snapshots: date-fns@4.4.0: {} + db0@0.3.4: {} + debounce-fn@4.0.0: dependencies: mimic-fn: 3.1.0 @@ -13416,17 +14329,14 @@ snapshots: dequal@2.0.3: {} - deslop-js@0.9.12(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1): + deslop-js@0.9.12: dependencies: '@oxc-project/types': 0.143.0 fast-glob: 3.3.3 minimatch: 10.2.5 oxc-parser: 0.143.0 - oxc-resolver: 11.24.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + oxc-resolver: 11.24.2 typescript: 5.9.3 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' detect-libc@2.1.2: {} @@ -13553,6 +14463,13 @@ snapshots: env-paths@3.0.0: {} + env-runner@0.1.16: + dependencies: + crossws: 0.4.12(srvx@0.11.22) + exsolve: 1.1.1 + httpxy: 0.5.5 + srvx: 0.11.22 + error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 @@ -14122,6 +15039,8 @@ snapshots: transitivePeerDependencies: - supports-color + exsolve@1.1.1: {} + ext-list@2.2.2: dependencies: mime-db: 1.54.0 @@ -14179,6 +15098,8 @@ snapshots: optionalDependencies: picomatch: 4.0.5 + fetchdts@0.1.7: {} + figures@6.1.0: dependencies: is-unicode-supported: 2.1.0 @@ -14278,7 +15199,7 @@ snapshots: fsevents@2.3.3: optional: true - fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3): + fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3): dependencies: '@orama/orama': 3.1.18 estree-util-value-to-estree: 3.5.0 @@ -14299,6 +15220,7 @@ snapshots: yaml: 2.9.0 optionalDependencies: '@mdx-js/mdx': 3.1.1 + '@tanstack/react-router': 1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.5 '@types/mdast': 4.0.4 @@ -14311,14 +15233,14 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-mdx@15.2.0(@types/mdast@4.0.4)(@types/mdx@2.0.14)(@types/react@19.2.17)(fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): + fumadocs-mdx@15.2.0(@types/mdast@4.0.4)(@types/mdx@2.0.14)(@types/react@19.2.17)(fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): dependencies: '@mdx-js/mdx': 3.1.1 '@standard-schema/spec': 1.1.0 chokidar: 5.0.0 esbuild: 0.28.1 estree-util-value-to-estree: 3.5.0 - fumadocs-core: 16.11.5(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3) + fumadocs-core: 16.11.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3) github-slugger: 2.0.0 magic-string: 0.30.21 mdast-util-mdx: 3.0.0 @@ -14344,7 +15266,7 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-ui@16.11.5(@types/mdx@2.0.14)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(tailwindcss@4.3.3): + fumadocs-ui@16.11.5(@types/mdx@2.0.14)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.11.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(tailwindcss@4.3.3): dependencies: '@fuma-translate/react': 1.0.2(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@fumadocs/tailwind': 0.1.1(tailwindcss@4.3.3) @@ -14360,7 +15282,7 @@ snapshots: '@radix-ui/react-tabs': 1.1.18(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) class-variance-authority: 0.7.1 cnfast: 0.0.8 - fumadocs-core: 16.11.5(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3) + fumadocs-core: 16.11.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.31(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/estree-jsx@1.0.5)(@types/hast@3.0.5)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.25.0(react@19.2.8))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(@types/node@26.1.1)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(zod@4.4.3) lucide-react: 1.25.0(react@19.2.8) motion: 12.42.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8) next-themes: 0.4.6(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -14502,6 +15424,20 @@ snapshots: dependencies: duplexer: 0.1.2 + h3@2.0.1-rc.20(crossws@0.4.12(srvx@0.11.22)): + dependencies: + rou3: 0.8.1 + srvx: 0.11.22 + optionalDependencies: + crossws: 0.4.12(srvx@0.11.22) + + h3@2.0.1-rc.22(crossws@0.4.12(srvx@0.11.22)): + dependencies: + rou3: 0.8.1 + srvx: 0.11.22 + optionalDependencies: + crossws: 0.4.12(srvx@0.11.22) + has-bigints@1.1.0: {} has-flag@4.0.0: {} @@ -14640,6 +15576,8 @@ snapshots: hono@4.12.31: {} + hookable@6.1.1: {} + hpagent@1.2.0: {} html-encoding-sniffer@6.0.0: @@ -14684,6 +15622,8 @@ snapshots: quick-lru: 5.1.1 resolve-alpn: 1.2.1 + httpxy@0.5.5: {} + human-signals@2.1.0: {} human-signals@5.0.0: {} @@ -14930,6 +15870,8 @@ snapshots: isarray@2.0.5: {} + isbot@5.2.1: {} + isexe@2.0.0: {} isexe@3.1.5: {} @@ -15852,6 +16794,61 @@ snapshots: - '@types/node' - babel-plugin-macros + nf3@0.3.24: {} + + nitro@3.0.260610-beta(chokidar@5.0.0)(dotenv@17.4.2)(jiti@2.7.0)(lru-cache@11.5.2)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): + dependencies: + consola: 3.4.2 + crossws: 0.4.12(srvx@0.11.22) + db0: 0.3.4 + env-runner: 0.1.16 + h3: 2.0.1-rc.22(crossws@0.4.12(srvx@0.11.22)) + hookable: 6.1.1 + nf3: 0.3.24 + ocache: 0.1.5 + ofetch: 2.0.0-alpha.3 + ohash: 2.0.12 + rolldown: 1.1.5 + srvx: 0.11.22 + unenv: 2.0.0-rc.24 + unstorage: 2.0.0-alpha.7(chokidar@5.0.0)(db0@0.3.4)(lru-cache@11.5.2)(ofetch@2.0.0-alpha.3) + optionalDependencies: + dotenv: 17.4.2 + jiti: 2.7.0 + rollup: 4.62.2 + vite: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@electric-sql/pglite' + - '@libsql/client' + - '@netlify/blobs' + - '@netlify/runtime' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - better-sqlite3 + - chokidar + - drizzle-orm + - idb-keyval + - ioredis + - lru-cache + - miniflare + - mongodb + - mysql2 + - sqlite3 + - uploadthing + - wrangler + node-addon-api@7.1.1: {} node-cron@4.6.0: {} @@ -15916,6 +16913,14 @@ snapshots: obug@2.1.4: {} + ocache@0.1.5: + dependencies: + ohash: 2.0.12 + + ofetch@2.0.0-alpha.3: {} + + ohash@2.0.12: {} + on-finished@2.4.1: dependencies: ee-first: 1.1.1 @@ -16030,7 +17035,7 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc': 0.143.0 '@oxc-parser/binding-win32-x64-msvc': 0.143.0 - oxc-resolver@11.24.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1): + oxc-resolver@11.24.2: optionalDependencies: '@oxc-resolver/binding-android-arm-eabi': 11.24.2 '@oxc-resolver/binding-android-arm64': 11.24.2 @@ -16048,12 +17053,9 @@ snapshots: '@oxc-resolver/binding-linux-x64-gnu': 11.24.2 '@oxc-resolver/binding-linux-x64-musl': 11.24.2 '@oxc-resolver/binding-openharmony-arm64': 11.24.2 - '@oxc-resolver/binding-wasm32-wasi': 11.24.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@oxc-resolver/binding-wasm32-wasi': 11.24.2 '@oxc-resolver/binding-win32-arm64-msvc': 11.24.2 '@oxc-resolver/binding-win32-x64-msvc': 11.24.2 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' oxlint-plugin-react-doctor@0.9.12: dependencies: @@ -16400,18 +17402,18 @@ snapshots: optionalDependencies: '@types/react': 19.2.17 - react-doctor@0.9.12(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(eslint@10.7.0(jiti@2.7.0)): + react-doctor@0.9.12(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(eslint@10.7.0(jiti@2.7.0)): dependencies: '@astrojs/compiler': 4.0.0 '@sentry/node': 10.67.0(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1)) agent-install: 0.0.5 conf: 15.1.0 confbox: 0.2.4 - deslop-js: 0.9.12(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + deslop-js: 0.9.12 eslint-plugin-react-hooks: 7.1.1(eslint@10.7.0(jiti@2.7.0)) jiti: 2.7.0 magicast: 0.5.3 - oxc-resolver: 11.24.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + oxc-resolver: 11.24.2 oxlint: 1.77.0 oxlint-plugin-react-doctor: 0.9.12 prompts: 2.4.2 @@ -16422,8 +17424,6 @@ snapshots: yaml: 2.9.0 yoga-layout: 3.2.1 transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - '@opentelemetry/core' - '@opentelemetry/exporter-trace-otlp-http' - eslint @@ -16513,7 +17513,7 @@ snapshots: react: 19.2.8 react-dom: 19.2.8(react@19.2.8) - react-scan@0.5.7(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(esbuild@0.27.7)(eslint@10.7.0(jiti@2.7.0))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.27.7)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): + react-scan@0.5.7(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(esbuild@0.27.7)(eslint@10.7.0(jiti@2.7.0))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.27.7)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): dependencies: '@babel/core': 7.29.7 '@babel/types': 7.29.7 @@ -16525,15 +17525,13 @@ snapshots: preact: 10.29.7 prompts: 2.4.2 react: 19.2.8 - react-doctor: 0.9.12(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(eslint@10.7.0(jiti@2.7.0)) + react-doctor: 0.9.12(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(eslint@10.7.0(jiti@2.7.0)) react-dom: 19.2.8(react@19.2.8) react-grab: 0.2.0(react@19.2.8) optionalDependencies: esbuild: 0.27.7 unplugin: 3.3.0(esbuild@0.27.7)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.27.7)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - '@farmfe/core' - '@opentelemetry/core' - '@opentelemetry/exporter-trace-otlp-http' @@ -16853,6 +17851,8 @@ snapshots: rope-sequence@1.3.4: {} + rou3@0.8.1: {} + router@2.2.0: dependencies: debug: 4.4.3 @@ -16944,6 +17944,12 @@ snapshots: transitivePeerDependencies: - supports-color + seroval-plugins@1.6.2(seroval@1.6.2): + dependencies: + seroval: 1.6.2 + + seroval@1.6.2: {} + serve-static@2.2.1: dependencies: encodeurl: 2.0.0 @@ -17200,6 +18206,8 @@ snapshots: space-separated-tokens@2.0.2: {} + srvx@0.11.22: {} + stack-generator@2.0.10: dependencies: stackframe: 1.3.4 @@ -17634,6 +18642,10 @@ snapshots: undici@7.28.0: {} + unenv@2.0.0-rc.24: + dependencies: + pathe: 2.0.3 + unicorn-magic@0.3.0: {} unified@11.0.5: @@ -17694,6 +18706,24 @@ snapshots: vite: 8.1.5(@types/node@26.1.1)(esbuild@0.27.7)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) optional: true + unplugin@3.3.0(esbuild@0.28.1)(rolldown@1.1.5)(rollup@4.62.2)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): + dependencies: + '@jridgewell/remapping': 2.3.5 + picomatch: 4.0.5 + webpack-virtual-modules: 0.6.2 + optionalDependencies: + esbuild: 0.28.1 + rolldown: 1.1.5 + rollup: 4.62.2 + vite: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + + unstorage@2.0.0-alpha.7(chokidar@5.0.0)(db0@0.3.4)(lru-cache@11.5.2)(ofetch@2.0.0-alpha.3): + optionalDependencies: + chokidar: 5.0.0 + db0: 0.3.4 + lru-cache: 11.5.2 + ofetch: 2.0.0-alpha.3 + update-browserslist-db@1.2.3(browserslist@4.28.7): dependencies: browserslist: 4.28.7 @@ -17814,6 +18844,10 @@ snapshots: tsx: 4.23.1 yaml: 2.9.0 + vitefu@1.1.3(vite@8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): + optionalDependencies: + vite: 8.1.5(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0) + vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.1)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@26.1.1)(esbuild@0.27.7)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 @@ -17922,8 +18956,7 @@ snapshots: - bufferutil - utf-8-validate - webpack-virtual-modules@0.6.2: - optional: true + webpack-virtual-modules@0.6.2: {} whatwg-mimetype@5.0.0: {} @@ -18006,6 +19039,13 @@ snapshots: xml-name-validator@5.0.0: {} + xmlbuilder2@4.0.3: + dependencies: + '@oozcitak/dom': 2.0.2 + '@oozcitak/infra': 2.0.2 + '@oozcitak/util': 10.0.0 + js-yaml: 4.3.0 + xmlchars@2.2.0: {} yallist@3.1.1: {} diff --git a/turbo.json b/turbo.json index 721572f01..53c5cad70 100644 --- a/turbo.json +++ b/turbo.json @@ -31,7 +31,13 @@ "build": { "dependsOn": ["^build:plugins", "^build"], "inputs": ["$TURBO_DEFAULT$", ".env*"], - "outputs": [".next/**", "!.next/cache/**", "!.next/dev/**", "dist/**"], + "outputs": [ + ".next/**", + "!.next/cache/**", + "!.next/dev/**", + ".output/**", + "dist/**" + ], "env": ["POSTGRES_URL", "NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_WEB_URL"] }, "build:scripts": { @@ -48,6 +54,9 @@ "lint": { "dependsOn": ["^lint"] }, + "typecheck": { + "dependsOn": ["^typecheck"] + }, "lint:fix": { "dependsOn": ["^lint:fix"] },