From a542b3ebea3dea4edae15ae366cc2008bf4c1aa4 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 20 Apr 2025 10:53:18 +0200 Subject: [PATCH 01/11] refactor: Api plugin system --- apps/docs/content/docs/dev/meta.json | 3 +- apps/docs/package.json | 1 + apps/web/package.json | 3 +- packages/vitnode/src/api/lib/module.ts | 13 +-- packages/vitnode/src/api/lib/route.ts | 10 +- .../api/modules/admin/routes/session.route.ts | 4 + .../modules/middleware/middleware.module.ts | 32 +----- .../src/api/modules/middleware/route.ts | 5 +- .../api/modules/users/routes/session.route.ts | 5 +- .../api/modules/users/routes/sign-in.route.ts | 5 +- .../modules/users/routes/sign-out.route.ts | 5 +- .../api/modules/users/routes/sign-up.route.ts | 5 +- .../users/sso/routes/callback.route.ts | 5 +- .../users/sso/routes/create-url.route.ts | 5 +- .../src/components/table/data-table.tsx | 74 +++++++------- packages/vitnode/src/components/ui/table.tsx | 2 +- packages/vitnode/src/lib/fetcher-new.ts | 81 +++++++++++++++ packages/vitnode/src/lib/fetcher.ts | 99 ++++++++++++------- packages/vitnode/src/plugin.config.ts | 19 ++++ packages/vitnode/src/plugin.types.ts | 3 - .../views/core/users/users-admin-view.tsx | 37 ++++++- packages/vitnode/src/vitnode.config.ts | 4 +- plugins/blog/package.json | 11 ++- plugins/blog/src/index.ts | 2 - .../modules/categories/categories.module.ts | 5 + .../modules/categories/routes/list.route.ts | 27 +++++ plugins/blog/src/plugin.config.ts | 8 ++ plugins/blog/src/test.ts | 11 +++ pnpm-lock.yaml | 81 +++++++++++++++ 29 files changed, 432 insertions(+), 133 deletions(-) create mode 100644 packages/vitnode/src/lib/fetcher-new.ts create mode 100644 packages/vitnode/src/plugin.config.ts delete mode 100644 packages/vitnode/src/plugin.types.ts delete mode 100644 plugins/blog/src/index.ts create mode 100644 plugins/blog/src/modules/categories/categories.module.ts create mode 100644 plugins/blog/src/modules/categories/routes/list.route.ts create mode 100644 plugins/blog/src/plugin.config.ts create mode 100644 plugins/blog/src/test.ts diff --git a/apps/docs/content/docs/dev/meta.json b/apps/docs/content/docs/dev/meta.json index 3340536f1..e66479287 100644 --- a/apps/docs/content/docs/dev/meta.json +++ b/apps/docs/content/docs/dev/meta.json @@ -9,10 +9,11 @@ "structure", "debugging", "swagger", + "---Plugins---", + "modules", "---Framework---", "auth", "fetcher", - "modules", "routes", "---API---", "sso", diff --git a/apps/docs/package.json b/apps/docs/package.json index a15279149..02a0cf23d 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -14,6 +14,7 @@ "fumadocs-mdx": "^11.6.0", "fumadocs-ui": "^15.2.8", "lucide-react": "^0.488.0", + "motion": "^12.7.4", "next": "^15.3.1", "react": "^19.1.0", "react-dom": "^19.1.0", diff --git a/apps/web/package.json b/apps/web/package.json index ab08114b7..0dfbb8241 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -33,7 +33,8 @@ "react-hook-form": "^7.55.0", "sonner": "^2.0.3", "vitnode": "workspace:*", - "zod": "^3.24.3" + "zod": "^3.24.3", + "vitnode-blog": "workspace:*" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.4", diff --git a/packages/vitnode/src/api/lib/module.ts b/packages/vitnode/src/api/lib/module.ts index 373dcefbe..d5f7a1863 100644 --- a/packages/vitnode/src/api/lib/module.ts +++ b/packages/vitnode/src/api/lib/module.ts @@ -12,20 +12,15 @@ export interface ModuleApi< plugin: P; } -export function createModuleApi< - E extends Env, - S extends Schema = Schema, - N extends string = string, - P extends string = string, ->({ +export function createModuleApi({ name, plugin, routes, }: { - name: N; - plugin: P; + name: string; + plugin: string; routes: OpenAPIHono; -}): ModuleApi { +}) { const current = routes; return { diff --git a/packages/vitnode/src/api/lib/route.ts b/packages/vitnode/src/api/lib/route.ts index dcb8ad1c9..70e19875c 100644 --- a/packages/vitnode/src/api/lib/route.ts +++ b/packages/vitnode/src/api/lib/route.ts @@ -1,3 +1,4 @@ +import { PluginConfig } from '@/plugin.config'; import { createRoute as createRouteHono, RouteConfig } from '@hono/zod-openapi'; import { MiddlewareHandler } from 'hono'; @@ -15,11 +16,11 @@ export function createApiRoute< }, >({ isAuth, - plugin, + pluginConfig, ...routeConfig }: R & { isAuth?: boolean; - plugin: string; + pluginConfig: PluginConfig; }): R & { getRoutingPath: () => RoutingPath; } { @@ -28,10 +29,7 @@ export function createApiRoute< ? routeConfig.middleware : [routeConfig.middleware] : []; - const tags: string[] = [ - plugin.charAt(0).toUpperCase() + plugin.slice(1), - ...(routeConfig.tags ?? []), - ]; + const tags: string[] = [pluginConfig.name, ...(routeConfig.tags ?? [])]; return createRouteHono({ middleware: isAuth ? [sessionMiddleware(), ...middlewareFromConfig] : [], diff --git a/packages/vitnode/src/api/modules/admin/routes/session.route.ts b/packages/vitnode/src/api/modules/admin/routes/session.route.ts index 05fe6caef..341f0e283 100644 --- a/packages/vitnode/src/api/modules/admin/routes/session.route.ts +++ b/packages/vitnode/src/api/modules/admin/routes/session.route.ts @@ -7,6 +7,10 @@ const route = createApiRoute({ method: 'get', description: 'Verify admin session', plugin: 'core', + pluginConfig: { + id: 'core', + name: 'Core', + }, path: '/', responses: { 200: { diff --git a/packages/vitnode/src/api/modules/middleware/middleware.module.ts b/packages/vitnode/src/api/modules/middleware/middleware.module.ts index cdab70139..3ce7e66d1 100644 --- a/packages/vitnode/src/api/modules/middleware/middleware.module.ts +++ b/packages/vitnode/src/api/modules/middleware/middleware.module.ts @@ -1,40 +1,12 @@ import { createModuleApi } from '@/api/lib/module'; -import { createApiRoute } from '@/api/lib/route'; -import { EmailModel } from '@/api/models/email'; -import { OpenAPIHono, z } from '@hono/zod-openapi'; +import { OpenAPIHono } from '@hono/zod-openapi'; import { middlewareRoute } from './route'; export const middlewareModule = createModuleApi({ name: 'middleware', plugin: 'core', - routes: new OpenAPIHono().route('/', middlewareRoute).openapi( - createApiRoute({ - method: 'post', - plugin: 'core', - path: '/test', - responses: { - 200: { - content: { - 'application/json': { - schema: z.string(), - }, - }, - description: 'test', - }, - }, - }), - async c => { - const email = new EmailModel(c); - await email.send({ - to: 'ithereplay@gmail.com', - subject: 'test', - html: 'test', - }); - - return c.json('Hello, world!'); - }, - ), + routes: new OpenAPIHono().route('/', middlewareRoute), }); export type MiddlewareTypes = typeof middlewareModule; diff --git a/packages/vitnode/src/api/modules/middleware/route.ts b/packages/vitnode/src/api/modules/middleware/route.ts index 6598ef4db..a594e769e 100644 --- a/packages/vitnode/src/api/modules/middleware/route.ts +++ b/packages/vitnode/src/api/modules/middleware/route.ts @@ -5,7 +5,10 @@ import { z } from 'zod'; const route = createApiRoute({ method: 'get', - plugin: 'core', + pluginConfig: { + id: 'core', + name: 'Core', + }, description: 'Middleware route with user authentication', path: '/', responses: { diff --git a/packages/vitnode/src/api/modules/users/routes/session.route.ts b/packages/vitnode/src/api/modules/users/routes/session.route.ts index 344f818e8..202b677cc 100644 --- a/packages/vitnode/src/api/modules/users/routes/session.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/session.route.ts @@ -7,7 +7,10 @@ import { z } from 'zod'; const route = createApiRoute({ method: 'get', description: 'Verify session', - plugin: 'core', + pluginConfig: { + id: 'core', + name: 'Core', + }, path: '/', responses: { 200: { diff --git a/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts b/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts index ff352b682..ff164a03f 100644 --- a/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts @@ -8,7 +8,10 @@ import { z } from 'zod'; const route = createApiRoute({ method: 'post', description: 'Sign in with email and password', - plugin: 'core', + pluginConfig: { + id: 'core', + name: 'Core', + }, path: '/', request: { body: { diff --git a/packages/vitnode/src/api/modules/users/routes/sign-out.route.ts b/packages/vitnode/src/api/modules/users/routes/sign-out.route.ts index 7dfbdba53..a1e3bc763 100644 --- a/packages/vitnode/src/api/modules/users/routes/sign-out.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/sign-out.route.ts @@ -6,7 +6,10 @@ import { OpenAPIHono, z } from '@hono/zod-openapi'; const route = createApiRoute({ method: 'delete', description: 'Sign out the current admin', - plugin: 'core', + pluginConfig: { + id: 'core', + name: 'Core', + }, path: '/', request: { body: { diff --git a/packages/vitnode/src/api/modules/users/routes/sign-up.route.ts b/packages/vitnode/src/api/modules/users/routes/sign-up.route.ts index e5f0adbe1..d766dc7f6 100644 --- a/packages/vitnode/src/api/modules/users/routes/sign-up.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/sign-up.route.ts @@ -9,7 +9,10 @@ const nameRegex = /^(?!.* {2})[\p{L}\p{N}._@ -]*$/u; const route = createApiRoute({ method: 'post', description: 'Create a new user', - plugin: 'core', + pluginConfig: { + id: 'core', + name: 'Core', + }, path: '/', request: { body: { diff --git a/packages/vitnode/src/api/modules/users/sso/routes/callback.route.ts b/packages/vitnode/src/api/modules/users/sso/routes/callback.route.ts index d9d5a2b56..4e4da31d0 100644 --- a/packages/vitnode/src/api/modules/users/sso/routes/callback.route.ts +++ b/packages/vitnode/src/api/modules/users/sso/routes/callback.route.ts @@ -7,7 +7,10 @@ import { z } from 'zod'; const route = createApiRoute({ method: 'get', description: 'SSO Callback', - plugin: 'core', + pluginConfig: { + id: 'core', + name: 'Core', + }, path: '/{providerId}/callback', request: { params: z.object({ diff --git a/packages/vitnode/src/api/modules/users/sso/routes/create-url.route.ts b/packages/vitnode/src/api/modules/users/sso/routes/create-url.route.ts index d2502040f..2a751a62b 100644 --- a/packages/vitnode/src/api/modules/users/sso/routes/create-url.route.ts +++ b/packages/vitnode/src/api/modules/users/sso/routes/create-url.route.ts @@ -5,8 +5,11 @@ import { z } from 'zod'; const route = createApiRoute({ method: 'post', + pluginConfig: { + id: 'core', + name: 'Core', + }, description: 'Generate SSO URL', - plugin: 'core', path: '/{providerId}', request: { params: z.object({ diff --git a/packages/vitnode/src/components/table/data-table.tsx b/packages/vitnode/src/components/table/data-table.tsx index 80de6a214..49c93f1eb 100644 --- a/packages/vitnode/src/components/table/data-table.tsx +++ b/packages/vitnode/src/components/table/data-table.tsx @@ -24,42 +24,46 @@ export function DataTable({ data: T[]; }) { return ( - - - - {columns.map(column => ( - {column.label} - ))} - - +
+
+
+ + + {columns.map(column => ( + {column.label} + ))} + + - - {data.length ? ( - data.map(row => ( - - {columns.map(column => { - const content = - column.cell?.({ - allData: data, - row, - }) ?? String(row[column.id]); + + {data.length ? ( + data.map(row => ( + + {columns.map(column => { + const content = + column.cell?.({ + allData: data, + row, + }) ?? String(row[column.id]); - return ( - - {content} - - ); - })} - - )) - ) : ( - - - Not Found - - - )} - -
+ return ( + + {content} + + ); + })} + + )) + ) : ( + + + Not Found + + + )} + + + + ); } diff --git a/packages/vitnode/src/components/ui/table.tsx b/packages/vitnode/src/components/ui/table.tsx index 83f366f2b..b6691a2ec 100644 --- a/packages/vitnode/src/components/ui/table.tsx +++ b/packages/vitnode/src/components/ui/table.tsx @@ -68,7 +68,7 @@ function TableHead({ className, ...props }: React.ComponentProps<'th'>) { return ( [role=checkbox]]:translate-y-[2px]', + 'text-muted-foreground h-10 whitespace-nowrap px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]', className, )} data-slot="table-head" diff --git a/packages/vitnode/src/lib/fetcher-new.ts b/packages/vitnode/src/lib/fetcher-new.ts new file mode 100644 index 000000000..4a77a2ed6 --- /dev/null +++ b/packages/vitnode/src/lib/fetcher-new.ts @@ -0,0 +1,81 @@ +import { OpenAPIHono } from '@hono/zod-openapi'; +import { ClientRequest, hc } from 'hono/client'; +import { UnionToIntersection } from 'hono/utils/types'; +import { cookies, headers } from 'next/headers'; + +import { CONFIG } from './config'; +import { Env, Schema } from 'hono'; +import { HonoBase } from 'hono/hono-base'; + +/** + * Maps an API path string to a nested object structure for type-safe client usage. + * Example: '/foo/bar' -> { foo: { bar: ... } } + * This is intentionally shallow to avoid deep recursion for TS perf. + */ +type PathToChain< + Path extends string, + E extends Schema, + Orig extends string = Path, +> = Path extends `/${infer P}` + ? PathToChain + : Path extends `${infer P}/${infer R}` + ? { [K in P]: PathToChain } + : Record< + Path extends '' ? 'index' : Path, + ClientRequest ? E[Orig] : never> + >; + +/** + * Type-safe client for a Hono API schema. + */ +export type Client = + T extends HonoBase + ? S extends Record + ? K extends string + ? PathToChain + : never + : never + : never; + +/** + * Create a type-safe client for a VitNode API module. + * @param plugin - The plugin name (e.g. 'core') + * @param module - The module name (e.g. 'users') + * @param options - Optional fetch options + */ +export async function fetcherNew({ + plugin, + module, + options, +}: { + module: string; + options?: Omit; + plugin: string; +}): Promise>> { + const url = new URL(`/api/${plugin}/${module}`, CONFIG.backend.origin); + const [nextInternalHeaders, cookie] = await Promise.all([ + headers(), + cookies(), + ]); + + const client = hc(url.href, { + fetch: async (input, requestInit) => { + const headers = new Headers({ + 'Content-Type': 'application/json', + Cookie: cookie.toString(), + ['user-agent']: nextInternalHeaders.get('user-agent') ?? 'node', + ['x-forwarded-for']: + nextInternalHeaders.get('x-forwarded-for') ?? '0.0.0.0', + ...options?.headers, + }); + + return await fetch(input, { + ...requestInit, + ...options, + headers, + }); + }, + }); + + return client as unknown as UnionToIntersection>; +} diff --git a/packages/vitnode/src/lib/fetcher.ts b/packages/vitnode/src/lib/fetcher.ts index e5ef3a8c9..da2eb1625 100644 --- a/packages/vitnode/src/lib/fetcher.ts +++ b/packages/vitnode/src/lib/fetcher.ts @@ -1,3 +1,7 @@ +// --- VitNode Fetcher Types & Utilities --- +// These types are optimized for TypeScript performance and readability. +// Avoid deep recursion and keep type-level logic as flat as possible. + import { ModuleApi } from '@/api/lib/module'; import { ClientRequest, ClientResponse, hc } from 'hono/client'; import { HonoBase } from 'hono/hono-base'; @@ -9,21 +13,29 @@ import { cookies, headers } from 'next/headers'; import { CONFIG } from './config'; import { cookieFromStringToObject } from './cookie-from-string-to-object'; +// --- Type Utilities --- + +/** + * Maps an API path string to a nested object structure for type-safe client usage. + * Example: '/foo/bar' -> { foo: { bar: ... } } + * This is intentionally shallow to avoid deep recursion for TS perf. + */ type PathToChain< Path extends string, E extends Schema, - Original extends string = Path, + Orig extends string = Path, > = Path extends `/${infer P}` ? PathToChain : Path extends `${infer P}/${infer R}` - ? { - [K in P]: PathToChain; - } + ? { [K in P]: PathToChain } : Record< Path extends '' ? 'index' : Path, - ClientRequest ? E[Original] : never> + ClientRequest ? E[Orig] : never> >; +/** + * Type-safe client for a Hono API schema. + */ export type Client = T extends HonoBase ? S extends Record @@ -33,6 +45,51 @@ export type Client = : never : never; +/** + * Type alias for extracting the schema from a ModuleApi. + */ +type SchemaOf> = + T extends ModuleApi ? S : never; + +/** + * Extracts available HTTP methods for a given endpoint path. + */ +type MethodsForEndpoint< + E extends Env, + T extends ModuleApi, + P extends keyof SchemaOf, +> = { + [K in Extract[P], `$${string}`>]: K extends `$${infer U}` + ? Lowercase + : never; +}[Extract[P], `$${string}`>]; + +/** + * Type-safe input for a fetcher endpoint method. + */ +export type FetcherInput< + T extends ModuleApi, + P extends keyof SchemaOf, + M extends MethodsForEndpoint, + E extends Env = Env, +> = { + [K in Extract[P], `$${string}`>]: Lowercase< + K extends `$${infer U}` ? U : never + > extends M + ? SchemaOf[P][K] extends { input: infer I } + ? I + : never + : never; +}[Extract[P], `$${string}`>]; + +// --- Fetcher Implementation --- + +/** + * Create a type-safe client for a VitNode API module. + * @param plugin - The plugin name (e.g. 'core') + * @param module - The module name (e.g. 'users') + * @param options - Optional fetch options + */ export async function fetcher< T extends ModuleApi, >({ @@ -58,7 +115,6 @@ export async function fetcher< ['user-agent']: nextInternalHeaders.get('user-agent') ?? 'node', ['x-forwarded-for']: nextInternalHeaders.get('x-forwarded-for') ?? '0.0.0.0', - // 'x-vitnode-user-language': cookie.get('NEXT_LOCALE')?.value ?? 'en', ...options?.headers, }); @@ -73,34 +129,9 @@ export async function fetcher< return client as unknown as UnionToIntersection>; } -type SchemaOf> = - T extends ModuleApi ? S : never; - -type MethodsForEndpoint< - E extends Env, - T extends ModuleApi, - P extends keyof SchemaOf, -> = { - [K in Extract[P], `$${string}`>]: K extends `$${infer U}` - ? Lowercase - : never; -}[Extract[P], `$${string}`>]; - -export type FetcherInput< - T extends ModuleApi, - P extends keyof SchemaOf, - M extends MethodsForEndpoint, - E extends Env = Env, -> = { - [K in Extract[P], `$${string}`>]: Lowercase< - K extends `$${infer U}` ? U : never - > extends M - ? SchemaOf[P][K] extends { input: infer I } - ? I - : never - : never; -}[Extract[P], `$${string}`>]; - +/** + * Handles setting cookies from a Hono client response in Next.js server context. + */ export async function handleSetCookiesFetcher< T, U extends number = StatusCode, diff --git a/packages/vitnode/src/plugin.config.ts b/packages/vitnode/src/plugin.config.ts new file mode 100644 index 000000000..03a46a579 --- /dev/null +++ b/packages/vitnode/src/plugin.config.ts @@ -0,0 +1,19 @@ +import { OpenAPIHono } from '@hono/zod-openapi'; + +export interface VitNodePlugin { + id: string; + routes: OpenAPIHono[]; +} + +export type PluginConfigReturn = VitNodePlugin; + +export function buildPluginConfig(args: VitNodePlugin): PluginConfigReturn { + return { + ...args, + }; +} + +export interface PluginConfig { + id: string; + name: string; +} diff --git a/packages/vitnode/src/plugin.types.ts b/packages/vitnode/src/plugin.types.ts deleted file mode 100644 index 428954e9c..000000000 --- a/packages/vitnode/src/plugin.types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface VitNodePlugin { - id: string; -} diff --git a/packages/vitnode/src/views/admin/views/core/users/users-admin-view.tsx b/packages/vitnode/src/views/admin/views/core/users/users-admin-view.tsx index 9e4d9ad44..5c133f558 100644 --- a/packages/vitnode/src/views/admin/views/core/users/users-admin-view.tsx +++ b/packages/vitnode/src/views/admin/views/core/users/users-admin-view.tsx @@ -1,11 +1,21 @@ +'use client'; + import { DataTable } from '@/components/table/data-table'; +import { Button } from '@/components/ui/button'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; +import { MoreVerticalIcon } from 'lucide-react'; export const UsersAdminView = () => { return (
{ ), }, + { + id: 'id', + label: 'Actions', + cell: () => ( + + + + + + Edit + Make a copy + Favorite + + Delete + + + ), + }, ]} data={[ { diff --git a/packages/vitnode/src/vitnode.config.ts b/packages/vitnode/src/vitnode.config.ts index 0a1fb4a6f..295735b2a 100644 --- a/packages/vitnode/src/vitnode.config.ts +++ b/packages/vitnode/src/vitnode.config.ts @@ -1,4 +1,4 @@ -import { VitNodePlugin } from './plugin.types'; +import { PluginConfigReturn } from './plugin.config'; export interface VitNodeConfig { debug?: boolean; @@ -11,7 +11,7 @@ export interface VitNodeConfig { shortTitle?: string; title: string; }; - plugins: VitNodePlugin[]; + plugins: PluginConfigReturn[]; } export function buildConfig( diff --git a/plugins/blog/package.json b/plugins/blog/package.json index 4e85eb218..fd37f9f9c 100644 --- a/plugins/blog/package.json +++ b/plugins/blog/package.json @@ -5,6 +5,13 @@ "author": "VitNode", "homepage": "https://vitnode.com", "type": "module", + "exports": { + "./*": { + "import": "./dist/src/*.js", + "types": "./dist/src/*.d.ts", + "default": "./dist/src/*.js" + } + }, "scripts": { "build": "tsc && swc src -d dist --config-file .swcrc", "dev": "concurrently \"tsc -w --preserveWatchOutput\" \"swc src -d dist --config-file .swcrc -w\"", @@ -12,6 +19,7 @@ "lint:fix": "eslint . --fix" }, "dependencies": { + "@hono/zod-openapi": "^0.19.5", "drizzle-kit": "^0.30.6", "drizzle-orm": "^0.41.0", "hono": "^4.7.6", @@ -20,7 +28,8 @@ "next-intl": "^4.0.2", "react": "^19.1.0", "react-dom": "^19.1.0", - "vitnode": "workspace:*" + "vitnode": "workspace:*", + "zod": "^3.24.3" }, "devDependencies": { "@swc/cli": "^0.6.0", diff --git a/plugins/blog/src/index.ts b/plugins/blog/src/index.ts deleted file mode 100644 index ba8dd067a..000000000 --- a/plugins/blog/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -// eslint-disable-next-line no-console -console.log('blog plugin loaded'); diff --git a/plugins/blog/src/modules/categories/categories.module.ts b/plugins/blog/src/modules/categories/categories.module.ts new file mode 100644 index 000000000..978886b54 --- /dev/null +++ b/plugins/blog/src/modules/categories/categories.module.ts @@ -0,0 +1,5 @@ +import { OpenAPIHono } from '@hono/zod-openapi'; + +import { listCategories } from './routes/list.route'; + +export const categoriesModule = new OpenAPIHono().route('/', listCategories); diff --git a/plugins/blog/src/modules/categories/routes/list.route.ts b/plugins/blog/src/modules/categories/routes/list.route.ts new file mode 100644 index 000000000..a92269be8 --- /dev/null +++ b/plugins/blog/src/modules/categories/routes/list.route.ts @@ -0,0 +1,27 @@ +import { OpenAPIHono } from '@hono/zod-openapi'; +import { z } from 'zod'; + +export const listCategories = new OpenAPIHono().openapi( + { + method: 'get', + description: 'Get categories', + path: '/', + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({ + test: z.string(), + }), + }, + }, + description: 'Test', + }, + }, + }, + c => { + return c.json({ + test: 'test', + }); + }, +); diff --git a/plugins/blog/src/plugin.config.ts b/plugins/blog/src/plugin.config.ts new file mode 100644 index 000000000..9145ad005 --- /dev/null +++ b/plugins/blog/src/plugin.config.ts @@ -0,0 +1,8 @@ +import { buildPluginConfig } from 'vitnode/plugin.config'; + +export const blogPlugin = () => { + return buildPluginConfig({ + id: 'blog', + routes: [], + }); +}; diff --git a/plugins/blog/src/test.ts b/plugins/blog/src/test.ts new file mode 100644 index 000000000..b7274b32b --- /dev/null +++ b/plugins/blog/src/test.ts @@ -0,0 +1,11 @@ +import { fetcherNew } from 'vitnode/lib/fetcher-new'; + +export const test = async () => { + const client = await fetcherNew({ + plugin: 'core', + module: 'middleware', + options: { + cache: 'force-cache', + }, + }); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9e1955967..ad7326f22 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: lucide-react: specifier: ^0.488.0 version: 0.488.0(react@19.1.0) + motion: + specifier: ^12.7.4 + version: 12.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next: specifier: ^15.3.1 version: 15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -135,6 +138,9 @@ importers: vitnode: specifier: workspace:* version: link:../../packages/vitnode + vitnode-blog: + specifier: workspace:* + version: link:../../plugins/blog zod: specifier: ^3.24.3 version: 3.24.3 @@ -444,6 +450,9 @@ importers: plugins/blog: dependencies: + '@hono/zod-openapi': + specifier: ^0.19.5 + version: 0.19.5(hono@4.7.6)(zod@3.24.3) drizzle-kit: specifier: ^0.30.6 version: 0.30.6 @@ -471,6 +480,9 @@ importers: vitnode: specifier: workspace:* version: link:../../packages/vitnode + zod: + specifier: ^3.24.3 + version: 3.24.3 devDependencies: '@swc/cli': specifier: ^0.6.0 @@ -4475,6 +4487,20 @@ packages: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} + framer-motion@12.7.4: + resolution: {integrity: sha512-jX0bPsTmU0oPZTYz/dVyD0dmOyEOEJvdn0TaZBE5I8g2GvVnnQnW9f65cJnoVfUkY3WZWNXGXnPbVA9YnaIfVA==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -5353,6 +5379,26 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + motion-dom@12.7.4: + resolution: {integrity: sha512-1ZUHAoSUMMxP6jPqyxlk9XUfb6NxMsnWPnH2YGhrOhTURLcXWbETi6eemoKb60Pe32NVJYduL4B62VQSO5Jq8Q==} + + motion-utils@12.7.2: + resolution: {integrity: sha512-XhZwqctxyJs89oX00zn3OGCuIIpVevbTa+u82usWBC6pSHUd2AoNWiYa7Du8tJxJy9TFbZ82pcn5t7NOm1PHAw==} + + motion@12.7.4: + resolution: {integrity: sha512-MBGrMbYageHw4iZJn+pGTr7abq5n53jCxYkhFC1It3vYukQPRWg5zij46MnwYGpLR8KG465MLHSASXot9edYOw==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -7431,6 +7477,13 @@ snapshots: dependencies: hono: 4.7.7 + '@hono/zod-openapi@0.19.5(hono@4.7.6)(zod@3.24.3)': + dependencies: + '@asteasolutions/zod-to-openapi': 7.3.0(zod@3.24.3) + '@hono/zod-validator': 0.4.3(hono@4.7.6)(zod@3.24.3) + hono: 4.7.6 + zod: 3.24.3 + '@hono/zod-openapi@0.19.5(hono@4.7.7)(zod@3.24.3)': dependencies: '@asteasolutions/zod-to-openapi': 7.3.0(zod@3.24.3) @@ -7438,6 +7491,11 @@ snapshots: hono: 4.7.7 zod: 3.24.3 + '@hono/zod-validator@0.4.3(hono@4.7.6)(zod@3.24.3)': + dependencies: + hono: 4.7.6 + zod: 3.24.3 + '@hono/zod-validator@0.4.3(hono@4.7.7)(zod@3.24.3)': dependencies: hono: 4.7.7 @@ -10449,6 +10507,15 @@ snapshots: form-data-encoder@2.1.4: {} + framer-motion@12.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + motion-dom: 12.7.4 + motion-utils: 12.7.2 + tslib: 2.8.1 + optionalDependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + fsevents@2.3.2: optional: true @@ -11623,6 +11690,20 @@ snapshots: minipass@7.1.2: {} + motion-dom@12.7.4: + dependencies: + motion-utils: 12.7.2 + + motion-utils@12.7.2: {} + + motion@12.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + framer-motion: 12.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + tslib: 2.8.1 + optionalDependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + mri@1.2.0: {} ms@2.1.3: {} From cb9b00f5af73750f19890899559150cc20aa8419 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 20 Apr 2025 19:52:43 +0200 Subject: [PATCH 02/11] feat: Add module test file --- .../modules/middleware/middleware.module.ts | 5 +- packages/vitnode/src/lib/fetcher-new.ts | 66 +---------- packages/vitnode/src/lib/test.ts | 19 ++++ packages/vitnode/src/lib/test.type.ts | 12 ++ packages/vitnode/src/test/module.ts | 105 ++++++++++++++++++ .../modules/categories/categories.module.ts | 8 +- .../{routes/list.route.ts => route.ts} | 15 ++- plugins/blog/src/modules/categories/test.ts | 10 ++ plugins/blog/src/test.ts | 11 -- 9 files changed, 168 insertions(+), 83 deletions(-) create mode 100644 packages/vitnode/src/lib/test.ts create mode 100644 packages/vitnode/src/lib/test.type.ts create mode 100644 packages/vitnode/src/test/module.ts rename plugins/blog/src/modules/categories/{routes/list.route.ts => route.ts} (56%) create mode 100644 plugins/blog/src/modules/categories/test.ts diff --git a/packages/vitnode/src/api/modules/middleware/middleware.module.ts b/packages/vitnode/src/api/modules/middleware/middleware.module.ts index 3ce7e66d1..2b8962247 100644 --- a/packages/vitnode/src/api/modules/middleware/middleware.module.ts +++ b/packages/vitnode/src/api/modules/middleware/middleware.module.ts @@ -1,4 +1,5 @@ import { createModuleApi } from '@/api/lib/module'; +import { test } from '@/test/module'; import { OpenAPIHono } from '@hono/zod-openapi'; import { middlewareRoute } from './route'; @@ -6,7 +7,9 @@ import { middlewareRoute } from './route'; export const middlewareModule = createModuleApi({ name: 'middleware', plugin: 'core', - routes: new OpenAPIHono().route('/', middlewareRoute), + routes: new OpenAPIHono() + .route('/', middlewareRoute) + .route('/testNew', test.hono), }); export type MiddlewareTypes = typeof middlewareModule; diff --git a/packages/vitnode/src/lib/fetcher-new.ts b/packages/vitnode/src/lib/fetcher-new.ts index 4a77a2ed6..2a651921b 100644 --- a/packages/vitnode/src/lib/fetcher-new.ts +++ b/packages/vitnode/src/lib/fetcher-new.ts @@ -1,41 +1,8 @@ import { OpenAPIHono } from '@hono/zod-openapi'; +import { Env, Hono, Schema } from 'hono'; import { ClientRequest, hc } from 'hono/client'; -import { UnionToIntersection } from 'hono/utils/types'; -import { cookies, headers } from 'next/headers'; - -import { CONFIG } from './config'; -import { Env, Schema } from 'hono'; import { HonoBase } from 'hono/hono-base'; - -/** - * Maps an API path string to a nested object structure for type-safe client usage. - * Example: '/foo/bar' -> { foo: { bar: ... } } - * This is intentionally shallow to avoid deep recursion for TS perf. - */ -type PathToChain< - Path extends string, - E extends Schema, - Orig extends string = Path, -> = Path extends `/${infer P}` - ? PathToChain - : Path extends `${infer P}/${infer R}` - ? { [K in P]: PathToChain } - : Record< - Path extends '' ? 'index' : Path, - ClientRequest ? E[Orig] : never> - >; - -/** - * Type-safe client for a Hono API schema. - */ -export type Client = - T extends HonoBase - ? S extends Record - ? K extends string - ? PathToChain - : never - : never - : never; +import { UnionToIntersection } from 'hono/utils/types'; /** * Create a type-safe client for a VitNode API module. @@ -51,31 +18,4 @@ export async function fetcherNew({ module: string; options?: Omit; plugin: string; -}): Promise>> { - const url = new URL(`/api/${plugin}/${module}`, CONFIG.backend.origin); - const [nextInternalHeaders, cookie] = await Promise.all([ - headers(), - cookies(), - ]); - - const client = hc(url.href, { - fetch: async (input, requestInit) => { - const headers = new Headers({ - 'Content-Type': 'application/json', - Cookie: cookie.toString(), - ['user-agent']: nextInternalHeaders.get('user-agent') ?? 'node', - ['x-forwarded-for']: - nextInternalHeaders.get('x-forwarded-for') ?? '0.0.0.0', - ...options?.headers, - }); - - return await fetch(input, { - ...requestInit, - ...options, - headers, - }); - }, - }); - - return client as unknown as UnionToIntersection>; -} +}) {} diff --git a/packages/vitnode/src/lib/test.ts b/packages/vitnode/src/lib/test.ts new file mode 100644 index 000000000..a6afd521b --- /dev/null +++ b/packages/vitnode/src/lib/test.ts @@ -0,0 +1,19 @@ +import { Env, Hono, Schema } from 'hono'; +import { HonoBase } from 'hono/hono-base'; + +type Client = + // eslint-disable-next-line @typescript-eslint/no-explicit-any + T extends HonoBase + ? S extends Record + ? K extends string + ? string + : never + : never + : never; + +export function fetcher>(): Client { + // const client = hc('https://example.com'); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return '' as any as Client; +} diff --git a/packages/vitnode/src/lib/test.type.ts b/packages/vitnode/src/lib/test.type.ts new file mode 100644 index 000000000..f2e6e6e32 --- /dev/null +++ b/packages/vitnode/src/lib/test.type.ts @@ -0,0 +1,12 @@ +// type PathToChain< +// Path extends string, +// E extends Schema, +// Original extends string = Path, +// > = Path extends `/${infer P}` +// ? PathToChain // Pass Original consistently +// : Path extends `${infer P}/${infer R}` +// ? { [K in P]: PathToChain } +// : Record< +// Path extends '' ? 'index' : Path, +// ClientRequest ? E[Original] : never> +// >; diff --git a/packages/vitnode/src/test/module.ts b/packages/vitnode/src/test/module.ts new file mode 100644 index 000000000..3f5d11b30 --- /dev/null +++ b/packages/vitnode/src/test/module.ts @@ -0,0 +1,105 @@ +import { + createRoute, + OpenAPIHono, + RouteConfig, + RouteHandler, + z, +} from '@hono/zod-openapi'; + +export const withHandler = >({ + route, + handler, +}: { + handler: H; + route: R; +}) => ({ route, handler }); + +type Route< + R extends RouteConfig = RouteConfig, + H extends RouteHandler = RouteHandler, +> = readonly { handler: H; route: R }[]; + +export interface BuildModuleType { + plugin: Plugin; + routes: T; +} + +export function buildModule< + const Routes extends Route, + const P extends string, +>({ routes, plugin }: { plugin: P; routes: Routes }) { + const hono = new OpenAPIHono(); + + routes.forEach(({ handler, route }) => { + hono.openapi(route, handler); + }); + + return { routes, plugin, hono }; +} + +export const test = buildModule({ + plugin: 'test_plugin', + routes: [ + withHandler({ + route: createRoute({ + path: '/test34', + method: 'get', + responses: { + 200: { + description: 'Success', + content: { + 'application/json': { + schema: z.object({ message: z.string() }), + }, + }, + }, + }, + }), + handler: c => c.json({ message: 'Success' }), + }), + withHandler({ + route: createRoute({ + path: '/test2', + method: 'post', + responses: { + 200: { + description: 'Success 2', + content: { + 'application/json': { + schema: z.object({ + message: z.string(), + }), + }, + }, + }, + }, + }), + handler: c => { + return c.json({ + message: `Hello from ${c.req.path}`, + }); + }, + }), + ], +}); + +type Test = typeof test; + +type FetcherParams< + T extends { plugin: string; routes: Route }, + R extends T['routes'][number], + // eslint-disable-next-line @typescript-eslint/no-explicit-any +> = R extends any + ? Pick & { plugin: T['plugin'] } + : never; + +function fetcher( + params: FetcherParams, +) { + const { path, method, plugin } = params; +} + +export const testFetcher = () => { + fetcher({ path: '/test34', method: 'get', plugin: 'test_plugin' }); + fetcher({ path: '/test2', method: 'post', plugin: 'test_plugin' }); +}; diff --git a/plugins/blog/src/modules/categories/categories.module.ts b/plugins/blog/src/modules/categories/categories.module.ts index 978886b54..3557324d7 100644 --- a/plugins/blog/src/modules/categories/categories.module.ts +++ b/plugins/blog/src/modules/categories/categories.module.ts @@ -1,5 +1,9 @@ import { OpenAPIHono } from '@hono/zod-openapi'; -import { listCategories } from './routes/list.route'; +import { categoriesRoute } from './route'; -export const categoriesModule = new OpenAPIHono().route('/', listCategories); +export const categoriesModule = new OpenAPIHono() + .route('/categories', categoriesRoute) + .route('/test', categoriesRoute); + +export type CategoriesTypes = typeof categoriesModule; diff --git a/plugins/blog/src/modules/categories/routes/list.route.ts b/plugins/blog/src/modules/categories/route.ts similarity index 56% rename from plugins/blog/src/modules/categories/routes/list.route.ts rename to plugins/blog/src/modules/categories/route.ts index a92269be8..cf0b0d423 100644 --- a/plugins/blog/src/modules/categories/routes/list.route.ts +++ b/plugins/blog/src/modules/categories/route.ts @@ -1,11 +1,14 @@ -import { OpenAPIHono } from '@hono/zod-openapi'; -import { z } from 'zod'; +import { OpenAPIHono, z } from '@hono/zod-openapi'; +import { createApiRoute } from 'vitnode/api/lib/route'; -export const listCategories = new OpenAPIHono().openapi( - { +export const categoriesRoute = new OpenAPIHono().openapi( + createApiRoute({ method: 'get', - description: 'Get categories', path: '/', + pluginConfig: { + id: 'blog', + name: 'Blog', + }, responses: { 200: { content: { @@ -18,7 +21,7 @@ export const listCategories = new OpenAPIHono().openapi( description: 'Test', }, }, - }, + }), c => { return c.json({ test: 'test', diff --git a/plugins/blog/src/modules/categories/test.ts b/plugins/blog/src/modules/categories/test.ts new file mode 100644 index 000000000..111565dee --- /dev/null +++ b/plugins/blog/src/modules/categories/test.ts @@ -0,0 +1,10 @@ +import { fetcher } from 'vitnode/lib/test'; + +import { CategoriesTypes } from './categories.module'; + +export const test = async () => { + const client = fetcher(); + const response = await client.categories.$get(); + + return response; +}; diff --git a/plugins/blog/src/test.ts b/plugins/blog/src/test.ts index b7274b32b..e69de29bb 100644 --- a/plugins/blog/src/test.ts +++ b/plugins/blog/src/test.ts @@ -1,11 +0,0 @@ -import { fetcherNew } from 'vitnode/lib/fetcher-new'; - -export const test = async () => { - const client = await fetcherNew({ - plugin: 'core', - module: 'middleware', - options: { - cache: 'force-cache', - }, - }); -}; From 886935efc5991f9a95e60e7721fb0255c53de660 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Mon, 21 Apr 2025 12:56:55 +0200 Subject: [PATCH 03/11] refactor: Update middleware module imports and remove unused files --- .../modules/middleware/middleware.module.ts | 2 +- packages/vitnode/src/lib/fetcher-new.ts | 21 ----- packages/vitnode/src/lib/test.ts | 19 ---- packages/vitnode/src/lib/test.type.ts | 12 --- packages/vitnode/src/test/fetcher.ts | 21 +++++ packages/vitnode/src/test/module.ts | 88 +------------------ packages/vitnode/src/test/route.ts | 39 ++++++++ packages/vitnode/src/test/test.ts | 78 ++++++++++++++++ 8 files changed, 141 insertions(+), 139 deletions(-) delete mode 100644 packages/vitnode/src/lib/fetcher-new.ts delete mode 100644 packages/vitnode/src/lib/test.ts delete mode 100644 packages/vitnode/src/lib/test.type.ts create mode 100644 packages/vitnode/src/test/fetcher.ts create mode 100644 packages/vitnode/src/test/route.ts create mode 100644 packages/vitnode/src/test/test.ts diff --git a/packages/vitnode/src/api/modules/middleware/middleware.module.ts b/packages/vitnode/src/api/modules/middleware/middleware.module.ts index 2b8962247..db1341e79 100644 --- a/packages/vitnode/src/api/modules/middleware/middleware.module.ts +++ b/packages/vitnode/src/api/modules/middleware/middleware.module.ts @@ -1,5 +1,5 @@ import { createModuleApi } from '@/api/lib/module'; -import { test } from '@/test/module'; +import { test } from '@/test/test'; import { OpenAPIHono } from '@hono/zod-openapi'; import { middlewareRoute } from './route'; diff --git a/packages/vitnode/src/lib/fetcher-new.ts b/packages/vitnode/src/lib/fetcher-new.ts deleted file mode 100644 index 2a651921b..000000000 --- a/packages/vitnode/src/lib/fetcher-new.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { OpenAPIHono } from '@hono/zod-openapi'; -import { Env, Hono, Schema } from 'hono'; -import { ClientRequest, hc } from 'hono/client'; -import { HonoBase } from 'hono/hono-base'; -import { UnionToIntersection } from 'hono/utils/types'; - -/** - * Create a type-safe client for a VitNode API module. - * @param plugin - The plugin name (e.g. 'core') - * @param module - The module name (e.g. 'users') - * @param options - Optional fetch options - */ -export async function fetcherNew({ - plugin, - module, - options, -}: { - module: string; - options?: Omit; - plugin: string; -}) {} diff --git a/packages/vitnode/src/lib/test.ts b/packages/vitnode/src/lib/test.ts deleted file mode 100644 index a6afd521b..000000000 --- a/packages/vitnode/src/lib/test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Env, Hono, Schema } from 'hono'; -import { HonoBase } from 'hono/hono-base'; - -type Client = - // eslint-disable-next-line @typescript-eslint/no-explicit-any - T extends HonoBase - ? S extends Record - ? K extends string - ? string - : never - : never - : never; - -export function fetcher>(): Client { - // const client = hc('https://example.com'); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return '' as any as Client; -} diff --git a/packages/vitnode/src/lib/test.type.ts b/packages/vitnode/src/lib/test.type.ts deleted file mode 100644 index f2e6e6e32..000000000 --- a/packages/vitnode/src/lib/test.type.ts +++ /dev/null @@ -1,12 +0,0 @@ -// type PathToChain< -// Path extends string, -// E extends Schema, -// Original extends string = Path, -// > = Path extends `/${infer P}` -// ? PathToChain // Pass Original consistently -// : Path extends `${infer P}/${infer R}` -// ? { [K in P]: PathToChain } -// : Record< -// Path extends '' ? 'index' : Path, -// ClientRequest ? E[Original] : never> -// >; diff --git a/packages/vitnode/src/test/fetcher.ts b/packages/vitnode/src/test/fetcher.ts new file mode 100644 index 000000000..57faa3fc9 --- /dev/null +++ b/packages/vitnode/src/test/fetcher.ts @@ -0,0 +1,21 @@ +import { Route } from './route'; +import { Test } from './test'; + +type FetcherParams< + T extends { plugin: string; routes: Route }, + R extends T['routes'][number], + // eslint-disable-next-line @typescript-eslint/no-explicit-any +> = R extends any + ? Pick & { plugin: T['plugin'] } + : never; + +function fetcher( + params: FetcherParams, +) { + const { path, method, plugin } = params; +} + +export const testFetcher = () => { + fetcher({ path: '/test34', method: 'get', plugin: 'test_plugin' }); + fetcher({ path: '/test2', method: 'post', plugin: 'test_plugin' }); +}; diff --git a/packages/vitnode/src/test/module.ts b/packages/vitnode/src/test/module.ts index 3f5d11b30..d5fe1bacb 100644 --- a/packages/vitnode/src/test/module.ts +++ b/packages/vitnode/src/test/module.ts @@ -1,23 +1,6 @@ -import { - createRoute, - OpenAPIHono, - RouteConfig, - RouteHandler, - z, -} from '@hono/zod-openapi'; +import { OpenAPIHono } from '@hono/zod-openapi'; -export const withHandler = >({ - route, - handler, -}: { - handler: H; - route: R; -}) => ({ route, handler }); - -type Route< - R extends RouteConfig = RouteConfig, - H extends RouteHandler = RouteHandler, -> = readonly { handler: H; route: R }[]; +import { Route } from './route'; export interface BuildModuleType { plugin: Plugin; @@ -36,70 +19,3 @@ export function buildModule< return { routes, plugin, hono }; } - -export const test = buildModule({ - plugin: 'test_plugin', - routes: [ - withHandler({ - route: createRoute({ - path: '/test34', - method: 'get', - responses: { - 200: { - description: 'Success', - content: { - 'application/json': { - schema: z.object({ message: z.string() }), - }, - }, - }, - }, - }), - handler: c => c.json({ message: 'Success' }), - }), - withHandler({ - route: createRoute({ - path: '/test2', - method: 'post', - responses: { - 200: { - description: 'Success 2', - content: { - 'application/json': { - schema: z.object({ - message: z.string(), - }), - }, - }, - }, - }, - }), - handler: c => { - return c.json({ - message: `Hello from ${c.req.path}`, - }); - }, - }), - ], -}); - -type Test = typeof test; - -type FetcherParams< - T extends { plugin: string; routes: Route }, - R extends T['routes'][number], - // eslint-disable-next-line @typescript-eslint/no-explicit-any -> = R extends any - ? Pick & { plugin: T['plugin'] } - : never; - -function fetcher( - params: FetcherParams, -) { - const { path, method, plugin } = params; -} - -export const testFetcher = () => { - fetcher({ path: '/test34', method: 'get', plugin: 'test_plugin' }); - fetcher({ path: '/test2', method: 'post', plugin: 'test_plugin' }); -}; diff --git a/packages/vitnode/src/test/route.ts b/packages/vitnode/src/test/route.ts new file mode 100644 index 000000000..a9db39b7e --- /dev/null +++ b/packages/vitnode/src/test/route.ts @@ -0,0 +1,39 @@ +import { RouteConfig, RouteHandler } from '@hono/zod-openapi'; + +type RoutingPath

= + P extends `${infer Head}/{${infer Param}}${infer Tail}` + ? `${Head}/:${Param}${RoutingPath}` + : P; + +type ValidHandler = ( + c: Parameters>[0], +) => ReturnType>; + +export const buildRoute = < + P extends string, + R extends Omit & { + path: P; + }, + H extends ValidHandler, +>({ + route, + handler, +}: { + handler: H; + route: R; +}): { + handler: H; + route: R & { + getRoutingPath: () => RoutingPath; + }; +} => ({ + route: route as R & { + getRoutingPath: () => RoutingPath; + }, + handler, +}); + +export type Route< + R extends RouteConfig = RouteConfig, + H extends RouteHandler = RouteHandler, +> = readonly { handler: H; route: R }[]; diff --git a/packages/vitnode/src/test/test.ts b/packages/vitnode/src/test/test.ts new file mode 100644 index 000000000..2d2661fc5 --- /dev/null +++ b/packages/vitnode/src/test/test.ts @@ -0,0 +1,78 @@ +import { z } from '@hono/zod-openapi'; + +import { buildModule } from './module'; +import { buildRoute } from './route'; + +export const test = buildModule({ + plugin: 'test_plugin', + routes: [ + buildRoute({ + route: { + path: '/test34', + method: 'get', + responses: { + 200: { + description: 'Success', + content: { + 'application/json': { + schema: z.object({ message: z.string() }), + }, + }, + }, + }, + }, + handler: c => { + return c.json({ + message: `Hello from ${c.req.path}`, + }); + }, + }), + buildRoute({ + route: { + path: '/test2', + method: 'post', + request: { + body: { + required: true, + content: { + 'application/json': { + schema: z.object({ + email: z.string().email().toLowerCase().openapi({ + example: 'test@test.com', + }), + password: z.string().openapi({ + example: 'Test123!', + }), + isAdmin: z.boolean().optional().openapi({ + example: false, + }), + }), + }, + }, + }, + }, + responses: { + 200: { + description: 'Success 2', + content: { + 'application/json': { + schema: z.object({ + message: z.string(), + }), + }, + }, + }, + }, + }, + handler: c => { + const { isAdmin, email } = c.req.valid('json'); + + return c.json({ + message: `Got request from ${email} with admin status: ${isAdmin ?? false}`, + }); + }, + }), + ], +}); + +export type Test = typeof test; From ca0d6c4c5469d48c9395a8e908770f06ff22a0c9 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Mon, 21 Apr 2025 21:04:44 +0200 Subject: [PATCH 04/11] Refactor API module structure and route handling - Updated module creation to use buildModule function for consistency. - Refactored route creation to utilize buildRoute function for improved clarity. - Adjusted imports across various modules to align with new structure. - Enhanced type definitions for plugins and modules to ensure better type safety. - Removed deprecated createApiRoute and createPluginApi functions. - Consolidated route definitions and handlers for better maintainability. - Added new plugin configuration to vitnode.config.ts for enhanced plugin management. - Updated categories module to reflect new route handling structure. --- apps/docs/content/docs/dev/modules.mdx | 4 + apps/web/src/vitnode.config.ts | 1 + packages/vitnode/src/api/config.ts | 12 +-- packages/vitnode/src/api/lib/module.ts | 54 +++++++---- packages/vitnode/src/api/lib/plugin.ts | 32 +++---- packages/vitnode/src/api/lib/route.ts | 60 ++++++++++-- .../src/api/modules/admin/admin.module.ts | 7 +- .../api/modules/admin/routes/session.route.ts | 78 +++++++-------- .../modules/middleware/middleware.module.ts | 18 ++-- .../src/api/modules/middleware/route.ts | 52 +++++----- .../api/modules/users/routes/session.route.ts | 86 ++++++++--------- .../api/modules/users/routes/sign-in.route.ts | 96 +++++++++---------- .../modules/users/routes/sign-out.route.ts | 65 ++++++------- .../api/modules/users/routes/sign-up.route.ts | 94 +++++++++--------- .../users/sso/routes/callback.route.ts | 70 +++++++------- .../users/sso/routes/create-url.route.ts | 54 +++++------ .../src/api/modules/users/sso/sso.module.ts | 9 +- .../src/api/modules/users/users.module.ts | 15 +-- packages/vitnode/src/api/plugin.ts | 6 +- packages/vitnode/src/test/fetcher.ts | 3 +- packages/vitnode/src/test/module.ts | 21 ---- packages/vitnode/src/test/route.ts | 39 -------- packages/vitnode/src/test/test.ts | 78 --------------- packages/vitnode/src/vitnode.config.ts | 2 + .../modules/categories/categories.module.ts | 10 +- plugins/blog/src/modules/categories/route.ts | 18 ++-- 26 files changed, 433 insertions(+), 551 deletions(-) delete mode 100644 packages/vitnode/src/test/module.ts delete mode 100644 packages/vitnode/src/test/route.ts delete mode 100644 packages/vitnode/src/test/test.ts diff --git a/apps/docs/content/docs/dev/modules.mdx b/apps/docs/content/docs/dev/modules.mdx index 25e4c9a7f..815339669 100644 --- a/apps/docs/content/docs/dev/modules.mdx +++ b/apps/docs/content/docs/dev/modules.mdx @@ -4,3 +4,7 @@ description: xdd --- xdd + +```ts + +``` diff --git a/apps/web/src/vitnode.config.ts b/apps/web/src/vitnode.config.ts index 314bc2e98..5295d0a90 100644 --- a/apps/web/src/vitnode.config.ts +++ b/apps/web/src/vitnode.config.ts @@ -7,6 +7,7 @@ export const vitNodeConfig = buildConfig({ shortTitle: 'VitNode', }, plugins: [], + pluginsNew: [], i18n: { locales: ['en', 'pl'] as const, defaultLocale: 'en', diff --git a/packages/vitnode/src/api/config.ts b/packages/vitnode/src/api/config.ts index 4e7b4d857..3aa306427 100644 --- a/packages/vitnode/src/api/config.ts +++ b/packages/vitnode/src/api/config.ts @@ -1,4 +1,4 @@ -import corePlugin from '@/api/plugin'; +import { newBuildPluginCore } from '@/api/plugin'; import { swaggerUI } from '@hono/swagger-ui'; import { OpenAPIHono } from '@hono/zod-openapi'; import { Context, Env, Schema } from 'hono'; @@ -6,7 +6,7 @@ import { cors } from 'hono/cors'; import { csrf } from 'hono/csrf'; import { HTTPException } from 'hono/http-exception'; -import { PluginAPI } from './lib/plugin'; +import { BuildPluginReturn } from './lib/plugin'; import { globalMiddleware } from './middlewares/global/global'; interface CORSOptions { @@ -26,7 +26,7 @@ interface CSRFOptions { origin?: IsAllowedOriginHandler | string | string[]; } -export function VitNodeAPI({ +export function VitNodeAPI({ app, cors: corsOptions, csrf: csrfOptions, @@ -36,7 +36,7 @@ export function VitNodeAPI({ app: OpenAPIHono; cors?: CORSOptions; csrf?: CSRFOptions; - plugins: PluginAPI[]; + plugins: BuildPluginReturn[]; }) { app.doc('/swagger/doc', { openapi: '3.0.0', @@ -69,8 +69,8 @@ export function VitNodeAPI({ }); }); - [corePlugin, ...plugins].map(root => { - app.route(`/${root.name}`, root.app); + [newBuildPluginCore, ...plugins].map(root => { + app.route(`/${root.name}`, root.hono); }); return app; diff --git a/packages/vitnode/src/api/lib/module.ts b/packages/vitnode/src/api/lib/module.ts index d5f7a1863..eb0d63605 100644 --- a/packages/vitnode/src/api/lib/module.ts +++ b/packages/vitnode/src/api/lib/module.ts @@ -1,31 +1,43 @@ import { OpenAPIHono } from '@hono/zod-openapi'; -import { Env, Schema } from 'hono'; -export interface ModuleApi< - E extends Env, - T extends Schema, - N extends string, - P extends string, +import { Route } from './route'; + +export interface BuildModuleType { + plugin: Plugin; + routes: T; +} + +export interface BuildModuleReturn< + P extends string = string, + M extends string = string, + Routes extends Route = Route, > { - app: OpenAPIHono; - name: N; + hono: OpenAPIHono; + name: M; plugin: P; + routes?: Routes; } -export function createModuleApi({ - name, - plugin, +export function buildModule< + const P extends string, + const M extends string, + const Routes extends Route, +>({ routes, + plugin, + name, }: { - name: string; - plugin: string; - routes: OpenAPIHono; -}) { - const current = routes; + name: M; + plugin: P; + routes?: Routes; +}): BuildModuleReturn { + const hono = new OpenAPIHono(); + + if (routes) { + routes.forEach(({ handler, route }) => { + hono.openapi(route, handler); + }); + } - return { - app: current, - plugin, - name, - }; + return { routes, plugin, hono, name }; } diff --git a/packages/vitnode/src/api/lib/plugin.ts b/packages/vitnode/src/api/lib/plugin.ts index 330beb2c8..709a37a56 100644 --- a/packages/vitnode/src/api/lib/plugin.ts +++ b/packages/vitnode/src/api/lib/plugin.ts @@ -1,31 +1,23 @@ import { OpenAPIHono } from '@hono/zod-openapi'; -import { Env, Schema } from 'hono'; -import { ModuleApi } from './module'; +import { BuildModuleReturn } from './module'; -export interface PluginAPI { - app: OpenAPIHono; - name: Plugin; +export interface BuildPluginReturn { + hono: OpenAPIHono; + name: string; } -export function createPluginApi< - T extends Schema, - E extends Env = Env, - Plugin extends string = string, ->({ +export function buildPlugin

({ name, - modules, + modules = [], }: { - modules: ModuleApi[]; - name: Plugin; -}): PluginAPI { - const root = new OpenAPIHono(); + modules?: BuildModuleReturn

[]; + name: P; +}): BuildPluginReturn { + const hono = new OpenAPIHono(); modules.forEach(handler => { - root.route(`/${handler.name}`, handler.app); + hono.route(`/${handler.name}`, handler.hono); }); - return { - name, - app: root, - }; + return { name, hono }; } diff --git a/packages/vitnode/src/api/lib/route.ts b/packages/vitnode/src/api/lib/route.ts index 70e19875c..74596f3cf 100644 --- a/packages/vitnode/src/api/lib/route.ts +++ b/packages/vitnode/src/api/lib/route.ts @@ -1,15 +1,14 @@ import { PluginConfig } from '@/plugin.config'; -import { createRoute as createRouteHono, RouteConfig } from '@hono/zod-openapi'; +import { + createRoute as createRouteHono, + RouteConfig, + RouteHandler, +} from '@hono/zod-openapi'; import { MiddlewareHandler } from 'hono'; import { sessionMiddleware } from '../middlewares/session'; -type RoutingPath

= - P extends `${infer Head}/{${infer Param}}${infer Tail}` - ? `${Head}/:${Param}${RoutingPath}` - : P; - -export function createApiRoute< +function createApiRoute< P extends string, R extends Omit & { path: P; @@ -39,3 +38,50 @@ export function createApiRoute< getRoutingPath: () => RoutingPath; }; } + +// =============== + +type RoutingPath

= + P extends `${infer Head}/{${infer Param}}${infer Tail}` + ? `${Head}/:${Param}${RoutingPath}` + : P; + +type ValidHandler = ( + c: Parameters>[0], +) => ReturnType>; + +export const buildRoute = < + P extends string, + R extends Omit & { + path: P; + }, + H extends ValidHandler, +>({ + route, + handler, +}: { + handler: H; + route: R; +}): { + handler: H; + route: R & { + getRoutingPath: () => RoutingPath; + }; +} => { + const tags: string[] = ['test123 from createRoute', ...(route.tags ?? [])]; + + return { + route: { + ...route, + tags, + } as R & { + getRoutingPath: () => RoutingPath; + }, + handler, + }; +}; + +export type Route< + R extends RouteConfig = RouteConfig, + H extends RouteHandler = RouteHandler, +> = readonly { handler: H; route: R }[]; diff --git a/packages/vitnode/src/api/modules/admin/admin.module.ts b/packages/vitnode/src/api/modules/admin/admin.module.ts index 5e129cb68..ddc365ca4 100644 --- a/packages/vitnode/src/api/modules/admin/admin.module.ts +++ b/packages/vitnode/src/api/modules/admin/admin.module.ts @@ -1,12 +1,11 @@ -import { createModuleApi } from '@/api/lib/module'; -import { OpenAPIHono } from '@hono/zod-openapi'; +import { buildModule } from '@/api/lib/module'; import { sessionAdminRoute } from './routes/session.route'; -export const adminModule = createModuleApi({ +export const adminModule = buildModule({ name: 'admin', plugin: 'core', - routes: new OpenAPIHono().route('/session', sessionAdminRoute), + routes: [sessionAdminRoute], }); export type AdminTypes = typeof adminModule; diff --git a/packages/vitnode/src/api/modules/admin/routes/session.route.ts b/packages/vitnode/src/api/modules/admin/routes/session.route.ts index 341f0e283..7b87fb05d 100644 --- a/packages/vitnode/src/api/modules/admin/routes/session.route.ts +++ b/packages/vitnode/src/api/modules/admin/routes/session.route.ts @@ -1,49 +1,49 @@ -import { createApiRoute } from '@/api/lib/route'; +import { buildRoute } from '@/api/lib/route'; import { SessionAdminModel } from '@/api/models/session-admin'; -import { OpenAPIHono } from '@hono/zod-openapi'; import { z } from 'zod'; -const route = createApiRoute({ - method: 'get', - description: 'Verify admin session', - plugin: 'core', - pluginConfig: { - id: 'core', - name: 'Core', - }, - path: '/', - responses: { - 200: { - content: { - 'application/json': { - schema: z.object({ - user: z.object({ - id: z.string(), - email: z.string(), - name: z.string(), - name_code: z.string(), - joined_at: z.date(), - newsletter: z.boolean(), - avatar_color: z.string(), - email_verified: z.boolean(), - role_id: z.string(), - birthday: z.date().nullable(), +export const sessionAdminRoute = buildRoute({ + route: { + method: 'get', + description: 'Verify admin session', + plugin: 'core', + pluginConfig: { + id: 'core', + name: 'Core', + }, + path: '/session', + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({ + user: z.object({ + id: z.string(), + email: z.string(), + name: z.string(), + name_code: z.string(), + joined_at: z.date(), + newsletter: z.boolean(), + avatar_color: z.string(), + email_verified: z.boolean(), + role_id: z.string(), + birthday: z.date().nullable(), + }), }), - }), + }, }, + description: 'User', + }, + 403: { + description: 'Access Denied', }, - description: 'User', - }, - 403: { - description: 'Access Denied', }, }, -}); - -export const sessionAdminRoute = new OpenAPIHono().openapi(route, async c => { - const user = await new SessionAdminModel(c).verifySession(); + handler: async c => { + const user = await new SessionAdminModel(c).verifySession(); - return c.json({ - user, - }); + return c.json({ + user, + }); + }, }); diff --git a/packages/vitnode/src/api/modules/middleware/middleware.module.ts b/packages/vitnode/src/api/modules/middleware/middleware.module.ts index db1341e79..cb1a71f08 100644 --- a/packages/vitnode/src/api/modules/middleware/middleware.module.ts +++ b/packages/vitnode/src/api/modules/middleware/middleware.module.ts @@ -1,15 +1,13 @@ -import { createModuleApi } from '@/api/lib/module'; -import { test } from '@/test/test'; -import { OpenAPIHono } from '@hono/zod-openapi'; +import { buildModule } from '@/api/lib/module'; -import { middlewareRoute } from './route'; +import { routeMiddleware } from './route'; -export const middlewareModule = createModuleApi({ - name: 'middleware', +export type MiddlewareTypes = typeof middlewareModule; + +export const middlewareModule = buildModule({ plugin: 'core', - routes: new OpenAPIHono() - .route('/', middlewareRoute) - .route('/testNew', test.hono), + name: 'middleware', + routes: [routeMiddleware], }); -export type MiddlewareTypes = typeof middlewareModule; +export type BuildMiddlewareTypes = typeof middlewareModule; diff --git a/packages/vitnode/src/api/modules/middleware/route.ts b/packages/vitnode/src/api/modules/middleware/route.ts index a594e769e..484462421 100644 --- a/packages/vitnode/src/api/modules/middleware/route.ts +++ b/packages/vitnode/src/api/modules/middleware/route.ts @@ -1,37 +1,33 @@ -import { createApiRoute } from '@/api/lib/route'; +import { buildRoute } from '@/api/lib/route'; import { EmailModel } from '@/api/models/email'; -import { OpenAPIHono } from '@hono/zod-openapi'; import { z } from 'zod'; -const route = createApiRoute({ - method: 'get', - pluginConfig: { - id: 'core', - name: 'Core', - }, - description: 'Middleware route with user authentication', - path: '/', - responses: { - 200: { - content: { - 'application/json': { - schema: z.object({ - sso: z.array(z.object({ id: z.string(), name: z.string() })), - isEmail: z.boolean(), - }), +export const routeMiddleware = buildRoute({ + route: { + path: '/', + method: 'get', + description: 'Middleware route with user authentication', + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({ + sso: z.array(z.object({ id: z.string(), name: z.string() })), + isEmail: z.boolean(), + }), + }, }, + description: 'Middleware route', }, - description: 'Middleware route', }, }, -}); + handler: c => { + const sso = c.get('core').authorization.ssoPlugins; + const email = new EmailModel(c); -export const middlewareRoute = new OpenAPIHono().openapi(route, c => { - const sso = c.get('core').authorization.ssoPlugins; - const email = new EmailModel(c); - - return c.json({ - isEmail: email.isAvailable(), - sso: sso.map(s => ({ id: s.id, name: s.name })), - }); + return c.json({ + isEmail: email.isAvailable(), + sso: sso.map(s => ({ id: s.id, name: s.name })), + }); + }, }); diff --git a/packages/vitnode/src/api/modules/users/routes/session.route.ts b/packages/vitnode/src/api/modules/users/routes/session.route.ts index 202b677cc..051a5716d 100644 --- a/packages/vitnode/src/api/modules/users/routes/session.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/session.route.ts @@ -1,55 +1,51 @@ -import { createApiRoute } from '@/api/lib/route'; +import { buildRoute } from '@/api/lib/route'; import { SessionModel } from '@/api/models/session'; import { SessionAdminModel } from '@/api/models/session-admin'; -import { OpenAPIHono } from '@hono/zod-openapi'; import { z } from 'zod'; -const route = createApiRoute({ - method: 'get', - description: 'Verify session', - pluginConfig: { - id: 'core', - name: 'Core', - }, - path: '/', - responses: { - 200: { - content: { - 'application/json': { - schema: z.object({ - user: z - .object({ - id: z.string(), - email: z.string(), - name: z.string(), - name_code: z.string(), - joined_at: z.date(), - newsletter: z.boolean(), - avatar_color: z.string(), - email_verified: z.boolean(), - role_id: z.string(), - birthday: z.date().nullable(), - isAdmin: z.boolean(), - }) - .nullable(), - }), +export const sessionRoute = buildRoute({ + route: { + method: 'get', + description: 'Verify session', + path: '/session', + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({ + user: z + .object({ + id: z.string(), + email: z.string(), + name: z.string(), + name_code: z.string(), + joined_at: z.date(), + newsletter: z.boolean(), + avatar_color: z.string(), + email_verified: z.boolean(), + role_id: z.string(), + birthday: z.date().nullable(), + isAdmin: z.boolean(), + }) + .nullable(), + }), + }, }, + description: 'User', }, - description: 'User', }, }, -}); + handler: async c => { + const user = await new SessionModel(c).verifySession(); + const admin = new SessionAdminModel(c); -export const sessionRoute = new OpenAPIHono().openapi(route, async c => { - const user = await new SessionModel(c).verifySession(); - const admin = new SessionAdminModel(c); - - return c.json({ - user: user - ? { - ...user, - isAdmin: await admin.checkIfUserIsAdmin(user.id), - } - : null, - }); + return c.json({ + user: user + ? { + ...user, + isAdmin: await admin.checkIfUserIsAdmin(user.id), + } + : null, + }); + }, }); diff --git a/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts b/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts index ff164a03f..2110861b5 100644 --- a/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts @@ -1,68 +1,64 @@ -import { createApiRoute } from '@/api/lib/route'; +import { buildRoute } from '@/api/lib/route'; import { SessionModel } from '@/api/models/session'; import { SessionAdminModel } from '@/api/models/session-admin'; import { UserModel } from '@/api/models/user'; -import { OpenAPIHono } from '@hono/zod-openapi'; import { z } from 'zod'; -const route = createApiRoute({ - method: 'post', - description: 'Sign in with email and password', - pluginConfig: { - id: 'core', - name: 'Core', - }, - path: '/', - request: { - body: { - required: true, - content: { - 'application/json': { - schema: z.object({ - email: z.string().email().toLowerCase().openapi({ - example: 'test@test.com', - }), - password: z.string().openapi({ - example: 'Test123!', - }), - isAdmin: z.boolean().optional().openapi({ - example: false, +export const signInRoute = buildRoute({ + route: { + method: 'post', + description: 'Sign in with email and password', + path: '/sign_in', + request: { + body: { + required: true, + content: { + 'application/json': { + schema: z.object({ + email: z.string().email().toLowerCase().openapi({ + example: 'test@test.com', + }), + password: z.string().openapi({ + example: 'Test123!', + }), + isAdmin: z.boolean().optional().openapi({ + example: false, + }), }), - }), + }, }, }, }, - }, - responses: { - 200: { - content: { - 'application/json': { - schema: z.object({ - id: z.string(), - token: z.string(), - }), + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({ + id: z.string(), + token: z.string(), + }), + }, }, + description: 'User signed in', + }, + 403: { + description: 'Access Denied', }, - description: 'User signed in', - }, - 403: { - description: 'Access Denied', }, }, -}); + handler: async c => { + const { password, isAdmin, email } = c.req.valid('json'); + const data = await new UserModel().signInWithPassword({ password, email }); -export const signInRoute = new OpenAPIHono().openapi(route, async c => { - const { password, isAdmin, email } = c.req.valid('json'); - const data = await new UserModel().signInWithPassword({ password, email }); + if (isAdmin) { + const { token } = await new SessionAdminModel(c).createSessionByUserId( + data.id, + ); - if (isAdmin) { - const { token } = await new SessionAdminModel(c).createSessionByUserId( - data.id, - ); + return c.json({ id: data.id, token }); + } + const { token } = await new SessionModel(c).createSessionByUserId(data.id); return c.json({ id: data.id, token }); - } - const { token } = await new SessionModel(c).createSessionByUserId(data.id); - - return c.json({ id: data.id, token }); + }, }); diff --git a/packages/vitnode/src/api/modules/users/routes/sign-out.route.ts b/packages/vitnode/src/api/modules/users/routes/sign-out.route.ts index a1e3bc763..a089491c8 100644 --- a/packages/vitnode/src/api/modules/users/routes/sign-out.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/sign-out.route.ts @@ -1,47 +1,44 @@ -import { createApiRoute } from '@/api/lib/route'; +import { buildRoute } from '@/api/lib/route'; import { SessionModel } from '@/api/models/session'; import { SessionAdminModel } from '@/api/models/session-admin'; -import { OpenAPIHono, z } from '@hono/zod-openapi'; +import { z } from '@hono/zod-openapi'; -const route = createApiRoute({ - method: 'delete', - description: 'Sign out the current admin', - pluginConfig: { - id: 'core', - name: 'Core', - }, - path: '/', - request: { - body: { - content: { - 'application/json': { - schema: z.object({ - isAdmin: z.boolean().optional().openapi({ - example: false, +export const signOutRoute = buildRoute({ + route: { + method: 'delete', + description: 'Sign out the current admin', + path: '/sign_out', + request: { + body: { + content: { + 'application/json': { + schema: z.object({ + isAdmin: z.boolean().optional().openapi({ + example: false, + }), }), - }), + }, }, }, }, - }, - responses: { - 200: { - description: 'User signed out', - }, - 403: { - description: 'Access Denied', + responses: { + 200: { + description: 'User signed out', + }, + 403: { + description: 'Access Denied', + }, }, }, -}); + handler: async c => { + const { isAdmin } = c.req.valid('json'); + if (isAdmin) { + await new SessionAdminModel(c).deleteSession(); -export const signOutRoute = new OpenAPIHono().openapi(route, async c => { - const { isAdmin } = c.req.valid('json'); - if (isAdmin) { - await new SessionAdminModel(c).deleteSession(); + return c.json({}); + } + await new SessionModel(c).deleteSession(); return c.json({}); - } - await new SessionModel(c).deleteSession(); - - return c.json({}); + }, }); diff --git a/packages/vitnode/src/api/modules/users/routes/sign-up.route.ts b/packages/vitnode/src/api/modules/users/routes/sign-up.route.ts index d766dc7f6..0569a2992 100644 --- a/packages/vitnode/src/api/modules/users/routes/sign-up.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/sign-up.route.ts @@ -1,66 +1,62 @@ -import { createApiRoute } from '@/api/lib/route'; +import { buildRoute } from '@/api/lib/route'; import { PasswordModel } from '@/api/models/password'; import { UserModel } from '@/api/models/user'; -import { OpenAPIHono } from '@hono/zod-openapi'; import { z } from 'zod'; const nameRegex = /^(?!.* {2})[\p{L}\p{N}._@ -]*$/u; -const route = createApiRoute({ - method: 'post', - description: 'Create a new user', - pluginConfig: { - id: 'core', - name: 'Core', - }, - path: '/', - request: { - body: { - required: true, - content: { - 'application/json': { - schema: z.object({ - email: z.string().email().toLowerCase().openapi({ - example: 'test@test.com', - }), - name: z - .string() - .openapi({ example: 'test' }) - .min(3) - .refine(val => nameRegex.test(val), { - message: 'Invalid name', +export const signUpRoute = buildRoute({ + route: { + method: 'post', + description: 'Create a new user', + path: '/sign_up', + request: { + body: { + required: true, + content: { + 'application/json': { + schema: z.object({ + email: z.string().email().toLowerCase().openapi({ + example: 'test@test.com', }), - password: z.string().min(8).openapi({ - example: 'Test123!', + name: z + .string() + .openapi({ example: 'test' }) + .min(3) + .refine(val => nameRegex.test(val), { + message: 'Invalid name', + }), + password: z.string().min(8).openapi({ + example: 'Test123!', + }), + newsletter: z.boolean().default(false).optional(), }), - newsletter: z.boolean().default(false).optional(), - }), + }, }, }, }, - }, - responses: { - 200: { - content: { - 'application/json': { - schema: z.object({ - id: z.string(), - }), + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({ + id: z.string(), + }), + }, }, + description: 'User created', }, - description: 'User created', }, }, -}); + handler: async c => { + const hashedPassword = await new PasswordModel().encryptPassword( + c.req.valid('json').password, + ); + const data = await new UserModel().signUp( + { ...c.req.valid('json'), hashedPassword }, + c.req, + ); -export const signUpRoute = new OpenAPIHono().openapi(route, async c => { - const hashedPassword = await new PasswordModel().encryptPassword( - c.req.valid('json').password, - ); - const data = await new UserModel().signUp( - { ...c.req.valid('json'), hashedPassword }, - c.req, - ); - - return c.json({ id: data.id }); + return c.json({ id: data.id }); + }, }); diff --git a/packages/vitnode/src/api/modules/users/sso/routes/callback.route.ts b/packages/vitnode/src/api/modules/users/sso/routes/callback.route.ts index 4e4da31d0..cf9a3b01a 100644 --- a/packages/vitnode/src/api/modules/users/sso/routes/callback.route.ts +++ b/packages/vitnode/src/api/modules/users/sso/routes/callback.route.ts @@ -1,46 +1,44 @@ -import { createApiRoute } from '@/api/lib/route'; +import { buildRoute } from '@/api/lib/route'; import { SessionModel } from '@/api/models/session'; import { SSOModel } from '@/api/models/sso'; -import { OpenAPIHono } from '@hono/zod-openapi'; import { z } from 'zod'; -const route = createApiRoute({ - method: 'get', - description: 'SSO Callback', - pluginConfig: { - id: 'core', - name: 'Core', - }, - path: '/{providerId}/callback', - request: { - params: z.object({ - providerId: z.string(), - }), - query: z.object({ - code: z.string(), - state: z.string(), - }), - }, - responses: { - 200: { - content: { - 'application/json': { - schema: z.object({ - id: z.string(), - token: z.string(), - }), +export const callbackRoute = buildRoute({ + route: { + method: 'get', + description: 'SSO Callback', + path: '/{providerId}/callback', + request: { + params: z.object({ + providerId: z.string(), + }), + query: z.object({ + code: z.string(), + state: z.string(), + }), + }, + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({ + id: z.string(), + token: z.string(), + }), + }, }, + description: 'URL', }, - description: 'URL', }, }, -}); - -export const callbackRoute = new OpenAPIHono().openapi(route, async c => { - const { providerId } = c.req.valid('param'); - const { code, state } = c.req.valid('query'); - const sso = await new SSOModel(c).callback({ providerId, code, state }); - const { token } = await new SessionModel(c).createSessionByUserId(sso.userId); + handler: async c => { + const { providerId } = c.req.valid('param'); + const { code, state } = c.req.valid('query'); + const sso = await new SSOModel(c).callback({ providerId, code, state }); + const { token } = await new SessionModel(c).createSessionByUserId( + sso.userId, + ); - return c.json({ id: sso.userId, token }); + return c.json({ id: sso.userId, token }); + }, }); diff --git a/packages/vitnode/src/api/modules/users/sso/routes/create-url.route.ts b/packages/vitnode/src/api/modules/users/sso/routes/create-url.route.ts index 2a751a62b..9ef6805b1 100644 --- a/packages/vitnode/src/api/modules/users/sso/routes/create-url.route.ts +++ b/packages/vitnode/src/api/modules/users/sso/routes/create-url.route.ts @@ -1,38 +1,34 @@ -import { createApiRoute } from '@/api/lib/route'; +import { buildRoute } from '@/api/lib/route'; import { SSOModel } from '@/api/models/sso'; -import { OpenAPIHono } from '@hono/zod-openapi'; import { z } from 'zod'; -const route = createApiRoute({ - method: 'post', - pluginConfig: { - id: 'core', - name: 'Core', - }, - description: 'Generate SSO URL', - path: '/{providerId}', - request: { - params: z.object({ - providerId: z.string(), - }), - }, - responses: { - 200: { - content: { - 'application/json': { - schema: z.object({ url: z.string() }), +export const createUrlRoute = buildRoute({ + route: { + method: 'post', + description: 'Generate SSO URL', + path: '/{providerId}', + request: { + params: z.object({ + providerId: z.string(), + }), + }, + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({ url: z.string() }), + }, }, + description: 'URL', }, - description: 'URL', }, }, -}); - -export const createUrlRoute = new OpenAPIHono().openapi(route, async c => { - const { providerId } = c.req.valid('param'); - const url = await new SSOModel(c).getUrl(providerId); + handler: async c => { + const { providerId } = c.req.valid('param'); + const url = await new SSOModel(c).getUrl(providerId); - return c.json({ - url, - }); + return c.json({ + url, + }); + }, }); diff --git a/packages/vitnode/src/api/modules/users/sso/sso.module.ts b/packages/vitnode/src/api/modules/users/sso/sso.module.ts index 862e174d6..f80c2f59a 100644 --- a/packages/vitnode/src/api/modules/users/sso/sso.module.ts +++ b/packages/vitnode/src/api/modules/users/sso/sso.module.ts @@ -1,13 +1,10 @@ -import { createModuleApi } from '@/api/lib/module'; -import { OpenAPIHono } from '@hono/zod-openapi'; +import { buildModule } from '@/api/lib/module'; import { callbackRoute } from './routes/callback.route'; import { createUrlRoute } from './routes/create-url.route'; -export const ssoUserModule = createModuleApi({ +export const ssoUserModule = buildModule({ name: 'sso', plugin: 'core', - routes: new OpenAPIHono() - .route('/', createUrlRoute) - .route('/', callbackRoute), + routes: [callbackRoute, createUrlRoute], }); diff --git a/packages/vitnode/src/api/modules/users/users.module.ts b/packages/vitnode/src/api/modules/users/users.module.ts index ab7831528..178c70040 100644 --- a/packages/vitnode/src/api/modules/users/users.module.ts +++ b/packages/vitnode/src/api/modules/users/users.module.ts @@ -1,5 +1,4 @@ -import { createModuleApi } from '@/api/lib/module'; -import { OpenAPIHono } from '@hono/zod-openapi'; +import { buildModule } from '@/api/lib/module'; import { sessionRoute } from './routes/session.route'; import { signInRoute } from './routes/sign-in.route'; @@ -7,15 +6,11 @@ import { signOutRoute } from './routes/sign-out.route'; import { signUpRoute } from './routes/sign-up.route'; import { ssoUserModule } from './sso/sso.module'; -export const usersModule = createModuleApi({ - name: 'users', +export const usersModule = buildModule({ plugin: 'core', - routes: new OpenAPIHono() - .route('/sign_up', signUpRoute) - .route('/sign_in', signInRoute) - .route('/session', sessionRoute) - .route('/sign_out', signOutRoute) - .route('/sso', ssoUserModule.app), + name: 'users', + // TODO: Add other modules + routes: [sessionRoute, signInRoute, signOutRoute, signUpRoute], }); export type UsersTypes = typeof usersModule; diff --git a/packages/vitnode/src/api/plugin.ts b/packages/vitnode/src/api/plugin.ts index f41b2244a..3462a181b 100644 --- a/packages/vitnode/src/api/plugin.ts +++ b/packages/vitnode/src/api/plugin.ts @@ -1,9 +1,9 @@ -import { createPluginApi } from './lib/plugin'; +import { buildPlugin } from './lib/plugin'; import { adminModule } from './modules/admin/admin.module'; import { middlewareModule } from './modules/middleware/middleware.module'; import { usersModule } from './modules/users/users.module'; -export default createPluginApi({ +export const newBuildPluginCore = buildPlugin({ name: 'core', - modules: [usersModule, middlewareModule, adminModule], + modules: [middlewareModule, usersModule, adminModule], }); diff --git a/packages/vitnode/src/test/fetcher.ts b/packages/vitnode/src/test/fetcher.ts index 57faa3fc9..c9b51b24d 100644 --- a/packages/vitnode/src/test/fetcher.ts +++ b/packages/vitnode/src/test/fetcher.ts @@ -1,4 +1,5 @@ -import { Route } from './route'; +import { Route } from '@/api/lib/route'; + import { Test } from './test'; type FetcherParams< diff --git a/packages/vitnode/src/test/module.ts b/packages/vitnode/src/test/module.ts deleted file mode 100644 index d5fe1bacb..000000000 --- a/packages/vitnode/src/test/module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { OpenAPIHono } from '@hono/zod-openapi'; - -import { Route } from './route'; - -export interface BuildModuleType { - plugin: Plugin; - routes: T; -} - -export function buildModule< - const Routes extends Route, - const P extends string, ->({ routes, plugin }: { plugin: P; routes: Routes }) { - const hono = new OpenAPIHono(); - - routes.forEach(({ handler, route }) => { - hono.openapi(route, handler); - }); - - return { routes, plugin, hono }; -} diff --git a/packages/vitnode/src/test/route.ts b/packages/vitnode/src/test/route.ts deleted file mode 100644 index a9db39b7e..000000000 --- a/packages/vitnode/src/test/route.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { RouteConfig, RouteHandler } from '@hono/zod-openapi'; - -type RoutingPath

= - P extends `${infer Head}/{${infer Param}}${infer Tail}` - ? `${Head}/:${Param}${RoutingPath}` - : P; - -type ValidHandler = ( - c: Parameters>[0], -) => ReturnType>; - -export const buildRoute = < - P extends string, - R extends Omit & { - path: P; - }, - H extends ValidHandler, ->({ - route, - handler, -}: { - handler: H; - route: R; -}): { - handler: H; - route: R & { - getRoutingPath: () => RoutingPath; - }; -} => ({ - route: route as R & { - getRoutingPath: () => RoutingPath; - }, - handler, -}); - -export type Route< - R extends RouteConfig = RouteConfig, - H extends RouteHandler = RouteHandler, -> = readonly { handler: H; route: R }[]; diff --git a/packages/vitnode/src/test/test.ts b/packages/vitnode/src/test/test.ts deleted file mode 100644 index 2d2661fc5..000000000 --- a/packages/vitnode/src/test/test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { z } from '@hono/zod-openapi'; - -import { buildModule } from './module'; -import { buildRoute } from './route'; - -export const test = buildModule({ - plugin: 'test_plugin', - routes: [ - buildRoute({ - route: { - path: '/test34', - method: 'get', - responses: { - 200: { - description: 'Success', - content: { - 'application/json': { - schema: z.object({ message: z.string() }), - }, - }, - }, - }, - }, - handler: c => { - return c.json({ - message: `Hello from ${c.req.path}`, - }); - }, - }), - buildRoute({ - route: { - path: '/test2', - method: 'post', - request: { - body: { - required: true, - content: { - 'application/json': { - schema: z.object({ - email: z.string().email().toLowerCase().openapi({ - example: 'test@test.com', - }), - password: z.string().openapi({ - example: 'Test123!', - }), - isAdmin: z.boolean().optional().openapi({ - example: false, - }), - }), - }, - }, - }, - }, - responses: { - 200: { - description: 'Success 2', - content: { - 'application/json': { - schema: z.object({ - message: z.string(), - }), - }, - }, - }, - }, - }, - handler: c => { - const { isAdmin, email } = c.req.valid('json'); - - return c.json({ - message: `Got request from ${email} with admin status: ${isAdmin ?? false}`, - }); - }, - }), - ], -}); - -export type Test = typeof test; diff --git a/packages/vitnode/src/vitnode.config.ts b/packages/vitnode/src/vitnode.config.ts index 295735b2a..d295eb9eb 100644 --- a/packages/vitnode/src/vitnode.config.ts +++ b/packages/vitnode/src/vitnode.config.ts @@ -1,3 +1,4 @@ +import { BuildPluginReturn } from './api/lib/plugin'; import { PluginConfigReturn } from './plugin.config'; export interface VitNodeConfig { @@ -12,6 +13,7 @@ export interface VitNodeConfig { title: string; }; plugins: PluginConfigReturn[]; + pluginsNew: BuildPluginReturn[]; } export function buildConfig( diff --git a/plugins/blog/src/modules/categories/categories.module.ts b/plugins/blog/src/modules/categories/categories.module.ts index 3557324d7..5db034703 100644 --- a/plugins/blog/src/modules/categories/categories.module.ts +++ b/plugins/blog/src/modules/categories/categories.module.ts @@ -1,9 +1,11 @@ -import { OpenAPIHono } from '@hono/zod-openapi'; +import { buildModule } from 'vitnode/api/lib/module'; import { categoriesRoute } from './route'; -export const categoriesModule = new OpenAPIHono() - .route('/categories', categoriesRoute) - .route('/test', categoriesRoute); +export const categoriesModule = buildModule({ + plugin: 'blog', + name: 'categories', + routes: [categoriesRoute], +}); export type CategoriesTypes = typeof categoriesModule; diff --git a/plugins/blog/src/modules/categories/route.ts b/plugins/blog/src/modules/categories/route.ts index cf0b0d423..32e20fcd0 100644 --- a/plugins/blog/src/modules/categories/route.ts +++ b/plugins/blog/src/modules/categories/route.ts @@ -1,14 +1,10 @@ -import { OpenAPIHono, z } from '@hono/zod-openapi'; -import { createApiRoute } from 'vitnode/api/lib/route'; +import { z } from '@hono/zod-openapi'; +import { buildRoute } from 'vitnode/api/lib/route'; -export const categoriesRoute = new OpenAPIHono().openapi( - createApiRoute({ +export const categoriesRoute = buildRoute({ + route: { method: 'get', path: '/', - pluginConfig: { - id: 'blog', - name: 'Blog', - }, responses: { 200: { content: { @@ -21,10 +17,10 @@ export const categoriesRoute = new OpenAPIHono().openapi( description: 'Test', }, }, - }), - c => { + }, + handler: c => { return c.json({ test: 'test', }); }, -); +}); From 7510ffb7d2dc68842bec19b01fb3bdb229c739b0 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sat, 26 Apr 2025 15:36:24 +0200 Subject: [PATCH 05/11] feat: Add fetcher with type safe arguments --- .github/copilot-instructions.md | 30 +- .../migrations/0001_smooth_grandmaster.sql | 13 + .../migrations/meta/0001_snapshot.json | 1325 +++++++++++++++++ .../database/migrations/meta/_journal.json | 7 + apps/web/src/database/schema/admins.ts | 4 +- apps/web/src/database/schema/config.ts | 2 +- apps/web/src/database/schema/languages.ts | 4 +- apps/web/src/database/schema/moderators.ts | 2 +- apps/web/src/database/schema/roles.ts | 2 +- apps/web/src/database/schema/sessions.ts | 4 +- apps/web/src/database/schema/users.ts | 8 +- apps/web/src/vitnode.config.ts | 1 - packages/vitnode/src/api/lib/module.ts | 33 +- packages/vitnode/src/api/lib/route.ts | 58 +- .../src/api/modules/middleware/route.ts | 1 + .../api/modules/users/routes/test.route.ts | 31 + .../src/api/modules/users/sso/sso.module.ts | 2 + .../users/sso/test/routes/test.route.ts | 31 + .../api/modules/users/sso/test/test.module.ts | 8 + .../src/api/modules/users/users.module.ts | 5 +- .../vitnode/src/database/schema/admins.ts | 4 +- .../vitnode/src/database/schema/config.ts | 2 +- .../vitnode/src/database/schema/languages.ts | 4 +- .../vitnode/src/database/schema/moderators.ts | 2 +- packages/vitnode/src/database/schema/roles.ts | 2 +- .../vitnode/src/database/schema/sessions.ts | 4 +- packages/vitnode/src/database/schema/users.ts | 8 +- packages/vitnode/src/plugin.config.ts | 19 - packages/vitnode/src/test/elo.ts | 137 ++ packages/vitnode/src/test/fetcher.ts | 74 +- packages/vitnode/src/test/test.ts | 82 + packages/vitnode/src/test/testtest.ts | 64 + .../src/views/auth/sign-in/sign-in-view.tsx | 30 +- packages/vitnode/src/vitnode.config.ts | 4 +- 34 files changed, 1873 insertions(+), 134 deletions(-) create mode 100644 apps/web/src/database/migrations/0001_smooth_grandmaster.sql create mode 100644 apps/web/src/database/migrations/meta/0001_snapshot.json create mode 100644 packages/vitnode/src/api/modules/users/routes/test.route.ts create mode 100644 packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts create mode 100644 packages/vitnode/src/api/modules/users/sso/test/test.module.ts delete mode 100644 packages/vitnode/src/plugin.config.ts create mode 100644 packages/vitnode/src/test/elo.ts create mode 100644 packages/vitnode/src/test/test.ts create mode 100644 packages/vitnode/src/test/testtest.ts diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 599da416b..9ec02ca09 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,26 +1,22 @@ -# AI Rules for VitNode +# VitNode VitNode is a comprehensive framework designed to simplify and accelerate application development with Next.js and Hono.js. Built as a monorepo solution managed by Turborepo, VitNode provides a structured environment that makes development faster and less complex. The framework includes an integrated AdminCP and plugin system to extend its core functionality. -# VitNode Technology Stack +> **Important:** VitNode is ESM-only (ECMAScript Modules) -- **Frontend (Web)**: Next.js 15 with Tailwind CSS 4 and Shadcn UI components -- **Backend (API)**: Hono.js with RPC for type-safe API calls -- **Database**: PostgreSQL -- **Documentation**: Fumadocs & Swagger 3 -- **Build System**: Turborepo for monorepo management -- **CI/CD**: GitHub Actions for automated testing, building, and deployment -- ESM (ECMAScript Modules) only +## Frontend Development Guidelines + +### Core Technologies -## Frontend +- **Framework:** Next.js 15 +- **Styling:** Tailwind CSS 4 +- **UI Components:** Shadcn UI +- **Internationalization:** next-intl 4 +- **Icons:** lucide-react 5 +- **Schema Validation:** zod 3 +- **Form Handling:** react-hook-form 7 -- **Framework**: Next.js 15 -- **Styling**: Tailwind CSS 4 -- **UI Components**: Shadcn UI -- **Internationalization**: next-intl 4 -- **Icons**: lucide-react 5 -- **Schema Validation**: zod 3 -- **Form Handling**: react-hook-form 7 +### Architecture Requirements - Use App Router and Server Components for improved performance and SEO - Use server actions for form handling and data mutations from Server Components diff --git a/apps/web/src/database/migrations/0001_smooth_grandmaster.sql b/apps/web/src/database/migrations/0001_smooth_grandmaster.sql new file mode 100644 index 000000000..d2a46d7c7 --- /dev/null +++ b/apps/web/src/database/migrations/0001_smooth_grandmaster.sql @@ -0,0 +1,13 @@ +ALTER TABLE "core_admin_permissions" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_admin_sessions" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_config" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_languages" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_languages_words" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_moderators_permissions" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_roles" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_sessions" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_sessions_known_devices" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_users" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_users_confirm_emails" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_users_forgot_password" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +ALTER TABLE "core_users_sso" ENABLE ROW LEVEL SECURITY; \ No newline at end of file diff --git a/apps/web/src/database/migrations/meta/0001_snapshot.json b/apps/web/src/database/migrations/meta/0001_snapshot.json new file mode 100644 index 000000000..db0c945cf --- /dev/null +++ b/apps/web/src/database/migrations/meta/0001_snapshot.json @@ -0,0 +1,1325 @@ +{ + "id": "c0392ab0-dc3a-4740-9ede-a859832d60bb", + "prevId": "f44bf16f-11ed-4e2c-be2c-08b60fcf720a", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.core_admin_permissions": { + "name": "core_admin_permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "protected": { + "name": "protected", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "core_admin_permissions_role_id_idx": { + "name": "core_admin_permissions_role_id_idx", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "core_admin_permissions_user_id_idx": { + "name": "core_admin_permissions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "core_admin_permissions_role_id_core_roles_id_fk": { + "name": "core_admin_permissions_role_id_core_roles_id_fk", + "tableFrom": "core_admin_permissions", + "tableTo": "core_roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "core_admin_permissions_user_id_core_users_id_fk": { + "name": "core_admin_permissions_user_id_core_users_id_fk", + "tableFrom": "core_admin_permissions", + "tableTo": "core_users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_admin_sessions": { + "name": "core_admin_sessions", + "schema": "", + "columns": { + "token": { + "name": "token", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_seen": { + "name": "last_seen", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "device_id": { + "name": "device_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "core_admin_sessions_token_idx": { + "name": "core_admin_sessions_token_idx", + "columns": [ + { + "expression": "token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "core_admin_sessions_user_id_idx": { + "name": "core_admin_sessions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "core_admin_sessions_user_id_core_users_id_fk": { + "name": "core_admin_sessions_user_id_core_users_id_fk", + "tableFrom": "core_admin_sessions", + "tableTo": "core_users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "core_admin_sessions_device_id_core_sessions_known_devices_id_fk": { + "name": "core_admin_sessions_device_id_core_sessions_known_devices_id_fk", + "tableFrom": "core_admin_sessions", + "tableTo": "core_sessions_known_devices", + "columnsFrom": [ + "device_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_config": { + "name": "core_config", + "schema": "", + "columns": { + "app_type": { + "name": "app_type", + "type": "vitnode_core_app_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'website'" + }, + "restart_server": { + "name": "restart_server", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "editor_sticky": { + "name": "editor_sticky", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "site_name": { + "name": "site_name", + "type": "varchar(150)", + "primaryKey": false, + "notNull": true, + "default": "'VitNode'" + }, + "site_short_name": { + "name": "site_short_name", + "type": "varchar(75)", + "primaryKey": false, + "notNull": true, + "default": "'VitNode'" + }, + "contact_email": { + "name": "contact_email", + "type": "varchar", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "last_updated": { + "name": "last_updated", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "auth_force_login": { + "name": "auth_force_login", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "auth_lock_register": { + "name": "auth_lock_register", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "auth_require_confirm_email": { + "name": "auth_require_confirm_email", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "admin_note": { + "name": "admin_note", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Enter your note here. :)'" + }, + "admin_note_updated_at": { + "name": "admin_note_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_languages": { + "name": "core_languages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "code": { + "name": "code", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "name": "timezone", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "'UTC'" + }, + "protected": { + "name": "protected", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "default": { + "name": "default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "time_24": { + "name": "time_24", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "allow_in_input": { + "name": "allow_in_input", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + } + }, + "indexes": { + "core_languages_code_idx": { + "name": "core_languages_code_idx", + "columns": [ + { + "expression": "code", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "core_languages_name_idx": { + "name": "core_languages_name_idx", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "core_languages_code_unique": { + "name": "core_languages_code_unique", + "nullsNotDistinct": false, + "columns": [ + "code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_languages_words": { + "name": "core_languages_words", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "language_code": { + "name": "language_code", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "plugin_code": { + "name": "plugin_code", + "type": "varchar(50)", + "primaryKey": false, + "notNull": true + }, + "item_id": { + "name": "item_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "table_name": { + "name": "table_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "variable": { + "name": "variable", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "core_languages_words_lang_code_idx": { + "name": "core_languages_words_lang_code_idx", + "columns": [ + { + "expression": "language_code", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "core_languages_words_language_code_core_languages_code_fk": { + "name": "core_languages_words_language_code_core_languages_code_fk", + "tableFrom": "core_languages_words", + "tableTo": "core_languages", + "columnsFrom": [ + "language_code" + ], + "columnsTo": [ + "code" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_moderators_permissions": { + "name": "core_moderators_permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "protected": { + "name": "protected", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "core_moderators_permissions_role_id_idx": { + "name": "core_moderators_permissions_role_id_idx", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "core_moderators_permissions_user_id_idx": { + "name": "core_moderators_permissions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "core_moderators_permissions_role_id_core_roles_id_fk": { + "name": "core_moderators_permissions_role_id_core_roles_id_fk", + "tableFrom": "core_moderators_permissions", + "tableTo": "core_roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "core_moderators_permissions_user_id_core_users_id_fk": { + "name": "core_moderators_permissions_user_id_core_users_id_fk", + "tableFrom": "core_moderators_permissions", + "tableTo": "core_users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_roles": { + "name": "core_roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "protected": { + "name": "protected", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "default": { + "name": "default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "root": { + "name": "root", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "guest": { + "name": "guest", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "color": { + "name": "color", + "type": "varchar(19)", + "primaryKey": false, + "notNull": false + }, + "files_allow_upload": { + "name": "files_allow_upload", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "files_total_max_storage": { + "name": "files_total_max_storage", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 500000 + }, + "files_max_storage_for_submit": { + "name": "files_max_storage_for_submit", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 5000 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_sessions": { + "name": "core_sessions", + "schema": "", + "columns": { + "token": { + "name": "token", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "device_id": { + "name": "device_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "core_sessions_user_id_idx": { + "name": "core_sessions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "core_sessions_user_id_core_users_id_fk": { + "name": "core_sessions_user_id_core_users_id_fk", + "tableFrom": "core_sessions", + "tableTo": "core_users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "core_sessions_device_id_core_sessions_known_devices_id_fk": { + "name": "core_sessions_device_id_core_sessions_known_devices_id_fk", + "tableFrom": "core_sessions", + "tableTo": "core_sessions_known_devices", + "columnsFrom": [ + "device_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "core_sessions_token_unique": { + "name": "core_sessions_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_sessions_known_devices": { + "name": "core_sessions_known_devices", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "ip_address": { + "name": "ip_address", + "type": "varchar(40)", + "primaryKey": false, + "notNull": true + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_seen": { + "name": "last_seen", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "core_sessions_known_devices_ip_address_idx": { + "name": "core_sessions_known_devices_ip_address_idx", + "columns": [ + { + "expression": "ip_address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_users": { + "name": "core_users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name_code": { + "name": "name_code", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "newsletter": { + "name": "newsletter", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "avatar_color": { + "name": "avatar_color", + "type": "varchar(6)", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "birthday": { + "name": "birthday", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "ip_address": { + "name": "ip_address", + "type": "varchar(40)", + "primaryKey": false, + "notNull": true + }, + "language": { + "name": "language", + "type": "varchar(5)", + "primaryKey": false, + "notNull": true, + "default": "'en'" + } + }, + "indexes": { + "core_users_name_code_idx": { + "name": "core_users_name_code_idx", + "columns": [ + { + "expression": "name_code", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "core_users_name_idx": { + "name": "core_users_name_idx", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "core_users_email_idx": { + "name": "core_users_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "core_users_role_id_core_roles_id_fk": { + "name": "core_users_role_id_core_roles_id_fk", + "tableFrom": "core_users", + "tableTo": "core_roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "core_users_language_core_languages_code_fk": { + "name": "core_users_language_core_languages_code_fk", + "tableFrom": "core_users", + "tableTo": "core_languages", + "columnsFrom": [ + "language" + ], + "columnsTo": [ + "code" + ], + "onDelete": "set default", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "core_users_name_code_unique": { + "name": "core_users_name_code_unique", + "nullsNotDistinct": false, + "columns": [ + "name_code" + ] + }, + "core_users_name_unique": { + "name": "core_users_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + }, + "core_users_email_unique": { + "name": "core_users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_users_confirm_emails": { + "name": "core_users_confirm_emails", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "varchar(100)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "core_users_confirm_emails_user_id_core_users_id_fk": { + "name": "core_users_confirm_emails_user_id_core_users_id_fk", + "tableFrom": "core_users_confirm_emails", + "tableTo": "core_users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "core_users_confirm_emails_token_unique": { + "name": "core_users_confirm_emails_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_users_forgot_password": { + "name": "core_users_forgot_password", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "varchar(100)", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "varchar(40)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "core_users_forgot_password_user_id_core_users_id_fk": { + "name": "core_users_forgot_password_user_id_core_users_id_fk", + "tableFrom": "core_users_forgot_password", + "tableTo": "core_users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "core_users_forgot_password_user_id_unique": { + "name": "core_users_forgot_password_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + }, + "core_users_forgot_password_token_unique": { + "name": "core_users_forgot_password_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + }, + "public.core_users_sso": { + "name": "core_users_sso", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "provider_account_id": { + "name": "provider_account_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "core_users_sso_user_id_idx": { + "name": "core_users_sso_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "core_users_sso_user_id_core_users_id_fk": { + "name": "core_users_sso_user_id_core_users_id_fk", + "tableFrom": "core_users_sso", + "tableTo": "core_users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": true + } + }, + "enums": { + "public.vitnode_core_app_type": { + "name": "vitnode_core_app_type", + "schema": "public", + "values": [ + "website", + "article", + "book", + "music.album", + "music.playlist", + "music.radio_station", + "music.song", + "profile", + "video.episode", + "video.movie", + "video.tv_show" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/web/src/database/migrations/meta/_journal.json b/apps/web/src/database/migrations/meta/_journal.json index dac71d09f..0df0a540c 100644 --- a/apps/web/src/database/migrations/meta/_journal.json +++ b/apps/web/src/database/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1744392720507, "tag": "0000_clever_wrecker", "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1745350130388, + "tag": "0001_smooth_grandmaster", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/web/src/database/schema/admins.ts b/apps/web/src/database/schema/admins.ts index 259946bdb..f40a399ed 100644 --- a/apps/web/src/database/schema/admins.ts +++ b/apps/web/src/database/schema/admins.ts @@ -29,7 +29,7 @@ export const core_admin_permissions = pgTable( index('core_admin_permissions_role_id_idx').on(t.role_id), index('core_admin_permissions_user_id_idx').on(t.user_id), ], -); +).enableRLS(); export const core_admin_permissions_relations = relations( core_admin_permissions, @@ -69,7 +69,7 @@ export const core_admin_sessions = pgTable( index('core_admin_sessions_token_idx').on(t.token), index('core_admin_sessions_user_id_idx').on(t.user_id), ], -); +).enableRLS(); export const core_admin_sessions_relations = relations( core_admin_sessions, diff --git a/apps/web/src/database/schema/config.ts b/apps/web/src/database/schema/config.ts index 5457aa77d..c795acac8 100644 --- a/apps/web/src/database/schema/config.ts +++ b/apps/web/src/database/schema/config.ts @@ -30,4 +30,4 @@ export const core_config = pgTable('core_config', t => ({ .timestamp() .notNull() .$onUpdate(() => new Date()), -})); +})).enableRLS(); diff --git a/apps/web/src/database/schema/languages.ts b/apps/web/src/database/schema/languages.ts index 339798b3a..e8b2b3907 100644 --- a/apps/web/src/database/schema/languages.ts +++ b/apps/web/src/database/schema/languages.ts @@ -23,7 +23,7 @@ export const core_languages = pgTable( index('core_languages_code_idx').on(t.code), index('core_languages_name_idx').on(t.name), ], -); +).enableRLS(); export const core_languages_words = pgTable( 'core_languages_words', @@ -42,7 +42,7 @@ export const core_languages_words = pgTable( variable: t.varchar({ length: 255 }).notNull(), }), t => [index('core_languages_words_lang_code_idx').on(t.language_code)], -); +).enableRLS(); export const core_languages_words_relations = relations( core_languages_words, diff --git a/apps/web/src/database/schema/moderators.ts b/apps/web/src/database/schema/moderators.ts index 64271c324..690d6f782 100644 --- a/apps/web/src/database/schema/moderators.ts +++ b/apps/web/src/database/schema/moderators.ts @@ -25,7 +25,7 @@ export const core_moderators_permissions = pgTable( index('core_moderators_permissions_role_id_idx').on(t.role_id), index('core_moderators_permissions_user_id_idx').on(t.user_id), ], -); +).enableRLS(); export const core_moderators_permissions_relations = relations( core_moderators_permissions, diff --git a/apps/web/src/database/schema/roles.ts b/apps/web/src/database/schema/roles.ts index 06939e904..a7be33623 100644 --- a/apps/web/src/database/schema/roles.ts +++ b/apps/web/src/database/schema/roles.ts @@ -15,4 +15,4 @@ export const core_roles = pgTable('core_roles', t => ({ files_allow_upload: t.boolean().notNull().default(true), files_total_max_storage: t.integer().notNull().default(500000), files_max_storage_for_submit: t.integer().notNull().default(5000), -})); +})).enableRLS(); diff --git a/apps/web/src/database/schema/sessions.ts b/apps/web/src/database/schema/sessions.ts index 75dc9876a..c1bd1c660 100644 --- a/apps/web/src/database/schema/sessions.ts +++ b/apps/web/src/database/schema/sessions.ts @@ -23,7 +23,7 @@ export const core_sessions = pgTable( .notNull(), }), t => [index('core_sessions_user_id_idx').on(t.user_id)], -); +).enableRLS(); export const core_sessions_relations = relations(core_sessions, ({ one }) => ({ user: one(core_users, { @@ -45,7 +45,7 @@ export const core_sessions_known_devices = pgTable( last_seen: t.timestamp().notNull().defaultNow(), }), t => [index('core_sessions_known_devices_ip_address_idx').on(t.ip_address)], -); +).enableRLS(); export const core_sessions_known_devices_relations = relations( core_sessions_known_devices, diff --git a/apps/web/src/database/schema/users.ts b/apps/web/src/database/schema/users.ts index 5e91dc31d..87822373b 100644 --- a/apps/web/src/database/schema/users.ts +++ b/apps/web/src/database/schema/users.ts @@ -35,7 +35,7 @@ export const core_users = pgTable( index('core_users_name_idx').on(t.name), index('core_users_email_idx').on(t.email), ], -); +).enableRLS(); export const core_users_relations = relations(core_users, ({ one, many }) => ({ group: one(core_roles, { @@ -75,7 +75,7 @@ export const core_users_sso = pgTable( .$onUpdate(() => new Date()), }), t => [index('core_users_sso_user_id_idx').on(t.user_id)], -); +).enableRLS(); export const core_users_sso_relations = relations( core_users_sso, @@ -101,7 +101,7 @@ export const core_users_confirm_emails = pgTable( created_at: t.timestamp().notNull().defaultNow(), expires: t.timestamp().notNull(), }), -); +).enableRLS(); export const core_users_confirm_emails_relations = relations( core_users_confirm_emails, @@ -129,7 +129,7 @@ export const core_users_forgot_password = pgTable( created_at: t.timestamp().notNull().defaultNow(), expires_at: t.timestamp().notNull(), }), -); +).enableRLS(); export const core_users_forgot_password_relations = relations( core_users_forgot_password, diff --git a/apps/web/src/vitnode.config.ts b/apps/web/src/vitnode.config.ts index 5295d0a90..314bc2e98 100644 --- a/apps/web/src/vitnode.config.ts +++ b/apps/web/src/vitnode.config.ts @@ -7,7 +7,6 @@ export const vitNodeConfig = buildConfig({ shortTitle: 'VitNode', }, plugins: [], - pluginsNew: [], i18n: { locales: ['en', 'pl'] as const, defaultLocale: 'en', diff --git a/packages/vitnode/src/api/lib/module.ts b/packages/vitnode/src/api/lib/module.ts index eb0d63605..7bc640d50 100644 --- a/packages/vitnode/src/api/lib/module.ts +++ b/packages/vitnode/src/api/lib/module.ts @@ -7,30 +7,43 @@ export interface BuildModuleType { routes: T; } -export interface BuildModuleReturn< +export interface BaseBuildModuleReturn< P extends string = string, M extends string = string, - Routes extends Route = Route, + Routes extends Route[] = Route[], > { hono: OpenAPIHono; + modules?: BaseBuildModuleReturn

[]; name: M; plugin: P; - routes?: Routes; + routes: Routes; +} + +export interface BuildModuleReturn< + P extends string, + M extends string, + Routes extends Route[] = [], + Modules extends BaseBuildModuleReturn

[] = [], +> extends BaseBuildModuleReturn { + modules?: Modules; } export function buildModule< const P extends string, const M extends string, - const Routes extends Route, + const Routes extends Route[], + Modules extends BaseBuildModuleReturn

[], >({ routes, plugin, name, + modules, }: { + modules?: Modules; name: M; plugin: P; - routes?: Routes; -}): BuildModuleReturn { + routes: Routes; +}): BuildModuleReturn { const hono = new OpenAPIHono(); if (routes) { @@ -39,5 +52,11 @@ export function buildModule< }); } - return { routes, plugin, hono, name }; + if (modules) { + modules.forEach(module => { + hono.route(`/${module.name}`, module.hono); + }); + } + + return { routes, plugin, hono, name, modules }; } diff --git a/packages/vitnode/src/api/lib/route.ts b/packages/vitnode/src/api/lib/route.ts index 74596f3cf..e2fe5f56b 100644 --- a/packages/vitnode/src/api/lib/route.ts +++ b/packages/vitnode/src/api/lib/route.ts @@ -1,46 +1,11 @@ -import { PluginConfig } from '@/plugin.config'; import { createRoute as createRouteHono, RouteConfig, RouteHandler, } from '@hono/zod-openapi'; -import { MiddlewareHandler } from 'hono'; import { sessionMiddleware } from '../middlewares/session'; -function createApiRoute< - P extends string, - R extends Omit & { - path: P; - }, ->({ - isAuth, - pluginConfig, - ...routeConfig -}: R & { - isAuth?: boolean; - pluginConfig: PluginConfig; -}): R & { - getRoutingPath: () => RoutingPath; -} { - const middlewareFromConfig: MiddlewareHandler[] = routeConfig.middleware - ? Array.isArray(routeConfig.middleware) - ? routeConfig.middleware - : [routeConfig.middleware] - : []; - const tags: string[] = [pluginConfig.name, ...(routeConfig.tags ?? [])]; - - return createRouteHono({ - middleware: isAuth ? [sessionMiddleware(), ...middlewareFromConfig] : [], - tags, - ...routeConfig, - }) as unknown as R & { - getRoutingPath: () => RoutingPath; - }; -} - -// =============== - type RoutingPath

= P extends `${infer Head}/{${infer Param}}${infer Tail}` ? `${Head}/:${Param}${RoutingPath}` @@ -53,6 +18,7 @@ type ValidHandler = ( export const buildRoute = < P extends string, R extends Omit & { + isAuthorization?: boolean; path: P; }, H extends ValidHandler, @@ -68,20 +34,32 @@ export const buildRoute = < getRoutingPath: () => RoutingPath; }; } => { + const { isAuthorization, middleware, ...restOfRoute } = route; const tags: string[] = ['test123 from createRoute', ...(route.tags ?? [])]; + const middlewareArray = middleware + ? Array.isArray(middleware) + ? middleware + : [middleware] + : []; return { - route: { - ...route, + route: createRouteHono({ + middleware: isAuthorization + ? [sessionMiddleware(), ...middlewareArray] + : middlewareArray, tags, - } as R & { + ...restOfRoute, + }) as R & { getRoutingPath: () => RoutingPath; }, handler, }; }; -export type Route< +export interface Route< R extends RouteConfig = RouteConfig, H extends RouteHandler = RouteHandler, -> = readonly { handler: H; route: R }[]; +> { + handler: H; + route: R; +} diff --git a/packages/vitnode/src/api/modules/middleware/route.ts b/packages/vitnode/src/api/modules/middleware/route.ts index 484462421..a67467a12 100644 --- a/packages/vitnode/src/api/modules/middleware/route.ts +++ b/packages/vitnode/src/api/modules/middleware/route.ts @@ -4,6 +4,7 @@ import { z } from 'zod'; export const routeMiddleware = buildRoute({ route: { + isAuth: true, path: '/', method: 'get', description: 'Middleware route with user authentication', diff --git a/packages/vitnode/src/api/modules/users/routes/test.route.ts b/packages/vitnode/src/api/modules/users/routes/test.route.ts new file mode 100644 index 000000000..e438ab11b --- /dev/null +++ b/packages/vitnode/src/api/modules/users/routes/test.route.ts @@ -0,0 +1,31 @@ +import { buildRoute } from '@/api/lib/route'; +import { z } from 'zod'; + +export const testRoute = buildRoute({ + route: { + method: 'get', + description: 'Test route', + path: '/test', + responses: { + 200: { + content: { + 'text/plain': { + schema: z.string(), + }, + }, + description: 'User', + }, + 201: { + content: { + 'text/plain': { + schema: z.string(), + }, + }, + description: 'User', + }, + }, + }, + handler: c => { + return c.text('test'); + }, +}); diff --git a/packages/vitnode/src/api/modules/users/sso/sso.module.ts b/packages/vitnode/src/api/modules/users/sso/sso.module.ts index f80c2f59a..51d407331 100644 --- a/packages/vitnode/src/api/modules/users/sso/sso.module.ts +++ b/packages/vitnode/src/api/modules/users/sso/sso.module.ts @@ -2,9 +2,11 @@ import { buildModule } from '@/api/lib/module'; import { callbackRoute } from './routes/callback.route'; import { createUrlRoute } from './routes/create-url.route'; +import { testModule } from './test/test.module'; export const ssoUserModule = buildModule({ name: 'sso', plugin: 'core', routes: [callbackRoute, createUrlRoute], + modules: [testModule], }); diff --git a/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts b/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts new file mode 100644 index 000000000..d9a857337 --- /dev/null +++ b/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts @@ -0,0 +1,31 @@ +import { buildRoute } from '@/api/lib/route'; +import { z } from 'zod'; + +export const testRoute = buildRoute({ + route: { + method: 'post', + description: 'Test route', + path: '/test', + responses: { + 200: { + content: { + 'text/plain': { + schema: z.string(), + }, + }, + description: 'User', + }, + 201: { + content: { + 'text/plain': { + schema: z.string(), + }, + }, + description: 'User', + }, + }, + }, + handler: c => { + return c.text('test'); + }, +}); diff --git a/packages/vitnode/src/api/modules/users/sso/test/test.module.ts b/packages/vitnode/src/api/modules/users/sso/test/test.module.ts new file mode 100644 index 000000000..bdda23178 --- /dev/null +++ b/packages/vitnode/src/api/modules/users/sso/test/test.module.ts @@ -0,0 +1,8 @@ +import { buildModule } from '@/api/lib/module'; +import { testRoute } from './routes/test.route'; + +export const testModule = buildModule({ + name: 'test', + plugin: 'core', + routes: [testRoute], +}); diff --git a/packages/vitnode/src/api/modules/users/users.module.ts b/packages/vitnode/src/api/modules/users/users.module.ts index 178c70040..b53322560 100644 --- a/packages/vitnode/src/api/modules/users/users.module.ts +++ b/packages/vitnode/src/api/modules/users/users.module.ts @@ -4,13 +4,14 @@ import { sessionRoute } from './routes/session.route'; import { signInRoute } from './routes/sign-in.route'; import { signOutRoute } from './routes/sign-out.route'; import { signUpRoute } from './routes/sign-up.route'; +import { testRoute } from './routes/test.route'; import { ssoUserModule } from './sso/sso.module'; export const usersModule = buildModule({ plugin: 'core', name: 'users', - // TODO: Add other modules - routes: [sessionRoute, signInRoute, signOutRoute, signUpRoute], + routes: [sessionRoute, signInRoute, signOutRoute, signUpRoute, testRoute], + modules: [ssoUserModule], }); export type UsersTypes = typeof usersModule; diff --git a/packages/vitnode/src/database/schema/admins.ts b/packages/vitnode/src/database/schema/admins.ts index 259946bdb..f40a399ed 100644 --- a/packages/vitnode/src/database/schema/admins.ts +++ b/packages/vitnode/src/database/schema/admins.ts @@ -29,7 +29,7 @@ export const core_admin_permissions = pgTable( index('core_admin_permissions_role_id_idx').on(t.role_id), index('core_admin_permissions_user_id_idx').on(t.user_id), ], -); +).enableRLS(); export const core_admin_permissions_relations = relations( core_admin_permissions, @@ -69,7 +69,7 @@ export const core_admin_sessions = pgTable( index('core_admin_sessions_token_idx').on(t.token), index('core_admin_sessions_user_id_idx').on(t.user_id), ], -); +).enableRLS(); export const core_admin_sessions_relations = relations( core_admin_sessions, diff --git a/packages/vitnode/src/database/schema/config.ts b/packages/vitnode/src/database/schema/config.ts index 5457aa77d..c795acac8 100644 --- a/packages/vitnode/src/database/schema/config.ts +++ b/packages/vitnode/src/database/schema/config.ts @@ -30,4 +30,4 @@ export const core_config = pgTable('core_config', t => ({ .timestamp() .notNull() .$onUpdate(() => new Date()), -})); +})).enableRLS(); diff --git a/packages/vitnode/src/database/schema/languages.ts b/packages/vitnode/src/database/schema/languages.ts index 339798b3a..e8b2b3907 100644 --- a/packages/vitnode/src/database/schema/languages.ts +++ b/packages/vitnode/src/database/schema/languages.ts @@ -23,7 +23,7 @@ export const core_languages = pgTable( index('core_languages_code_idx').on(t.code), index('core_languages_name_idx').on(t.name), ], -); +).enableRLS(); export const core_languages_words = pgTable( 'core_languages_words', @@ -42,7 +42,7 @@ export const core_languages_words = pgTable( variable: t.varchar({ length: 255 }).notNull(), }), t => [index('core_languages_words_lang_code_idx').on(t.language_code)], -); +).enableRLS(); export const core_languages_words_relations = relations( core_languages_words, diff --git a/packages/vitnode/src/database/schema/moderators.ts b/packages/vitnode/src/database/schema/moderators.ts index 64271c324..690d6f782 100644 --- a/packages/vitnode/src/database/schema/moderators.ts +++ b/packages/vitnode/src/database/schema/moderators.ts @@ -25,7 +25,7 @@ export const core_moderators_permissions = pgTable( index('core_moderators_permissions_role_id_idx').on(t.role_id), index('core_moderators_permissions_user_id_idx').on(t.user_id), ], -); +).enableRLS(); export const core_moderators_permissions_relations = relations( core_moderators_permissions, diff --git a/packages/vitnode/src/database/schema/roles.ts b/packages/vitnode/src/database/schema/roles.ts index 06939e904..a7be33623 100644 --- a/packages/vitnode/src/database/schema/roles.ts +++ b/packages/vitnode/src/database/schema/roles.ts @@ -15,4 +15,4 @@ export const core_roles = pgTable('core_roles', t => ({ files_allow_upload: t.boolean().notNull().default(true), files_total_max_storage: t.integer().notNull().default(500000), files_max_storage_for_submit: t.integer().notNull().default(5000), -})); +})).enableRLS(); diff --git a/packages/vitnode/src/database/schema/sessions.ts b/packages/vitnode/src/database/schema/sessions.ts index 75dc9876a..c1bd1c660 100644 --- a/packages/vitnode/src/database/schema/sessions.ts +++ b/packages/vitnode/src/database/schema/sessions.ts @@ -23,7 +23,7 @@ export const core_sessions = pgTable( .notNull(), }), t => [index('core_sessions_user_id_idx').on(t.user_id)], -); +).enableRLS(); export const core_sessions_relations = relations(core_sessions, ({ one }) => ({ user: one(core_users, { @@ -45,7 +45,7 @@ export const core_sessions_known_devices = pgTable( last_seen: t.timestamp().notNull().defaultNow(), }), t => [index('core_sessions_known_devices_ip_address_idx').on(t.ip_address)], -); +).enableRLS(); export const core_sessions_known_devices_relations = relations( core_sessions_known_devices, diff --git a/packages/vitnode/src/database/schema/users.ts b/packages/vitnode/src/database/schema/users.ts index 5e91dc31d..87822373b 100644 --- a/packages/vitnode/src/database/schema/users.ts +++ b/packages/vitnode/src/database/schema/users.ts @@ -35,7 +35,7 @@ export const core_users = pgTable( index('core_users_name_idx').on(t.name), index('core_users_email_idx').on(t.email), ], -); +).enableRLS(); export const core_users_relations = relations(core_users, ({ one, many }) => ({ group: one(core_roles, { @@ -75,7 +75,7 @@ export const core_users_sso = pgTable( .$onUpdate(() => new Date()), }), t => [index('core_users_sso_user_id_idx').on(t.user_id)], -); +).enableRLS(); export const core_users_sso_relations = relations( core_users_sso, @@ -101,7 +101,7 @@ export const core_users_confirm_emails = pgTable( created_at: t.timestamp().notNull().defaultNow(), expires: t.timestamp().notNull(), }), -); +).enableRLS(); export const core_users_confirm_emails_relations = relations( core_users_confirm_emails, @@ -129,7 +129,7 @@ export const core_users_forgot_password = pgTable( created_at: t.timestamp().notNull().defaultNow(), expires_at: t.timestamp().notNull(), }), -); +).enableRLS(); export const core_users_forgot_password_relations = relations( core_users_forgot_password, diff --git a/packages/vitnode/src/plugin.config.ts b/packages/vitnode/src/plugin.config.ts deleted file mode 100644 index 03a46a579..000000000 --- a/packages/vitnode/src/plugin.config.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { OpenAPIHono } from '@hono/zod-openapi'; - -export interface VitNodePlugin { - id: string; - routes: OpenAPIHono[]; -} - -export type PluginConfigReturn = VitNodePlugin; - -export function buildPluginConfig(args: VitNodePlugin): PluginConfigReturn { - return { - ...args, - }; -} - -export interface PluginConfig { - id: string; - name: string; -} diff --git a/packages/vitnode/src/test/elo.ts b/packages/vitnode/src/test/elo.ts new file mode 100644 index 000000000..543674d6b --- /dev/null +++ b/packages/vitnode/src/test/elo.ts @@ -0,0 +1,137 @@ +import { BaseBuildModuleReturn, BuildModuleReturn } from '@/api/lib/module'; +import { Route } from '@/api/lib/route'; +import { usersModule } from '@/api/modules/users/users.module'; + +interface RouteSpec { + readonly method: string; + readonly path: string; +} + +interface RouteShape { + readonly route: RouteSpec; +} + +interface ModuleSpec { + readonly modules?: readonly ModuleSpec[]; + readonly name: string; + readonly routes: readonly RouteShape[]; +} + +type SplitPath = S extends `${infer First}/${infer Rest}` + ? [First, ...SplitPath] + : [S]; + +type FindModuleNested< + M extends { modules?: readonly ModuleSpec[] }, + Path extends string[], +> = Path extends [infer First extends string, ...infer Rest extends string[]] + ? Rest['length'] extends 0 + ? Extract[number] extends infer SubM + ? Extract + : never + : FindModuleNested< + Extract< + Extract[number], + { name: First } + >, + Rest + > + : M; + +type ExtractPaths = + M['routes'][number]['route']['path']; + +type ExtractMethod< + M extends { routes: readonly RouteShape[] }, + P extends string, +> = Extract['method']; + +type GetModulePaths< + ModulePath extends string, + MainModule extends string, + Routes extends Route[], + Modules extends BaseBuildModuleReturn[], +> = ModulePath extends MainModule + ? ExtractPaths<{ routes: Routes }> + : ModulePath extends `${MainModule}/${infer Rest}` + ? ExtractPaths>> + : never; + +type GetModuleMethod< + ModulePath extends string, + MainModule extends string, + Path extends string, + Routes extends Route[], + Modules extends BaseBuildModuleReturn[], +> = ModulePath extends MainModule + ? ExtractMethod<{ routes: Routes }, Path> + : ModulePath extends `${MainModule}/${infer Rest}` + ? ExtractMethod< + FindModuleNested<{ modules: Modules }, SplitPath>, + Path + > + : never; + +interface FetcherParams< + P extends string, + M extends string, + Routes extends Route[], + Modules extends BaseBuildModuleReturn

[], + ModuleName extends string, + SelectedPath extends GetModulePaths, +> { + input?: string; + method: Lowercase< + GetModuleMethod + >; + module: ModuleName; + path: SelectedPath; +} + +export function fetcher< + P extends string, + M extends string, + Routes extends Route[], + Modules extends BaseBuildModuleReturn

[], + ModuleName extends + | `${M}/${Modules[number]['name']}/${Extract< + Modules[number]['modules'], + readonly BaseBuildModuleReturn

[] + >[number]['name']}` + | `${M}/${Modules[number]['name']}` + | M, + SelectedPath extends GetModulePaths, +>( + moduleInput: BuildModuleReturn, + params: FetcherParams, +): void { + void moduleInput; + void params; +} + +// Example usage +(() => { + fetcher(usersModule, { + path: '/session', + method: 'get', + module: 'users', + }); + + fetcher(usersModule, { + path: '/{providerId}', + method: 'post', + module: 'users/sso', + }); + + fetcher(usersModule, { + path: '/session', + method: 'post', + module: 'users', + }); + + fetcher(usersModule, { + path: '/{providerId}', + method: 'get', + module: 'users/sso', + }); +})(); diff --git a/packages/vitnode/src/test/fetcher.ts b/packages/vitnode/src/test/fetcher.ts index c9b51b24d..32744b95b 100644 --- a/packages/vitnode/src/test/fetcher.ts +++ b/packages/vitnode/src/test/fetcher.ts @@ -1,22 +1,66 @@ +import { BuildModuleReturn } from '@/api/lib/module'; import { Route } from '@/api/lib/route'; - -import { Test } from './test'; +import { CONFIG } from '@/lib/config'; +import { cookies, headers } from 'next/headers'; type FetcherParams< - T extends { plugin: string; routes: Route }, + T extends { name: string; plugin: string; routes: Route[] }, R extends T['routes'][number], - // eslint-disable-next-line @typescript-eslint/no-explicit-any -> = R extends any - ? Pick & { plugin: T['plugin'] } +> = R extends T['routes'][number] + ? Pick & { + input?: string; + module: T['name']; + plugin: T['plugin']; + } : never; -function fetcher( - params: FetcherParams, -) { - const { path, method, plugin } = params; -} +export async function fetcher< + T extends BuildModuleReturn, + P extends string = T['plugin'], + M extends string = T['name'], +>({ + path, + method, + plugin, + module, + input, +}: FetcherParams): Promise<{ data: never }> { + const formattedPath = path.startsWith('/') ? path : `/${path}`; + const url = new URL( + `/api/${plugin}/${module}${formattedPath}`, + CONFIG.backend.origin, + ); + const [nextInternalHeaders, cookie] = await Promise.all([ + headers(), + cookies(), + ]); + + const response = await fetch(url, { + method: method.toUpperCase(), + headers: new Headers({ + 'Content-Type': 'application/json', + Cookie: cookie.toString(), + ['user-agent']: nextInternalHeaders.get('user-agent') ?? 'node', + ['x-forwarded-for']: + nextInternalHeaders.get('x-forwarded-for') ?? '0.0.0.0', + }), + }); + + const returnValue = { + clone: response.clone, + }; -export const testFetcher = () => { - fetcher({ path: '/test34', method: 'get', plugin: 'test_plugin' }); - fetcher({ path: '/test2', method: 'post', plugin: 'test_plugin' }); -}; + // JSON response + const contentType = response.headers.get('Content-Type') ?? ''; + if (contentType.includes('application/json')) { + return { + data: '', + format: 'json', + ...returnValue, + }; + } + + // const data = await res.json(); + + return { data: '', format: 'text', ...returnValue }; +} diff --git a/packages/vitnode/src/test/test.ts b/packages/vitnode/src/test/test.ts new file mode 100644 index 000000000..261805b46 --- /dev/null +++ b/packages/vitnode/src/test/test.ts @@ -0,0 +1,82 @@ +import { createRoute, OpenAPIHono, z } from '@hono/zod-openapi'; +import { hc } from 'hono/client'; + +import { fetcher } from './testtest'; + +const test1 = new OpenAPIHono().openapi( + createRoute({ + path: '/test123/:test', + method: 'get', + request: { + params: z.object({ + test: z.string(), + }), + }, + responses: { + 200: { + description: 'test', + content: { + 'application/json': { + schema: z.object({ + test: z.string(), + }), + }, + }, + }, + 403: { + description: 'test', + content: { + 'application/json': { + schema: z.object({ + test: z.string(), + }), + }, + }, + }, + }, + }), + c => { + return c.json({ test: 'test' }); + }, +); + +export const test = new OpenAPIHono() + .openapi( + createRoute({ + path: '/test', + method: 'get', + request: { + query: z.object({ + test: z.string(), + }), + }, + responses: { + 200: { + description: 'test', + content: { + 'application/json': { + schema: z.object({ + test: z.string(), + }), + }, + }, + }, + 403: { + description: 'test', + content: { + 'application/json': { + schema: z.object({ + test: z.string(), + }), + }, + }, + }, + }, + }), + c => { + return c.json({ test: 'test' }); + }, + ) + .route('/something', test1); + +const client = hc('http://localhost:3000/api/core/test'); diff --git a/packages/vitnode/src/test/testtest.ts b/packages/vitnode/src/test/testtest.ts new file mode 100644 index 000000000..0aca8b77d --- /dev/null +++ b/packages/vitnode/src/test/testtest.ts @@ -0,0 +1,64 @@ +/* eslint-disable no-console */ +import { BuildModuleReturn } from '@/api/lib/module'; +import { OpenAPIHono } from '@hono/zod-openapi'; +import { UnionToIntersection } from 'hono/utils/types'; + +import type { Client } from './client/types'; + +const createProxy = ( + callback: (opts: { args: unknown[]; path: string[] }) => unknown, + path: string[], +) => { + const proxy = new Proxy(() => {}, { + get(_obj, key) { + if (typeof key !== 'string' || key === 'then') { + return undefined; + } + + return createProxy(callback, [...path, key]); + }, + apply(_1, _2, args) { + return callback({ + path, + args, + }); + }, + }); + + return proxy; +}; + +type UnionFromArrays = T[number] extends (infer U)[] + ? U + : T[number]; + +export function fetcher() { + return createProxy(async function proxyCallback(args) { + const paths = args.path; + + let method = ''; + const lastPartAt0 = paths.at(-1); + if (lastPartAt0 && /^\$/.test(lastPartAt0)) { + const last = paths.pop(); + if (last) { + method = last.replace(/^\$/, ''); + } + } + + const path = paths.join('/'); + + const test = await fetch('http://localhost:3000/' + path); + + if (method === 'ws') { + // TODO: implement ws + } + + console.log('args', args); + console.log('paths', paths); + console.log('method', method); + console.log('path', path); + + return ''; + // }, []) as UnionToIntersection>; + }, []) as UnionToIntersection; +} diff --git a/packages/vitnode/src/views/auth/sign-in/sign-in-view.tsx b/packages/vitnode/src/views/auth/sign-in/sign-in-view.tsx index 0b42da505..8a791020d 100644 --- a/packages/vitnode/src/views/auth/sign-in/sign-in-view.tsx +++ b/packages/vitnode/src/views/auth/sign-in/sign-in-view.tsx @@ -1,6 +1,9 @@ +import { UsersTypes } from '@/api/modules/users/users.module'; import { Card, CardDescription } from '@/components/ui/card'; import { Link } from '@/lib/navigation'; -import { useTranslations } from 'next-intl'; +import { fetcher as fetcherTest } from '@/test/fetcher'; +import { test } from '@/test/test'; +import { fetcher } from '@/test/testtest'; import { getTranslations } from 'next-intl/server'; import { Metadata } from 'next/dist/types'; import React from 'react'; @@ -8,6 +11,24 @@ import React from 'react'; import { SSOButtons, SSOButtonsSkeleton } from '../sso/buttons/sso-buttons'; import { FormSignIn } from './form/form'; +const getData = async () => { + const test123 = fetcher(); + const test12312 = await fetcherTest({ + path: '/session', + method: 'get', + plugin: 'core', + module: 'users', + }); + + const data = await test123.something.test123[':test'].$get({ + param: { + test: 'test', + }, + }); + + console.log('data', data); +}; + export const generateMetadataSignInView = async ( locale: string, ): Promise => { @@ -18,9 +39,10 @@ export const generateMetadataSignInView = async ( }; }; -export const SignInView = () => { - const t = useTranslations('core.auth.sign_in'); - const tGlobal = useTranslations('core.global'); +export const SignInView = async () => { + const t = await getTranslations('core.auth.sign_in'); + const tGlobal = await getTranslations('core.global'); + await getData(); return (

diff --git a/packages/vitnode/src/vitnode.config.ts b/packages/vitnode/src/vitnode.config.ts index d295eb9eb..5b3bbd3b0 100644 --- a/packages/vitnode/src/vitnode.config.ts +++ b/packages/vitnode/src/vitnode.config.ts @@ -1,5 +1,4 @@ import { BuildPluginReturn } from './api/lib/plugin'; -import { PluginConfigReturn } from './plugin.config'; export interface VitNodeConfig { debug?: boolean; @@ -12,8 +11,7 @@ export interface VitNodeConfig { shortTitle?: string; title: string; }; - plugins: PluginConfigReturn[]; - pluginsNew: BuildPluginReturn[]; + plugins: BuildPluginReturn[]; } export function buildConfig( From a2f17c662e583e06c013524819d14d041d6b42f7 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sat, 26 Apr 2025 15:36:31 +0200 Subject: [PATCH 06/11] chore: clean up --- .../api/modules/users/sso/test/test.module.ts | 1 + packages/vitnode/src/test/elo.ts | 159 +++++++++++------- 2 files changed, 100 insertions(+), 60 deletions(-) diff --git a/packages/vitnode/src/api/modules/users/sso/test/test.module.ts b/packages/vitnode/src/api/modules/users/sso/test/test.module.ts index bdda23178..4e6c8517a 100644 --- a/packages/vitnode/src/api/modules/users/sso/test/test.module.ts +++ b/packages/vitnode/src/api/modules/users/sso/test/test.module.ts @@ -1,4 +1,5 @@ import { buildModule } from '@/api/lib/module'; + import { testRoute } from './routes/test.route'; export const testModule = buildModule({ diff --git a/packages/vitnode/src/test/elo.ts b/packages/vitnode/src/test/elo.ts index 543674d6b..e8122f710 100644 --- a/packages/vitnode/src/test/elo.ts +++ b/packages/vitnode/src/test/elo.ts @@ -2,97 +2,142 @@ import { BaseBuildModuleReturn, BuildModuleReturn } from '@/api/lib/module'; import { Route } from '@/api/lib/route'; import { usersModule } from '@/api/modules/users/users.module'; -interface RouteSpec { - readonly method: string; - readonly path: string; -} +// --- Core Type Definitions --- +// Represents the expected shape of a route for type extraction interface RouteShape { - readonly route: RouteSpec; + readonly route: { + readonly method: string; + readonly path: string; + }; } +// Represents the expected shape of a module for type extraction interface ModuleSpec { readonly modules?: readonly ModuleSpec[]; readonly name: string; readonly routes: readonly RouteShape[]; } +// --- Utility Types --- + +// Splits a path string like "a/b/c" into ["a", "b", "c"] type SplitPath = S extends `${infer First}/${infer Rest}` ? [First, ...SplitPath] - : [S]; + : S extends '' // Handle empty string case + ? [] + : [S]; +// Recursively finds a nested module definition based on a path array type FindModuleNested< M extends { modules?: readonly ModuleSpec[] }, Path extends string[], > = Path extends [infer First extends string, ...infer Rest extends string[]] - ? Rest['length'] extends 0 - ? Extract[number] extends infer SubM - ? Extract + ? // Find the sub-module matching the first path segment + Extract[number] extends infer SubModule + ? SubModule extends ModuleSpec & { name: First } + ? // If this is the last segment, return the found sub-module + Rest['length'] extends 0 + ? SubModule + : // Otherwise, recurse into the found sub-module + FindModuleNested + : never // No sub-module found with that name + : never // M['modules'] is not an array or is empty + : // If Path is empty, it implies we are looking for the module M itself + M; + +// Helper to get the target module specification based on the module path string +// It handles the base module case and nested module cases. +type GetTargetModule< + ModulePath extends string, + MainModuleName extends string, + MainRoutes extends readonly RouteShape[], + SubModules extends readonly ModuleSpec[], +> = ModulePath extends MainModuleName + ? { modules: SubModules; name: MainModuleName; routes: MainRoutes } // Return the main module spec + : ModulePath extends `${MainModuleName}/${infer Rest}` + ? SplitPath extends infer PathArray extends string[] + ? PathArray['length'] extends 0 + ? never // Path like "main/" is invalid + : FindModuleNested<{ modules: SubModules }, PathArray> : never - : FindModuleNested< - Extract< - Extract[number], - { name: First } - >, - Rest - > - : M; + : never; // Path doesn't start with the main module name +// Extracts all possible path strings from a module's routes type ExtractPaths = M['routes'][number]['route']['path']; -type ExtractMethod< +// Extracts the method string for a specific path within a module's routes +type ExtractMethodForPath< M extends { routes: readonly RouteShape[] }, P extends string, -> = Extract['method']; +> = Extract['route']['method']; + +// --- Derived Types for Fetcher --- -type GetModulePaths< +// Gets all valid path strings for a given module path (e.g., "users" or "users/sso") +type GetValidPathsForModule< ModulePath extends string, - MainModule extends string, - Routes extends Route[], - Modules extends BaseBuildModuleReturn[], -> = ModulePath extends MainModule - ? ExtractPaths<{ routes: Routes }> - : ModulePath extends `${MainModule}/${infer Rest}` - ? ExtractPaths>> - : never; - -type GetModuleMethod< + MainModuleName extends string, + MainRoutes extends readonly RouteShape[], + SubModules extends readonly ModuleSpec[], +> = ExtractPaths< + GetTargetModule +>; + +// Gets the valid method (lowercase) for a given module path and a specific path within that module +type GetValidMethodForPath< ModulePath extends string, - MainModule extends string, Path extends string, - Routes extends Route[], - Modules extends BaseBuildModuleReturn[], -> = ModulePath extends MainModule - ? ExtractMethod<{ routes: Routes }, Path> - : ModulePath extends `${MainModule}/${infer Rest}` - ? ExtractMethod< - FindModuleNested<{ modules: Modules }, SplitPath>, - Path - > - : never; + MainModuleName extends string, + MainRoutes extends readonly RouteShape[], + SubModules extends readonly ModuleSpec[], +> = Lowercase< + Extract< + ExtractMethodForPath< + GetTargetModule, + Path + >, + string // Ensure we only get string methods + > +>; +// --- Fetcher Function Definition --- + +// Define the structure for the fetcher parameters, using the derived types for constraints interface FetcherParams< + // Generic parameters from BuildModuleReturn P extends string, M extends string, Routes extends Route[], Modules extends BaseBuildModuleReturn

[], - ModuleName extends string, - SelectedPath extends GetModulePaths, + // The specific module path string provided by the user (e.g., "users/sso") + // This complex union type accurately constrains valid module paths. + ModuleName extends + | `${M}/${Modules[number]['name']}/${Extract< + Modules[number]['modules'], + readonly BaseBuildModuleReturn

[] + >[number]['name']}` // Second level sub-module + | `${M}/${Modules[number]['name']}` // First level sub-module (e.g., "users/sso") + // Add support for deeper nesting if necessary: + | M, // Base module name (e.g., "users") + // The specific path string selected within the chosen module + SelectedPath extends GetValidPathsForModule, > { - input?: string; - method: Lowercase< - GetModuleMethod - >; + input?: unknown; // TODO: Define input type based on the route if possible + method: GetValidMethodForPath; module: ModuleName; path: SelectedPath; } +// The fetcher function signature export function fetcher< + // Generic parameters matching BuildModuleReturn P extends string, M extends string, Routes extends Route[], Modules extends BaseBuildModuleReturn

[], + // Constrain ModuleName to valid possibilities based on the module structure ModuleName extends | `${M}/${Modules[number]['name']}/${Extract< Modules[number]['modules'], @@ -100,19 +145,19 @@ export function fetcher< >[number]['name']}` | `${M}/${Modules[number]['name']}` | M, - SelectedPath extends GetModulePaths, + // SelectedPath is constrained based on the chosen ModuleName + SelectedPath extends GetValidPathsForModule, >( - moduleInput: BuildModuleReturn, + _moduleInput: BuildModuleReturn, // Mark as unused params: FetcherParams, ): void { - void moduleInput; - void params; + // Function implementation would go here + void params; // Mark as unused for now } -// Example usage (() => { fetcher(usersModule, { - path: '/session', + path: '/test', method: 'get', module: 'users', }); @@ -124,13 +169,7 @@ export function fetcher< }); fetcher(usersModule, { - path: '/session', - method: 'post', - module: 'users', - }); - - fetcher(usersModule, { - path: '/{providerId}', + path: '/{providerId}/callback', method: 'get', module: 'users/sso', }); From 873cea370e3aa0f34f4af2ecd9a6ee9d7f4553cd Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sat, 26 Apr 2025 16:42:22 +0200 Subject: [PATCH 07/11] perf: Add tsc-alias for vitnode package --- apps/docs/package.json | 14 +- apps/web/package.json | 16 +- package.json | 4 +- packages/create-vitnode-app/package.json | 6 +- packages/eslint/package.json | 10 +- packages/vitnode/package.json | 47 +- plugins/blog/package.json | 15 +- .../modules/categories/categories.module.ts | 2 - plugins/blog/src/modules/categories/test.ts | 15 +- pnpm-lock.yaml | 1937 ++++++++--------- 10 files changed, 926 insertions(+), 1140 deletions(-) diff --git a/apps/docs/package.json b/apps/docs/package.json index 02a0cf23d..c55ce7f75 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -9,12 +9,12 @@ "postinstall": "fumadocs-mdx" }, "dependencies": { - "babel-plugin-react-compiler": "19.0.0-beta-ebf51a3-20250411", - "fumadocs-core": "^15.2.8", - "fumadocs-mdx": "^11.6.0", - "fumadocs-ui": "^15.2.8", + "babel-plugin-react-compiler": "19.1.0-rc.1", + "fumadocs-core": "^15.2.11", + "fumadocs-mdx": "^11.6.1", + "fumadocs-ui": "^15.2.11", "lucide-react": "^0.488.0", - "motion": "^12.7.4", + "motion": "^12.9.2", "next": "^15.3.1", "react": "^19.1.0", "react-dom": "^19.1.0", @@ -23,11 +23,11 @@ "devDependencies": { "@tailwindcss/postcss": "^4.1.4", "@types/mdx": "^2.0.13", - "@types/node": "^22.14.1", + "@types/node": "^22.15.2", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", "postcss": "^8.5.3", - "shiki": "^3.2.2", + "shiki": "^3.3.0", "tailwindcss": "^4.1.4", "typescript": "^5.8.3" } diff --git a/apps/web/package.json b/apps/web/package.json index 0dfbb8241..2ee6c979f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -20,33 +20,33 @@ "@hono/zod-validator": "^0.4.3", "@hookform/resolvers": "^5.0.1", "@react-email/components": "0.0.36", - "babel-plugin-react-compiler": "19.0.0-beta-ebf51a3-20250411", + "babel-plugin-react-compiler": "19.1.0-rc.1", "dotenv": "^16.5.0", "drizzle-kit": "^0.31.0", "drizzle-orm": "^0.42.0", "hono": "^4.7.7", "lucide-react": "^0.488.0", "next": "^15.3.1", - "next-intl": "^4.0.2", + "next-intl": "^4.1.0", "react": "^19.1.0", "react-dom": "^19.1.0", - "react-hook-form": "^7.55.0", + "react-hook-form": "^7.56.1", "sonner": "^2.0.3", "vitnode": "workspace:*", - "zod": "^3.24.3", - "vitnode-blog": "workspace:*" + "vitnode-blog": "workspace:*", + "zod": "^3.24.3" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.4", - "@types/node": "^22.14.1", + "@types/node": "^22.15.2", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", - "eslint": "^9.25.0", + "eslint": "^9.25.1", "eslint-config-typescript-vitnode": "workspace:*", "prettier": "^3.5.3", "react-email": "^4.0.7", "tailwindcss": "^4.1.4", - "tw-animate-css": "^1.2.5", + "tw-animate-css": "^1.2.8", "typescript": "^5.8.3" } } diff --git a/package.json b/package.json index 536827b6c..897baef9c 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,8 @@ "eslint-config-typescript-vitnode": "workspace:*", "prettier": "^3.5.3", "prettier-plugin-tailwindcss": "^0.6.11", - "turbo": "^2.5.0", - "typescript": "^5.8.2" + "turbo": "^2.5.2", + "typescript": "^5.8.3" }, "engines": { "node": ">=22" diff --git a/packages/create-vitnode-app/package.json b/packages/create-vitnode-app/package.json index 9e3294401..57c52c97c 100644 --- a/packages/create-vitnode-app/package.json +++ b/packages/create-vitnode-app/package.json @@ -28,11 +28,11 @@ "typescript" ], "devDependencies": { - "@inquirer/prompts": "^7.4.1", - "@types/node": "^22.14.1", + "@inquirer/prompts": "^7.5.0", + "@types/node": "^22.15.2", "@types/prompts": "^2.4.9", "commander": "^13.1.0", - "eslint": "^9.24.0", + "eslint": "^9.25.1", "eslint-config-typescript-vitnode": "workspace:*", "ora": "^8.2.0", "picocolors": "^1.1.1", diff --git a/packages/eslint/package.json b/packages/eslint/package.json index 6bbc2526f..55640f361 100644 --- a/packages/eslint/package.json +++ b/packages/eslint/package.json @@ -29,14 +29,14 @@ "typescript": "^5.8.3" }, "dependencies": { - "@eslint/js": "^9.25.0", + "@eslint/js": "^9.25.1", "eslint-config-prettier": "^10.1.2", "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-perfectionist": "^4.11.0", + "eslint-plugin-perfectionist": "^4.12.3", "eslint-plugin-prettier": "^5.2.6", "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-compiler": "19.0.0-beta-ebf51a3-20250411", - "eslint-plugin-react-hooks": "^5.2.0", - "typescript-eslint": "^8.30.1" + "eslint-plugin-react-compiler": "19.1.0-rc.1", + "eslint-plugin-react-hooks": "6.0.0-rc1", + "typescript-eslint": "^8.31.0" } } diff --git a/packages/vitnode/package.json b/packages/vitnode/package.json index 6e756ab92..67387ad26 100644 --- a/packages/vitnode/package.json +++ b/packages/vitnode/package.json @@ -8,8 +8,8 @@ "@hookform/resolvers": "^5.0.1", "@react-email/components": "0.0.36", "@swc/cli": "^0.6.0", - "@swc/core": "^1.11.21", - "@types/node": "^22.14.1", + "@swc/core": "^1.11.22", + "@types/node": "^22.15.2", "@types/nodemailer": "^6.4.17", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", @@ -18,20 +18,21 @@ "dotenv": "^16.5.0", "drizzle-kit": "^0.31.0", "drizzle-orm": "^0.42.0", - "eslint": "^9.25.0", + "eslint": "^9.25.1", "eslint-config-typescript-vitnode": "workspace:*", "hono": "^4.7.7", "lucide-react": "^0.488.0", "next": "^15.3.1", - "next-intl": "^4.0.2", + "next-intl": "^4.1.0", "react": "^19.1.0", "react-dom": "^19.1.0", "react-email": "^4.0.7", - "react-hook-form": "^7.55.0", + "react-hook-form": "^7.56.1", "sonner": "^2.0.3", "tailwindcss": "^4.1.4", + "tsc-alias": "^1.8.15", "tsup": "^8.4.0", - "tw-animate-css": "^1.2.5", + "tw-animate-css": "^1.2.8", "typescript": "^5.8.3", "zod": "^3.24.3" }, @@ -54,8 +55,8 @@ "scripts": { "build:scripts": "tsup", "start:scripts": "bun ./dist/scripts/scripts.js", - "build": "tsc && swc src -d dist --config-file .swcrc", - "dev": "concurrently \"tsc -w --preserveWatchOutput\" \"swc src -d dist --config-file .swcrc -w\"", + "build": "tsc && swc src -d dist --config-file .swcrc && tsc-alias -p tsconfig.json", + "dev": "concurrently \"tsc -w --preserveWatchOutput\" \"swc src -d dist --config-file .swcrc -w\" \"tsc-alias -w\"", "dev:email": "email dev", "lint": "eslint .", "lint:fix": "eslint . --fix" @@ -63,28 +64,28 @@ "type": "module", "dependencies": { "@dnd-kit/core": "^6.3.1", - "@radix-ui/react-accordion": "^1.2.7", - "@radix-ui/react-alert-dialog": "^1.1.10", - "@radix-ui/react-checkbox": "^1.2.2", - "@radix-ui/react-collapsible": "^1.1.7", - "@radix-ui/react-context-menu": "^2.2.10", - "@radix-ui/react-dialog": "^1.1.10", - "@radix-ui/react-dropdown-menu": "^2.1.10", - "@radix-ui/react-hover-card": "^1.1.10", + "@radix-ui/react-accordion": "^1.2.8", + "@radix-ui/react-alert-dialog": "^1.1.11", + "@radix-ui/react-checkbox": "^1.2.3", + "@radix-ui/react-collapsible": "^1.1.8", + "@radix-ui/react-context-menu": "^2.2.12", + "@radix-ui/react-dialog": "^1.1.11", + "@radix-ui/react-dropdown-menu": "^2.1.12", + "@radix-ui/react-hover-card": "^1.1.11", "@radix-ui/react-label": "^2.1.4", - "@radix-ui/react-menubar": "^1.1.10", - "@radix-ui/react-popover": "^1.1.10", + "@radix-ui/react-menubar": "^1.1.12", + "@radix-ui/react-popover": "^1.1.11", "@radix-ui/react-progress": "^1.1.4", - "@radix-ui/react-radio-group": "^1.3.2", + "@radix-ui/react-radio-group": "^1.3.4", "@radix-ui/react-select": "^2.2.2", "@radix-ui/react-separator": "^1.1.4", "@radix-ui/react-slider": "^1.3.2", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-switch": "^1.2.2", - "@radix-ui/react-tabs": "^1.1.7", + "@radix-ui/react-tabs": "^1.1.9", "@radix-ui/react-toggle": "^1.1.6", - "@radix-ui/react-toggle-group": "^1.1.6", - "@radix-ui/react-tooltip": "^1.2.3", + "@radix-ui/react-toggle-group": "^1.1.7", + "@radix-ui/react-tooltip": "^1.2.4", "@tanstack/react-query": "^5.74.4", "cache-manager": "^6.4.2", "class-variance-authority": "^0.7.1", @@ -94,7 +95,7 @@ "nodemailer": "^6.10.1", "postgres": "^3.4.5", "react-scan": "^0.3.3", - "resend": "^4.3.0", + "resend": "^4.4.1", "tailwind-merge": "^3.2.0", "vaul": "^1.1.2" } diff --git a/plugins/blog/package.json b/plugins/blog/package.json index fd37f9f9c..e4cb7aec4 100644 --- a/plugins/blog/package.json +++ b/plugins/blog/package.json @@ -13,8 +13,8 @@ } }, "scripts": { - "build": "tsc && swc src -d dist --config-file .swcrc", - "dev": "concurrently \"tsc -w --preserveWatchOutput\" \"swc src -d dist --config-file .swcrc -w\"", + "build": "tsc && swc src -d dist --config-file .swcrc && tsc-alias -p tsconfig.json", + "dev": "concurrently \"tsc -w --preserveWatchOutput\" \"swc src -d dist --config-file .swcrc -w\" \"tsc-alias -w\"", "lint": "eslint .", "lint:fix": "eslint . --fix" }, @@ -22,10 +22,10 @@ "@hono/zod-openapi": "^0.19.5", "drizzle-kit": "^0.30.6", "drizzle-orm": "^0.41.0", - "hono": "^4.7.6", + "hono": "^4.7.7", "lucide-react": "^0.487.0", - "next": "^15.3.0", - "next-intl": "^4.0.2", + "next": "^15.3.1", + "next-intl": "^4.1.0", "react": "^19.1.0", "react-dom": "^19.1.0", "vitnode": "workspace:*", @@ -33,10 +33,11 @@ }, "devDependencies": { "@swc/cli": "^0.6.0", - "@swc/core": "^1.11.20", + "@swc/core": "^1.11.22", "concurrently": "^9.1.2", - "eslint": "^9.24.0", + "eslint": "^9.25.1", "eslint-config-typescript-vitnode": "workspace:*", + "tsc-alias": "^1.8.15", "typescript": "^5.8.3" } } diff --git a/plugins/blog/src/modules/categories/categories.module.ts b/plugins/blog/src/modules/categories/categories.module.ts index 5db034703..b086fff55 100644 --- a/plugins/blog/src/modules/categories/categories.module.ts +++ b/plugins/blog/src/modules/categories/categories.module.ts @@ -7,5 +7,3 @@ export const categoriesModule = buildModule({ name: 'categories', routes: [categoriesRoute], }); - -export type CategoriesTypes = typeof categoriesModule; diff --git a/plugins/blog/src/modules/categories/test.ts b/plugins/blog/src/modules/categories/test.ts index 111565dee..f42ed08d8 100644 --- a/plugins/blog/src/modules/categories/test.ts +++ b/plugins/blog/src/modules/categories/test.ts @@ -1,10 +1,11 @@ -import { fetcher } from 'vitnode/lib/test'; +import { fetcher } from 'vitnode/test/elo'; -import { CategoriesTypes } from './categories.module'; +import { categoriesModule } from './categories.module'; -export const test = async () => { - const client = fetcher(); - const response = await client.categories.$get(); - - return response; +export const test = () => { + fetcher(categoriesModule, { + module: 'categories', + path: '/', + method: 'get', + }); }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad7326f22..8abcaae91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,35 +18,35 @@ importers: specifier: ^0.6.11 version: 0.6.11(prettier-plugin-astro@0.7.2)(prettier@3.5.3) turbo: - specifier: ^2.5.0 - version: 2.5.0 + specifier: ^2.5.2 + version: 2.5.2 typescript: - specifier: ^5.8.2 + specifier: ^5.8.3 version: 5.8.3 apps/docs: dependencies: babel-plugin-react-compiler: - specifier: 19.0.0-beta-ebf51a3-20250411 - version: 19.0.0-beta-ebf51a3-20250411 + specifier: 19.1.0-rc.1 + version: 19.1.0-rc.1 fumadocs-core: - specifier: ^15.2.8 - version: 15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^15.2.11 + version: 15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) fumadocs-mdx: - specifier: ^11.6.0 - version: 11.6.0(@fumadocs/mdx-remote@1.3.0(acorn@8.14.1)(fumadocs-core@15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0))(acorn@8.14.1)(fumadocs-core@15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)) + specifier: ^11.6.1 + version: 11.6.1(@fumadocs/mdx-remote@1.3.0(acorn@8.14.1)(fumadocs-core@15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0))(acorn@8.14.1)(fumadocs-core@15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)) fumadocs-ui: - specifier: ^15.2.8 - version: 15.2.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tailwindcss@4.1.4) + specifier: ^15.2.11 + version: 15.2.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tailwindcss@4.1.4) lucide-react: specifier: ^0.488.0 version: 0.488.0(react@19.1.0) motion: - specifier: ^12.7.4 - version: 12.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^12.9.2 + version: 12.9.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next: specifier: ^15.3.1 - version: 15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: specifier: ^19.1.0 version: 19.1.0 @@ -64,8 +64,8 @@ importers: specifier: ^2.0.13 version: 2.0.13 '@types/node': - specifier: ^22.14.1 - version: 22.14.1 + specifier: ^22.15.2 + version: 22.15.2 '@types/react': specifier: ^19.1.2 version: 19.1.2 @@ -76,8 +76,8 @@ importers: specifier: ^8.5.3 version: 8.5.3 shiki: - specifier: ^3.2.2 - version: 3.2.2 + specifier: ^3.3.0 + version: 3.3.0 tailwindcss: specifier: ^4.1.4 version: 4.1.4 @@ -95,13 +95,13 @@ importers: version: 0.4.3(hono@4.7.7)(zod@3.24.3) '@hookform/resolvers': specifier: ^5.0.1 - version: 5.0.1(react-hook-form@7.55.0(react@19.1.0)) + version: 5.0.1(react-hook-form@7.56.1(react@19.1.0)) '@react-email/components': specifier: 0.0.36 version: 0.0.36(react-dom@19.1.0(react@19.1.0))(react@19.1.0) babel-plugin-react-compiler: - specifier: 19.0.0-beta-ebf51a3-20250411 - version: 19.0.0-beta-ebf51a3-20250411 + specifier: 19.1.0-rc.1 + version: 19.1.0-rc.1 dotenv: specifier: ^16.5.0 version: 16.5.0 @@ -119,10 +119,10 @@ importers: version: 0.488.0(react@19.1.0) next: specifier: ^15.3.1 - version: 15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next-intl: - specifier: ^4.0.2 - version: 4.0.2(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3) + specifier: ^4.1.0 + version: 4.1.0(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3) react: specifier: ^19.1.0 version: 19.1.0 @@ -130,8 +130,8 @@ importers: specifier: ^19.1.0 version: 19.1.0(react@19.1.0) react-hook-form: - specifier: ^7.55.0 - version: 7.55.0(react@19.1.0) + specifier: ^7.56.1 + version: 7.56.1(react@19.1.0) sonner: specifier: ^2.0.3 version: 2.0.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -149,8 +149,8 @@ importers: specifier: ^4.1.4 version: 4.1.4 '@types/node': - specifier: ^22.14.1 - version: 22.14.1 + specifier: ^22.15.2 + version: 22.15.2 '@types/react': specifier: ^19.1.2 version: 19.1.2 @@ -158,8 +158,8 @@ importers: specifier: ^19.1.2 version: 19.1.2(@types/react@19.1.2) eslint: - specifier: ^9.25.0 - version: 9.25.0(jiti@2.4.2) + specifier: ^9.25.1 + version: 9.25.1(jiti@2.4.2) eslint-config-typescript-vitnode: specifier: workspace:* version: link:../../packages/eslint @@ -168,13 +168,13 @@ importers: version: 3.5.3 react-email: specifier: ^4.0.7 - version: 4.0.7(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 4.0.7(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) tailwindcss: specifier: ^4.1.4 version: 4.1.4 tw-animate-css: - specifier: ^1.2.5 - version: 1.2.5 + specifier: ^1.2.8 + version: 1.2.8 typescript: specifier: ^5.8.3 version: 5.8.3 @@ -182,11 +182,11 @@ importers: packages/create-vitnode-app: devDependencies: '@inquirer/prompts': - specifier: ^7.4.1 - version: 7.4.1(@types/node@22.14.1) + specifier: ^7.5.0 + version: 7.5.0(@types/node@22.15.2) '@types/node': - specifier: ^22.14.1 - version: 22.14.1 + specifier: ^22.15.2 + version: 22.15.2 '@types/prompts': specifier: ^2.4.9 version: 2.4.9 @@ -194,8 +194,8 @@ importers: specifier: ^13.1.0 version: 13.1.0 eslint: - specifier: ^9.24.0 - version: 9.24.0(jiti@2.4.2) + specifier: ^9.25.1 + version: 9.25.1(jiti@2.4.2) eslint-config-typescript-vitnode: specifier: workspace:* version: link:../eslint @@ -212,32 +212,32 @@ importers: packages/eslint: dependencies: '@eslint/js': - specifier: ^9.25.0 - version: 9.25.0 + specifier: ^9.25.1 + version: 9.25.1 eslint-config-prettier: specifier: ^10.1.2 - version: 10.1.2(eslint@9.25.0(jiti@2.4.2)) + version: 10.1.2(eslint@9.25.1(jiti@2.4.2)) eslint-plugin-jsx-a11y: specifier: ^6.10.2 - version: 6.10.2(eslint@9.25.0(jiti@2.4.2)) + version: 6.10.2(eslint@9.25.1(jiti@2.4.2)) eslint-plugin-perfectionist: - specifier: ^4.11.0 - version: 4.11.0(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + specifier: ^4.12.3 + version: 4.12.3(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.2.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.2(eslint@9.25.0(jiti@2.4.2)))(eslint@9.25.0(jiti@2.4.2))(prettier@3.5.3) + version: 5.2.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.2(eslint@9.25.1(jiti@2.4.2)))(eslint@9.25.1(jiti@2.4.2))(prettier@3.5.3) eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@9.25.0(jiti@2.4.2)) + version: 7.37.5(eslint@9.25.1(jiti@2.4.2)) eslint-plugin-react-compiler: - specifier: 19.0.0-beta-ebf51a3-20250411 - version: 19.0.0-beta-ebf51a3-20250411(eslint@9.25.0(jiti@2.4.2)) + specifier: 19.1.0-rc.1 + version: 19.1.0-rc.1(eslint@9.25.1(jiti@2.4.2)) eslint-plugin-react-hooks: - specifier: ^5.2.0 - version: 5.2.0(eslint@9.25.0(jiti@2.4.2)) + specifier: 6.0.0-rc1 + version: 6.0.0-rc1(eslint@9.25.1(jiti@2.4.2)) typescript-eslint: - specifier: ^8.30.1 - version: 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + specifier: ^8.31.0 + version: 8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) devDependencies: typescript: specifier: ^5.8.3 @@ -249,44 +249,44 @@ importers: specifier: ^6.3.1 version: 6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-accordion': - specifier: ^1.2.7 - version: 1.2.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.2.8 + version: 1.2.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-alert-dialog': - specifier: ^1.1.10 - version: 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.1.11 + version: 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-checkbox': - specifier: ^1.2.2 - version: 1.2.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.2.3 + version: 1.2.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-collapsible': - specifier: ^1.1.7 - version: 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.1.8 + version: 1.1.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-context-menu': - specifier: ^2.2.10 - version: 2.2.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^2.2.12 + version: 2.2.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-dialog': - specifier: ^1.1.10 - version: 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.1.11 + version: 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-dropdown-menu': - specifier: ^2.1.10 - version: 2.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^2.1.12 + version: 2.1.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-hover-card': - specifier: ^1.1.10 - version: 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.1.11 + version: 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-label': specifier: ^2.1.4 version: 2.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-menubar': - specifier: ^1.1.10 - version: 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.1.12 + version: 1.1.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-popover': - specifier: ^1.1.10 - version: 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.1.11 + version: 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-progress': specifier: ^1.1.4 version: 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-radio-group': - specifier: ^1.3.2 - version: 1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.3.4 + version: 1.3.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-select': specifier: ^2.2.2 version: 2.2.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -303,17 +303,17 @@ importers: specifier: ^1.2.2 version: 1.2.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-tabs': - specifier: ^1.1.7 - version: 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.1.9 + version: 1.1.9(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-toggle': specifier: ^1.1.6 version: 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-toggle-group': - specifier: ^1.1.6 - version: 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.1.7 + version: 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-tooltip': - specifier: ^1.2.3 - version: 1.2.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^1.2.4 + version: 1.2.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@tanstack/react-query': specifier: ^5.74.4 version: 5.74.4(react@19.1.0) @@ -342,8 +342,8 @@ importers: specifier: ^0.3.3 version: 0.3.3(@types/react@19.1.2)(next@15.3.1(@babel/core@7.26.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(rollup@4.40.0) resend: - specifier: ^4.3.0 - version: 4.3.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^4.4.1 + version: 4.4.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) tailwind-merge: specifier: ^3.2.0 version: 3.2.0 @@ -362,19 +362,19 @@ importers: version: 0.4.3(hono@4.7.7)(zod@3.24.3) '@hookform/resolvers': specifier: ^5.0.1 - version: 5.0.1(react-hook-form@7.55.0(react@19.1.0)) + version: 5.0.1(react-hook-form@7.56.1(react@19.1.0)) '@react-email/components': specifier: 0.0.36 version: 0.0.36(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@swc/cli': specifier: ^0.6.0 - version: 0.6.0(@swc/core@1.11.21)(chokidar@4.0.3) + version: 0.6.0(@swc/core@1.11.22)(chokidar@4.0.3) '@swc/core': - specifier: ^1.11.21 - version: 1.11.21 + specifier: ^1.11.22 + version: 1.11.22 '@types/node': - specifier: ^22.14.1 - version: 22.14.1 + specifier: ^22.15.2 + version: 22.15.2 '@types/nodemailer': specifier: ^6.4.17 version: 6.4.17 @@ -400,8 +400,8 @@ importers: specifier: ^0.42.0 version: 0.42.0(@neondatabase/serverless@0.10.4)(@types/pg@8.11.10)(gel@2.0.2)(pg@8.13.1)(postgres@3.4.5) eslint: - specifier: ^9.25.0 - version: 9.25.0(jiti@2.4.2) + specifier: ^9.25.1 + version: 9.25.1(jiti@2.4.2) eslint-config-typescript-vitnode: specifier: workspace:* version: link:../eslint @@ -415,8 +415,8 @@ importers: specifier: ^15.3.1 version: 15.3.1(@babel/core@7.26.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next-intl: - specifier: ^4.0.2 - version: 4.0.2(next@15.3.1(@babel/core@7.26.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3) + specifier: ^4.1.0 + version: 4.1.0(next@15.3.1(@babel/core@7.26.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3) react: specifier: ^19.1.0 version: 19.1.0 @@ -427,20 +427,23 @@ importers: specifier: ^4.0.7 version: 4.0.7(@babel/core@7.26.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-hook-form: - specifier: ^7.55.0 - version: 7.55.0(react@19.1.0) + specifier: ^7.56.1 + version: 7.56.1(react@19.1.0) sonner: specifier: ^2.0.3 version: 2.0.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) tailwindcss: specifier: ^4.1.4 version: 4.1.4 + tsc-alias: + specifier: ^1.8.15 + version: 1.8.15 tsup: specifier: ^8.4.0 - version: 8.4.0(@swc/core@1.11.21)(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.7.1) + version: 8.4.0(@swc/core@1.11.22)(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.7.1) tw-animate-css: - specifier: ^1.2.5 - version: 1.2.5 + specifier: ^1.2.8 + version: 1.2.8 typescript: specifier: ^5.8.3 version: 5.8.3 @@ -452,7 +455,7 @@ importers: dependencies: '@hono/zod-openapi': specifier: ^0.19.5 - version: 0.19.5(hono@4.7.6)(zod@3.24.3) + version: 0.19.5(hono@4.7.7)(zod@3.24.3) drizzle-kit: specifier: ^0.30.6 version: 0.30.6 @@ -460,17 +463,17 @@ importers: specifier: ^0.41.0 version: 0.41.0(@neondatabase/serverless@0.10.4)(@types/pg@8.11.10)(gel@2.0.2)(pg@8.13.1)(postgres@3.4.5) hono: - specifier: ^4.7.6 - version: 4.7.6 + specifier: ^4.7.7 + version: 4.7.7 lucide-react: specifier: ^0.487.0 version: 0.487.0(react@19.1.0) next: - specifier: ^15.3.0 - version: 15.3.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^15.3.1 + version: 15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next-intl: - specifier: ^4.0.2 - version: 4.0.2(next@15.3.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3) + specifier: ^4.1.0 + version: 4.1.0(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3) react: specifier: ^19.1.0 version: 19.1.0 @@ -486,19 +489,22 @@ importers: devDependencies: '@swc/cli': specifier: ^0.6.0 - version: 0.6.0(@swc/core@1.11.20)(chokidar@4.0.3) + version: 0.6.0(@swc/core@1.11.22)(chokidar@4.0.3) '@swc/core': - specifier: ^1.11.20 - version: 1.11.20 + specifier: ^1.11.22 + version: 1.11.22 concurrently: specifier: ^9.1.2 version: 9.1.2 eslint: - specifier: ^9.24.0 - version: 9.24.0(jiti@2.4.2) + specifier: ^9.25.1 + version: 9.25.1(jiti@2.4.2) eslint-config-typescript-vitnode: specifier: workspace:* version: link:../../packages/eslint + tsc-alias: + specifier: ^1.8.15 + version: 1.8.15 typescript: specifier: ^5.8.3 version: 5.8.3 @@ -616,6 +622,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-private-methods@7.25.9': + resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/template@7.27.0': resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} engines: {node: '>=6.9.0'} @@ -686,8 +698,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.25.2': - resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} + '@esbuild/aix-ppc64@0.25.3': + resolution: {integrity: sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -716,8 +728,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.2': - resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} + '@esbuild/android-arm64@0.25.3': + resolution: {integrity: sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -746,8 +758,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.2': - resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} + '@esbuild/android-arm@0.25.3': + resolution: {integrity: sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -776,8 +788,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.2': - resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} + '@esbuild/android-x64@0.25.3': + resolution: {integrity: sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -806,8 +818,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.2': - resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} + '@esbuild/darwin-arm64@0.25.3': + resolution: {integrity: sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -836,8 +848,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.2': - resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} + '@esbuild/darwin-x64@0.25.3': + resolution: {integrity: sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -866,8 +878,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.2': - resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} + '@esbuild/freebsd-arm64@0.25.3': + resolution: {integrity: sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -896,8 +908,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.2': - resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} + '@esbuild/freebsd-x64@0.25.3': + resolution: {integrity: sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -926,8 +938,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.2': - resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} + '@esbuild/linux-arm64@0.25.3': + resolution: {integrity: sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -956,8 +968,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.2': - resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} + '@esbuild/linux-arm@0.25.3': + resolution: {integrity: sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -986,8 +998,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.2': - resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} + '@esbuild/linux-ia32@0.25.3': + resolution: {integrity: sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -1016,8 +1028,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.2': - resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} + '@esbuild/linux-loong64@0.25.3': + resolution: {integrity: sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -1046,8 +1058,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.2': - resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} + '@esbuild/linux-mips64el@0.25.3': + resolution: {integrity: sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -1076,8 +1088,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.2': - resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} + '@esbuild/linux-ppc64@0.25.3': + resolution: {integrity: sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -1106,8 +1118,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.2': - resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} + '@esbuild/linux-riscv64@0.25.3': + resolution: {integrity: sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -1136,8 +1148,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.2': - resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} + '@esbuild/linux-s390x@0.25.3': + resolution: {integrity: sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -1166,8 +1178,8 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.2': - resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} + '@esbuild/linux-x64@0.25.3': + resolution: {integrity: sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==} engines: {node: '>=18'} cpu: [x64] os: [linux] @@ -1184,8 +1196,8 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.25.2': - resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} + '@esbuild/netbsd-arm64@0.25.3': + resolution: {integrity: sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -1214,8 +1226,8 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.2': - resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} + '@esbuild/netbsd-x64@0.25.3': + resolution: {integrity: sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] @@ -1232,8 +1244,8 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.25.2': - resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} + '@esbuild/openbsd-arm64@0.25.3': + resolution: {integrity: sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -1262,8 +1274,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.2': - resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} + '@esbuild/openbsd-x64@0.25.3': + resolution: {integrity: sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -1292,8 +1304,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.2': - resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} + '@esbuild/sunos-x64@0.25.3': + resolution: {integrity: sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -1322,8 +1334,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.2': - resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} + '@esbuild/win32-arm64@0.25.3': + resolution: {integrity: sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -1352,8 +1364,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.2': - resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} + '@esbuild/win32-ia32@0.25.3': + resolution: {integrity: sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -1382,8 +1394,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.2': - resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} + '@esbuild/win32-x64@0.25.3': + resolution: {integrity: sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1406,10 +1418,6 @@ packages: resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.12.0': - resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.13.0': resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1418,12 +1426,8 @@ packages: resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.24.0': - resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.25.0': - resolution: {integrity: sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w==} + '@eslint/js@9.25.1': + resolution: {integrity: sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -1807,8 +1811,8 @@ packages: '@types/node': optional: true - '@inquirer/prompts@7.4.1': - resolution: {integrity: sha512-UlmM5FVOZF0gpoe1PT/jN4vk8JmpIWBlMvTL8M+hlvPmzN89K6z03+IFmyeu/oFCenwdwHDr2gky7nIGSEVvlA==} + '@inquirer/prompts@7.5.0': + resolution: {integrity: sha512-tk8Bx7l5AX/CR0sVfGj3Xg6v7cYlFBkEahH+EgBB+cZib6Fc83dwerTbzj7f2+qKckjIUGsviWRI1d7lx6nqQA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -1816,8 +1820,8 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@4.0.12': - resolution: {integrity: sha512-wNPJZy8Oc7RyGISPxp9/MpTOqX8lr0r+lCCWm7hQra+MDtYRgINv1hxw7R+vKP71Bu/3LszabxOodfV/uTfsaA==} + '@inquirer/rawlist@4.1.0': + resolution: {integrity: sha512-6ob45Oh9pXmfprKqUiEeMz/tjtVTFQTgDDz1xAMKMrIvyrYjAmRbQZjMJfsictlL4phgjLhdLu27IkHNnNjB7g==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -1834,8 +1838,8 @@ packages: '@types/node': optional: true - '@inquirer/select@4.1.1': - resolution: {integrity: sha512-IUXzzTKVdiVNMA+2yUvPxWsSgOG4kfX93jOM4Zb5FgujeInotv5SPIJVeXQ+fO4xu7tW8VowFhdG5JRmmCyQ1Q==} + '@inquirer/select@4.2.0': + resolution: {integrity: sha512-KkXQ4aSySWimpV4V/TUJWdB3tdfENZUU765GjOIZ0uPwdbGIG6jrxD4dDf1w68uP+DVtfNhr1A92B+0mbTZ8FA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -1986,9 +1990,6 @@ packages: '@next/env@15.2.4': resolution: {integrity: sha512-+SFtMgoiYP3WoSswuNmxJOCwi06TdWE733D+WPjpXIe4LXGULwEaofiiAy6kbS0+XjM5xF5n3lKuBwN2SnqD9g==} - '@next/env@15.3.0': - resolution: {integrity: sha512-6mDmHX24nWlHOlbwUiAOmMyY7KELimmi+ed8qWcJYjqXeC+G6JzPZ3QosOAfjNwgMIzwhXBiRiCgdh8axTTdTA==} - '@next/env@15.3.1': resolution: {integrity: sha512-cwK27QdzrMblHSn9DZRV+DQscHXRuJv6MydlJRpFSqJWZrTYMLzKDeyueJNN9MGd8NNiUKzDQADAf+dMLXX7YQ==} @@ -1998,12 +1999,6 @@ packages: cpu: [arm64] os: [darwin] - '@next/swc-darwin-arm64@15.3.0': - resolution: {integrity: sha512-PDQcByT0ZfF2q7QR9d+PNj3wlNN4K6Q8JoHMwFyk252gWo4gKt7BF8Y2+KBgDjTFBETXZ/TkBEUY7NIIY7A/Kw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - '@next/swc-darwin-arm64@15.3.1': resolution: {integrity: sha512-hjDw4f4/nla+6wysBL07z52Gs55Gttp5Bsk5/8AncQLJoisvTBP0pRIBK/B16/KqQyH+uN4Ww8KkcAqJODYH3w==} engines: {node: '>= 10'} @@ -2016,12 +2011,6 @@ packages: cpu: [x64] os: [darwin] - '@next/swc-darwin-x64@15.3.0': - resolution: {integrity: sha512-m+eO21yg80En8HJ5c49AOQpFDq+nP51nu88ZOMCorvw3g//8g1JSUsEiPSiFpJo1KCTQ+jm9H0hwXK49H/RmXg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - '@next/swc-darwin-x64@15.3.1': resolution: {integrity: sha512-q+aw+cJ2ooVYdCEqZVk+T4Ni10jF6Fo5DfpEV51OupMaV5XL6pf3GCzrk6kSSZBsMKZtVC1Zm/xaNBFpA6bJ2g==} engines: {node: '>= 10'} @@ -2034,12 +2023,6 @@ packages: cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-gnu@15.3.0': - resolution: {integrity: sha512-H0Kk04ZNzb6Aq/G6e0un4B3HekPnyy6D+eUBYPJv9Abx8KDYgNMWzKt4Qhj57HXV3sTTjsfc1Trc1SxuhQB+Tg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - '@next/swc-linux-arm64-gnu@15.3.1': resolution: {integrity: sha512-wBQ+jGUI3N0QZyWmmvRHjXjTWFy8o+zPFLSOyAyGFI94oJi+kK/LIZFJXeykvgXUk1NLDAEFDZw/NVINhdk9FQ==} engines: {node: '>= 10'} @@ -2052,12 +2035,6 @@ packages: cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.3.0': - resolution: {integrity: sha512-k8GVkdMrh/+J9uIv/GpnHakzgDQhrprJ/FbGQvwWmstaeFG06nnAoZCJV+wO/bb603iKV1BXt4gHG+s2buJqZA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - '@next/swc-linux-arm64-musl@15.3.1': resolution: {integrity: sha512-IIxXEXRti/AulO9lWRHiCpUUR8AR/ZYLPALgiIg/9ENzMzLn3l0NSxVdva7R/VDcuSEBo0eGVCe3evSIHNz0Hg==} engines: {node: '>= 10'} @@ -2070,12 +2047,6 @@ packages: cpu: [x64] os: [linux] - '@next/swc-linux-x64-gnu@15.3.0': - resolution: {integrity: sha512-ZMQ9yzDEts/vkpFLRAqfYO1wSpIJGlQNK9gZ09PgyjBJUmg8F/bb8fw2EXKgEaHbCc4gmqMpDfh+T07qUphp9A==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - '@next/swc-linux-x64-gnu@15.3.1': resolution: {integrity: sha512-bfI4AMhySJbyXQIKH5rmLJ5/BP7bPwuxauTvVEiJ/ADoddaA9fgyNNCcsbu9SlqfHDoZmfI6g2EjzLwbsVTr5A==} engines: {node: '>= 10'} @@ -2088,12 +2059,6 @@ packages: cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.3.0': - resolution: {integrity: sha512-RFwq5VKYTw9TMr4T3e5HRP6T4RiAzfDJ6XsxH8j/ZeYq2aLsBqCkFzwMI0FmnSsLaUbOb46Uov0VvN3UciHX5A==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - '@next/swc-linux-x64-musl@15.3.1': resolution: {integrity: sha512-FeAbR7FYMWR+Z+M5iSGytVryKHiAsc0x3Nc3J+FD5NVbD5Mqz7fTSy8CYliXinn7T26nDMbpExRUI/4ekTvoiA==} engines: {node: '>= 10'} @@ -2106,12 +2071,6 @@ packages: cpu: [arm64] os: [win32] - '@next/swc-win32-arm64-msvc@15.3.0': - resolution: {integrity: sha512-a7kUbqa/k09xPjfCl0RSVAvEjAkYBYxUzSVAzk2ptXiNEL+4bDBo9wNC43G/osLA/EOGzG4CuNRFnQyIHfkRgQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - '@next/swc-win32-arm64-msvc@15.3.1': resolution: {integrity: sha512-yP7FueWjphQEPpJQ2oKmshk/ppOt+0/bB8JC8svPUZNy0Pi3KbPx2Llkzv1p8CoQa+D2wknINlJpHf3vtChVBw==} engines: {node: '>= 10'} @@ -2124,12 +2083,6 @@ packages: cpu: [x64] os: [win32] - '@next/swc-win32-x64-msvc@15.3.0': - resolution: {integrity: sha512-vHUQS4YVGJPmpjn7r5lEZuMhK5UQBNBRSB+iGDvJjaNk649pTIcRluDWNb9siunyLLiu/LDPHfvxBtNamyuLTw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - '@next/swc-win32-x64-msvc@15.3.1': resolution: {integrity: sha512-3PMvF2zRJAifcRNni9uMk/gulWfWS+qVI/pagd+4yLF5bcXPZPPH2xlYRYOsUjmCJOXSTAC2PjRzbhsRzR2fDQ==} engines: {node: '>= 10'} @@ -2187,8 +2140,8 @@ packages: '@radix-ui/primitive@1.1.2': resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==} - '@radix-ui/react-accordion@1.2.7': - resolution: {integrity: sha512-stDPylBV/3kFHBAFQK/GeyIFaN7q60zWaXthA5/p6egu8AclIN79zG+bv+Ps+exB4JE5rtW/u3Z7SDvmFuTzgA==} + '@radix-ui/react-accordion@1.2.8': + resolution: {integrity: sha512-c7OKBvO36PfQIUGIjj1Wko0hH937pYFU2tR5zbIJDUsmTzHoZVHHt4bmb7OOJbzTaWJtVELKWojBHa7OcnUHmQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2200,8 +2153,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-alert-dialog@1.1.10': - resolution: {integrity: sha512-EJ+FGNgLiOw33YOipPZ4/fZC2x1zKELDBjdJJleYsM6kJCBp3lvAPuXeUoYEHXNvv9iWl5VRU3IT7d/f4A5C7g==} + '@radix-ui/react-alert-dialog@1.1.11': + resolution: {integrity: sha512-4KfkwrFnAw3Y5Jeoq6G+JYSKW0JfIS3uDdFC/79Jw9AsMayZMizSSMxk1gkrolYXsa/WzbbDfOA7/D8N5D+l1g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2226,8 +2179,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-checkbox@1.2.2': - resolution: {integrity: sha512-pMxzQLK+m/tkDRXJg7VUjRx6ozsBdzNLOV4vexfVBU57qT2Gvf4cw2gKKhOohJxjadQ+WcUXCKosTIxcZzi03A==} + '@radix-ui/react-checkbox@1.2.3': + resolution: {integrity: sha512-pHVzDYsnaDmBlAuwim45y3soIN8H4R7KbkSVirGhXO+R/kO2OLCe0eucUEbddaTcdMHHdzcIGHtZSMSQlA+apw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2239,8 +2192,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collapsible@1.1.7': - resolution: {integrity: sha512-zGFsPcFJNdQa/UNd6MOgF40BS054FIGj32oOWBllixz42f+AkQg3QJ1YT9pw7vs+Ai+EgWkh839h69GEK8oH2A==} + '@radix-ui/react-collapsible@1.1.8': + resolution: {integrity: sha512-hxEsLvK9WxIAPyxdDRULL4hcaSjMZCfP7fHB0Z1uUnDoDBat1Zh46hwYfa69DeZAbJrPckjf0AGAtEZyvDyJbw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2274,8 +2227,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-context-menu@2.2.10': - resolution: {integrity: sha512-Mxvhy1W5MGoOn/Cu0wosVpIindudtvCPUZuYity0tKxCl9hZshkV3xbqsH2xf0BmZU5OXbaQkiEoaVmG9Ogq8g==} + '@radix-ui/react-context-menu@2.2.12': + resolution: {integrity: sha512-5UFKuTMX8F2/KjHvyqu9IYT8bEtDSCJwwIx1PghBo4jh9S6jJVsceq9xIjqsOVcxsynGwV5eaqPE3n/Cu+DrSA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2296,8 +2249,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-dialog@1.1.10': - resolution: {integrity: sha512-m6pZb0gEM5uHPSb+i2nKKGQi/HMSVjARMsLMWQfKDP+eJ6B+uqryHnXhpnohTWElw+vEcMk/o4wJODtdRKHwqg==} + '@radix-ui/react-dialog@1.1.11': + resolution: {integrity: sha512-yI7S1ipkP5/+99qhSI6nthfo/tR6bL6Zgxi/+1UO6qPa6UeM6nlafWcQ65vB4rU2XjgjMfMhI3k9Y5MztA62VQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2331,8 +2284,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dropdown-menu@2.1.10': - resolution: {integrity: sha512-8qnILty92BmXbxKugWX3jgEeFeMoxtdggeCCxb/aB7l34QFAKB23IhJfnwyVMbRnAUJiT5LOay4kUS22+AWuRg==} + '@radix-ui/react-dropdown-menu@2.1.12': + resolution: {integrity: sha512-VJoMs+BWWE7YhzEQyVwvF9n22Eiyr83HotCVrMQzla/OwRovXCgah7AcaEr4hMNj4gJxSdtIbcHGvmJXOoJVHA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2366,8 +2319,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-hover-card@1.1.10': - resolution: {integrity: sha512-YXfPbk4IZ/7NGCcU/LzYm0PmJsHK9lWVAsh7uHD8oriaHK2v5GEMaICPRg85ufSnT7FpCRSdMeQbgyx92hEbrg==} + '@radix-ui/react-hover-card@1.1.11': + resolution: {integrity: sha512-q9h9grUpGZKR3MNhtVCLVnPGmx1YnzBgGR+O40mhSNGsUnkR+LChVH8c7FB0mkS+oudhd8KAkZGTJPJCjdAPIg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2401,8 +2354,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-menu@2.1.10': - resolution: {integrity: sha512-OupA+1PrVf2H0K4jIwkDyA+rsJ7vF1y/VxLEO43dmZ68GtCjvx9K1/B/QscPZM3jIeFNK/wPd0HmiLjT36hVcA==} + '@radix-ui/react-menu@2.1.12': + resolution: {integrity: sha512-+qYq6LfbiGo97Zz9fioX83HCiIYYFNs8zAsVCMQrIakoNYylIzWuoD/anAD3UzvvR6cnswmfRFJFq/zYYq/k7Q==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2414,8 +2367,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-menubar@1.1.10': - resolution: {integrity: sha512-z6gfZ7CcqEvGTzd5zGmG+DqDFk31KS9QOBaITeMYt3xwFPRYmfNhLpKKeHLAWNrqQPbvb3RqldsBsDQOAjk96Q==} + '@radix-ui/react-menubar@1.1.12': + resolution: {integrity: sha512-bM2vT5nxRqJH/d1vFQ9jLsW4qR70yFQw2ZD1TUPWUNskDsV0eYeMbbNJqxNjGMOVogEkOJaHtu11kzYdTJvVJg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2427,8 +2380,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-navigation-menu@1.2.9': - resolution: {integrity: sha512-Z7lefjA5VAmEB5ZClxeHGWGQAqhGWgEc6u0MYviUmIVrgGCVLv5mv/jsfUY3tJWI71cVhpQ7dnf/Q6RtM3ylVA==} + '@radix-ui/react-navigation-menu@1.2.10': + resolution: {integrity: sha512-kGDqMVPj2SRB1vJmXN/jnhC66REAXNyDmDRubbbmJ+360zSIJUDmWGMKIJOf72PHMwPENrbtJVb3CMAUJDjEIA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2440,8 +2393,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popover@1.1.10': - resolution: {integrity: sha512-IZN7b3sXqajiPsOzKuNJBSP9obF4MX5/5UhTgWNofw4r1H+eATWb0SyMlaxPD/kzA4vadFgy1s7Z1AEJ6WMyHQ==} + '@radix-ui/react-popover@1.1.11': + resolution: {integrity: sha512-yFMfZkVA5G3GJnBgb2PxrrcLKm1ZLWXrbYVgdyTl//0TYEIHS9LJbnyz7WWcZ0qCq7hIlJZpRtxeSeIG5T5oJw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2479,8 +2432,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-presence@1.1.3': - resolution: {integrity: sha512-IrVLIhskYhH3nLvtcBLQFZr61tBG7wx7O3kEmdzcYwRGAEBmBicGGL7ATzNgruYJ3xBTbuzEEq9OXJM3PAX3tA==} + '@radix-ui/react-presence@1.1.4': + resolution: {integrity: sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2518,8 +2471,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-radio-group@1.3.2': - resolution: {integrity: sha512-Vgixw918V89lbHR+cmZkY6wDbZtc2XUem5m7g7XRwGlzdRSAFA6V5f2ZGok4qeIekGpXbUkypWA91S5OB+AhEg==} + '@radix-ui/react-radio-group@1.3.4': + resolution: {integrity: sha512-N4J9QFdW5zcJNxxY/zwTXBN4Uc5VEuRM7ZLjNfnWoKmNvgrPtNNw4P8zY532O3qL6aPkaNO+gY9y6bfzmH4U1g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2531,8 +2484,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-roving-focus@1.1.6': - resolution: {integrity: sha512-D2ReXCuIueKf5L2f1ks/wTj3bWck1SvK1pjLmEHPbwksS1nOHBsvgY0b9Hypt81FczqBqSyLHQxn/vbsQ0gDHw==} + '@radix-ui/react-roving-focus@1.1.7': + resolution: {integrity: sha512-C6oAg451/fQT3EGbWHbCQjYTtbyjNO1uzQgMzwyivcHT3GKNEmu1q3UuREhN+HzHAVtv3ivMVK08QlC+PkYw9Q==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2544,8 +2497,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-scroll-area@1.2.5': - resolution: {integrity: sha512-VyLjxI8/gXYn+Wij1FLpXjZp6Z/uNklUFQQ75tOpJNESeNaZ2kCRfjiEDmHgWmLeUPeJGwrqbgRmcdFjtYEkMA==} + '@radix-ui/react-scroll-area@1.2.6': + resolution: {integrity: sha512-lj8OMlpPERXrQIHlEQdlXHJoRT52AMpBrgyPYylOhXYq5e/glsEdtOc/kCQlsTdtgN5U0iDbrrolDadvektJGQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2618,8 +2571,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-tabs@1.1.7': - resolution: {integrity: sha512-sawt4HkD+6haVGjYOC3BMIiCumBpqTK6o407n6zN/6yReed2EN7bXyykNrpqg+xCfudpBUZg7Y2cJBd/x/iybA==} + '@radix-ui/react-tabs@1.1.9': + resolution: {integrity: sha512-KIjtwciYvquiW/wAFkELZCVnaNLBsYNhTNcvl+zfMAbMhRkcvNuCLXDDd22L0j7tagpzVh/QwbFpwAATg7ILPw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2631,8 +2584,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-toggle-group@1.1.6': - resolution: {integrity: sha512-XOBq9VqC+mIn5hzjGdJLhQbvQeiOpV5ExNE6qMQQPvFsCT44QUcxFzYytTWVoyWg9XKfgrleKmTeEyu6aoTPhg==} + '@radix-ui/react-toggle-group@1.1.7': + resolution: {integrity: sha512-GRaPJhxrRSOqAcmcX3MwRL/SZACkoYdmoY9/sg7Bd5DhBYsB2t4co0NxTvVW8H7jUmieQDQwRtUlZ5Ta8UbgJA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2657,8 +2610,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-tooltip@1.2.3': - resolution: {integrity: sha512-0KX7jUYFA02np01Y11NWkk6Ip6TqMNmD4ijLelYAzeIndl2aVeltjJFJ2gwjNa1P8U/dgjQ+8cr9Y3Ni+ZNoRA==} + '@radix-ui/react-tooltip@1.2.4': + resolution: {integrity: sha512-DyW8VVeeMSSLFvAmnVnCwvI3H+1tpJFHT50r+tdOoMse9XqYDBCcyux8u3G2y+LOpt7fPQ6KKH0mhs+ce1+Z5w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -3001,29 +2954,29 @@ packages: '@selderee/plugin-htmlparser2@0.11.0': resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} - '@shikijs/core@3.2.2': - resolution: {integrity: sha512-yvlSKVMLjddAGBa2Yu+vUZxuu3sClOWW1AG+UtJkvejYuGM5BVL35s6Ijiwb75O9QdEx6IkMxinHZSi8ZyrBaA==} + '@shikijs/core@3.3.0': + resolution: {integrity: sha512-CovkFL2WVaHk6PCrwv6ctlmD4SS1qtIfN8yEyDXDYWh4ONvomdM9MaFw20qHuqJOcb8/xrkqoWQRJ//X10phOQ==} - '@shikijs/engine-javascript@3.2.2': - resolution: {integrity: sha512-tlDKfhWpF4jKLUyVAnmL+ggIC+0VyteNsUpBzh1iwWLZu4i+PelIRr0TNur6pRRo5UZIv3ss/PLMuwahg9S2hg==} + '@shikijs/engine-javascript@3.3.0': + resolution: {integrity: sha512-XlhnFGv0glq7pfsoN0KyBCz9FJU678LZdQ2LqlIdAj6JKsg5xpYKay3DkazXWExp3DTJJK9rMOuGzU2911pg7Q==} - '@shikijs/engine-oniguruma@3.2.2': - resolution: {integrity: sha512-vyXRnWVCSvokwbaUD/8uPn6Gqsf5Hv7XwcW4AgiU4Z2qwy19sdr6VGzMdheKKN58tJOOe5MIKiNb901bgcUXYQ==} + '@shikijs/engine-oniguruma@3.3.0': + resolution: {integrity: sha512-l0vIw+GxeNU7uGnsu6B+Crpeqf+WTQ2Va71cHb5ZYWEVEPdfYwY5kXwYqRJwHrxz9WH+pjSpXQz+TJgAsrkA5A==} - '@shikijs/langs@3.2.2': - resolution: {integrity: sha512-NY0Urg2dV9ETt3JIOWoMPuoDNwte3geLZ4M1nrPHbkDS8dWMpKcEwlqiEIGqtwZNmt5gKyWpR26ln2Bg2ecPgw==} + '@shikijs/langs@3.3.0': + resolution: {integrity: sha512-zt6Kf/7XpBQKSI9eqku+arLkAcDQ3NHJO6zFjiChI8w0Oz6Jjjay7pToottjQGjSDCFk++R85643WbyINcuL+g==} - '@shikijs/rehype@3.2.2': - resolution: {integrity: sha512-Z/1crAoWBpQoUx/KSjiUM2eT91cjAhxMiInQ8gbgtWm2l2qQEIAWdSk6RJAINq+kl0+KO59QvcKWZHpKhCfXvw==} + '@shikijs/rehype@3.3.0': + resolution: {integrity: sha512-m9clrxedJHyKDwYoAkIUJ7thWGSZwZbA0PeGDST7NHCTGeS227BFn8Hoq2olAtxXo14k5T1JcUCDgyaRZfI4Hw==} - '@shikijs/themes@3.2.2': - resolution: {integrity: sha512-Zuq4lgAxVKkb0FFdhHSdDkALuRpsj1so1JdihjKNQfgM78EHxV2JhO10qPsMrm01FkE3mDRTdF68wfmsqjt6HA==} + '@shikijs/themes@3.3.0': + resolution: {integrity: sha512-tXeCvLXBnqq34B0YZUEaAD1lD4lmN6TOHAhnHacj4Owh7Ptb/rf5XCDeROZt2rEOk5yuka3OOW2zLqClV7/SOg==} - '@shikijs/transformers@3.2.2': - resolution: {integrity: sha512-DQvrPdygc6NNdbfeOZoO1+KiRnnjUQuuPLwsAbUuSKq4QFLD0Ik15FbHojmot5NbgCQRbVr8ufRg8U6X5rGWuQ==} + '@shikijs/transformers@3.3.0': + resolution: {integrity: sha512-PIknEyxfkT7i7at/78ynVmuZEv4+7IcS37f6abxMjQ0pVIPEya8n+KNl7XtfbhNL+U9ElR3UzfSzuD5l5Iu+nw==} - '@shikijs/types@3.2.2': - resolution: {integrity: sha512-a5TiHk7EH5Lso8sHcLHbVNNhWKP0Wi3yVnXnu73g86n3WoDgEra7n3KszyeCGuyoagspQ2fzvy4cpSc8pKhb0A==} + '@shikijs/types@3.3.0': + resolution: {integrity: sha512-KPCGnHG6k06QG/2pnYGbFtFvpVJmC3uIpXrAiPrawETifujPBv0Se2oUxm5qYgjCvGJS9InKvjytOdN+bGuX+Q==} '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} @@ -3052,137 +3005,68 @@ packages: chokidar: optional: true - '@swc/core-darwin-arm64@1.11.20': - resolution: {integrity: sha512-Sc06h6pwMhQagU7vz92b7wwQTIibTiqRE4y/XjkvurSbjSarrtSZR4OKkrdNwUkSy1HlQE4NhKQf7tmLeQ7PhQ==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - - '@swc/core-darwin-arm64@1.11.21': - resolution: {integrity: sha512-v6gjw9YFWvKulCw3ZA1dY+LGMafYzJksm1mD4UZFZ9b36CyHFowYVYug1ajYRIRqEvvfIhHUNV660zTLoVFR8g==} + '@swc/core-darwin-arm64@1.11.22': + resolution: {integrity: sha512-upSiFQfo1TE2QM3+KpBcp5SrOdKKjoc+oUoD1mmBDU2Wv4Bjjv16Z2I5ADvIqMV+b87AhYW+4Qu6iVrQD7j96Q==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.11.20': - resolution: {integrity: sha512-kHANJrgbqaGzUyTectNfLyhnHAeDGGVSRXYyPVAx6x0nuLOnRhKbuSyZY42UEN1IgHauaADCzcd+HiiMv/rgRw==} + '@swc/core-darwin-x64@1.11.22': + resolution: {integrity: sha512-8PEuF/gxIMJVK21DjuCOtzdqstn2DqnxVhpAYfXEtm3WmMqLIOIZBypF/xafAozyaHws4aB/5xmz8/7rPsjavw==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-darwin-x64@1.11.21': - resolution: {integrity: sha512-CUiTiqKlzskwswrx9Ve5NhNoab30L1/ScOfQwr1duvNlFvarC8fvQSgdtpw2Zh3MfnfNPpyLZnYg7ah4kbT9JQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - - '@swc/core-linux-arm-gnueabihf@1.11.20': - resolution: {integrity: sha512-FXllEBeAwU6FNIZzo+u1LmHGaHzwAKzz7tWRkUOqBKjKr20Ot4KGS3xlz2qgV2NESFHAisdHja2P2rcQWqtZRg==} + '@swc/core-linux-arm-gnueabihf@1.11.22': + resolution: {integrity: sha512-NIPTXvqtn9e7oQHgdaxM9Z/anHoXC3Fg4ZAgw5rSGa1OlnKKupt5sdfJamNggSi+eAtyoFcyfkgqHnfe2u63HA==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm-gnueabihf@1.11.21': - resolution: {integrity: sha512-YyBTAFM/QPqt1PscD8hDmCLnqPGKmUZpqeE25HXY8OLjl2MUs8+O4KjwPZZ+OGxpdTbwuWFyMoxjcLy80JODvg==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - - '@swc/core-linux-arm64-gnu@1.11.20': - resolution: {integrity: sha512-OsYMFyJzUM0K8a97tu6KxZaCob3vr+UknVqHO09QwechX+rdX4euWm7Lte4d1B+7SBfokhw7ghLZsNTQfRw9pA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - - '@swc/core-linux-arm64-gnu@1.11.21': - resolution: {integrity: sha512-DQD+ooJmwpNsh4acrftdkuwl5LNxxg8U4+C/RJNDd7m5FP9Wo4c0URi5U0a9Vk/6sQNh9aSGcYChDpqCDWEcBw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - - '@swc/core-linux-arm64-musl@1.11.20': - resolution: {integrity: sha512-fbSWOQ5ZZ7sWodoC6GnzV9RhbImdxoH8b14K1tnHCWJXolzTH40/4JKf/koJ3r24nm1PtsqX9OUxRsOXYAy5dg==} + '@swc/core-linux-arm64-gnu@1.11.22': + resolution: {integrity: sha512-xZ+bgS60c5r8kAeYsLNjJJhhQNkXdidQ277pUabSlu5GjR0CkQUPQ+L9hFeHf8DITEqpPBPRiAiiJsWq5eqMBg==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.11.21': - resolution: {integrity: sha512-y1L49+snt1a1gLTYPY641slqy55QotPdtRK9Y6jMi4JBQyZwxC8swWYlQWb+MyILwxA614fi62SCNZNznB3XSA==} + '@swc/core-linux-arm64-musl@1.11.22': + resolution: {integrity: sha512-JhrP/q5VqQl2eJR0xKYIkKTPjgf8CRsAmRnjJA2PtZhfQ543YbYvUqxyXSRyBOxdyX8JwzuAxIPEAlKlT7PPuQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.11.20': - resolution: {integrity: sha512-OFU53idbY8KA1RkNzZBi0FpoRPSn/anv4N7ZzGZGk664UoFwMbSL+XHGocJzhV9G/VNGH7bMBmgoVWk72nn5hw==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - - '@swc/core-linux-x64-gnu@1.11.21': - resolution: {integrity: sha512-NesdBXv4CvVEaFUlqKj+GA4jJMNUzK2NtKOrUNEtTbXaVyNiXjFCSaDajMTedEB0jTAd9ybB0aBvwhgkJUWkWA==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - - '@swc/core-linux-x64-musl@1.11.20': - resolution: {integrity: sha512-GZbqXEc09nIarkGMXc2P4Hf2ONb1vre22X7Se9CCeU/QtWYRU/H1a2TFnYgBKzNVOH65Dd/XYXcuy+tM1aw1iw==} + '@swc/core-linux-x64-gnu@1.11.22': + resolution: {integrity: sha512-htmAVL+U01gk9GyziVUP0UWYaUQBgrsiP7Ytf6uDffrySyn/FclUS3MDPocNydqYsOpj3OpNKPxkaHK+F+X5fg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.11.21': - resolution: {integrity: sha512-qFV60pwpKVOdmX67wqQzgtSrUGWX9Cibnp1CXyqZ9Mmt8UyYGvmGu7p6PMbTyX7vdpVUvWVRf8DzrW2//wmVHg==} + '@swc/core-linux-x64-musl@1.11.22': + resolution: {integrity: sha512-PL0VHbduWPX+ANoyOzr58jBiL2VnD0xGSFwPy7NRZ1Pr6SNWm4jw3x2u6RjLArGhS5EcWp64BSk9ZxqmTV3FEg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.11.20': - resolution: {integrity: sha512-i0H2MeK8krEd/YeiGz0GHtNL9wSGfAPXiouh8aRNV/u+w4vPaaRqnXwv/yzAW+D2vPpKJBhOwmNFFzdgTJ5mWw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - - '@swc/core-win32-arm64-msvc@1.11.21': - resolution: {integrity: sha512-DJJe9k6gXR/15ZZVLv1SKhXkFst8lYCeZRNHH99SlBodvu4slhh/MKQ6YCixINRhCwliHrpXPym8/5fOq8b7Ig==} + '@swc/core-win32-arm64-msvc@1.11.22': + resolution: {integrity: sha512-moJvFhhTVGoMeEThtdF7hQog80Q00CS06v5uB+32VRuv+I31+4WPRyGlTWHO+oY4rReNcXut/mlDHPH7p0LdFg==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.11.20': - resolution: {integrity: sha512-/7e3X7EGO8uOvAUP+YKJTdoR2JR5vdiewDOnDS9FFXj8yr9x6/oDFLd92Sp9NglF+aXuqAo33IfH2OTz1MR+Ww==} + '@swc/core-win32-ia32-msvc@1.11.22': + resolution: {integrity: sha512-/jnsPJJz89F1aKHIb5ScHkwyzBciz2AjEq2m9tDvQdIdVufdJ4SpEDEN9FqsRNRLcBHjtbLs6bnboA+B+pRFXw==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-ia32-msvc@1.11.21': - resolution: {integrity: sha512-TqEXuy6wedId7bMwLIr9byds+mKsaXVHctTN88R1UIBPwJA92Pdk0uxDgip0pEFzHB/ugU27g6d8cwUH3h2eIw==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - - '@swc/core-win32-x64-msvc@1.11.20': - resolution: {integrity: sha512-rcZpt5uiVNTs/Se+CYBoaDphafFJcsqXo3DNmfkJZoDZUb4PZqxu61p4Qa+lvFDQlRragrlLRpGQM9qnLNd4iQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - - '@swc/core-win32-x64-msvc@1.11.21': - resolution: {integrity: sha512-BT9BNNbMxdpUM1PPAkYtviaV0A8QcXttjs2MDtOeSqqvSJaPtyM+Fof2/+xSwQDmDEFzbGCcn75M5+xy3lGqpA==} + '@swc/core-win32-x64-msvc@1.11.22': + resolution: {integrity: sha512-lc93Y8Mku7LCFGqIxJ91coXZp2HeoDcFZSHCL90Wttg5xhk5xVM9uUCP+OdQsSsEixLF34h5DbT9ObzP8rAdRw==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.11.20': - resolution: {integrity: sha512-2F0+bQs7+pwbudsxRffLdfpGCQX4Ih5k88f7LqTfj2oC7aTrv7FssduOvcAvfVY/InZmyYEblKl1rqg8bvzrZQ==} - engines: {node: '>=10'} - peerDependencies: - '@swc/helpers': '>=0.5.17' - peerDependenciesMeta: - '@swc/helpers': - optional: true - - '@swc/core@1.11.21': - resolution: {integrity: sha512-/Y3BJLcwd40pExmdar8MH2UGGvCBrqNN7hauOMckrEX2Ivcbv3IMhrbGX4od1dnF880Ed8y/E9aStZCIQi0EGw==} + '@swc/core@1.11.22': + resolution: {integrity: sha512-mjPYbqq8XjwqSE0hEPT9CzaJDyxql97LgK4iyvYlwVSQhdN1uK0DBG4eP9PxYzCS2MUGAXB34WFLegdUj5HGpg==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -3335,11 +3219,11 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@20.17.30': - resolution: {integrity: sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==} + '@types/node@20.17.31': + resolution: {integrity: sha512-quODOCNXQAbNf1Q7V+fI8WyErOCh0D5Yd31vHnKu4GkSztGQ7rlltAaqXhHhLl33tlVyUXs2386MkANSwgDn6A==} - '@types/node@22.14.1': - resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==} + '@types/node@22.15.2': + resolution: {integrity: sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==} '@types/nodemailer@6.4.17': resolution: {integrity: sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==} @@ -3372,51 +3256,51 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@typescript-eslint/eslint-plugin@8.30.1': - resolution: {integrity: sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==} + '@typescript-eslint/eslint-plugin@8.31.0': + resolution: {integrity: sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.30.1': - resolution: {integrity: sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==} + '@typescript-eslint/parser@8.31.0': + resolution: {integrity: sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/scope-manager@8.30.1': - resolution: {integrity: sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==} + '@typescript-eslint/scope-manager@8.31.0': + resolution: {integrity: sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.30.1': - resolution: {integrity: sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==} + '@typescript-eslint/type-utils@8.31.0': + resolution: {integrity: sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/types@8.30.1': - resolution: {integrity: sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==} + '@typescript-eslint/types@8.31.0': + resolution: {integrity: sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.30.1': - resolution: {integrity: sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==} + '@typescript-eslint/typescript-estree@8.31.0': + resolution: {integrity: sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.30.1': - resolution: {integrity: sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==} + '@typescript-eslint/utils@8.31.0': + resolution: {integrity: sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/visitor-keys@8.30.1': - resolution: {integrity: sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==} + '@typescript-eslint/visitor-keys@8.31.0': + resolution: {integrity: sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.3.0': @@ -3502,6 +3386,10 @@ packages: any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + arch@3.0.0: resolution: {integrity: sha512-AmIAC+Wtm2AU8lGfTtHsw0Y9Qtftx2YXEEtiBP10xFUtMOA+sHHx6OAddyL52mUKh1vsXQ6/w1mVDptZCyUt4Q==} @@ -3527,6 +3415,10 @@ packages: resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + array.prototype.findlast@1.2.5: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} @@ -3573,8 +3465,8 @@ packages: b4a@1.6.7: resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} - babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411: - resolution: {integrity: sha512-q84bNR9JG1crykAlJUt5Ud0/5BUyMFuQww/mrwIQDFBaxsikqBDj3f/FNDsVd2iR26A1HvXKWPEIfgJDv8/V2g==} + babel-plugin-react-compiler@19.1.0-rc.1: + resolution: {integrity: sha512-M4fpG+Hfq5gWzsJeeMErdRokzg0fdJ8IAk+JDhfB/WLT+U3WwJWR8edphypJrk447/JEvYu6DBFwsTn10bMW4Q==} bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -3600,6 +3492,10 @@ packages: resolution: {integrity: sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw==} engines: {node: '>=12'} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + bippy@0.3.9: resolution: {integrity: sha512-VRAaUmdLkHPvnhXA7RewaAgYlG1JJZfsCE5ljkooQPMvKgosblkisZtkuj1DSOleuoTxVrlmFNA+tICGBdr2bA==} peerDependencies: @@ -3676,11 +3572,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001712: - resolution: {integrity: sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==} - - caniuse-lite@1.0.30001714: - resolution: {integrity: sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg==} + caniuse-lite@1.0.30001715: + resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -3708,6 +3601,10 @@ packages: chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + chokidar@4.0.3: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} @@ -3792,6 +3689,10 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + compute-scroll-into-view@3.1.1: resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==} @@ -3911,8 +3812,8 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} - detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + detect-libc@2.0.4: + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} engines: {node: '>=8'} detect-node-es@1.1.0: @@ -3921,6 +3822,10 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -4135,11 +4040,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.139: - resolution: {integrity: sha512-GGnRYOTdN5LYpwbIr0rwP/ZHOQSvAF6TG0LSzp28uCBb9JiXHJGmaaKw29qjNJc5bGnnp6kXJqRnGMQoELwi5w==} - - emoji-regex-xs@1.0.0: - resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + electron-to-chromium@1.5.142: + resolution: {integrity: sha512-Ah2HgkTu/9RhTDNThBtzu2Wirdy4DC9b0sMT1pUhbkZQ5U/iwmE+PHZX1MpjD5IkJCc2wSghgGG/B04szAx07w==} emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -4233,8 +4135,8 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.25.2: - resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} + esbuild@0.25.3: + resolution: {integrity: sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==} engines: {node: '>=18'} hasBin: true @@ -4262,8 +4164,8 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-perfectionist@4.11.0: - resolution: {integrity: sha512-5s+ehXydnLPQpLDj5mJ0CnYj2fQe6v6gKA3tS+FZVBLzwMOh8skH+l+1Gni08rG0SdEcNhJyjQp/mEkDYK8czw==} + eslint-plugin-perfectionist@4.12.3: + resolution: {integrity: sha512-V0dmpq6fBbn0BYofHsiRuuY9wgkKMDkdruM0mIRBIJ8XZ8vEaTAZqFsywm40RuWNVnduWBt5HO1ZZ+flE2yqjg==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: eslint: '>=8.45.0' @@ -4282,15 +4184,15 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411: - resolution: {integrity: sha512-R7ncuwbCPFAoeMlS56DGGSJFxmRtlWafYH/iWyep5Ks0RaPqTCL4k5gA87axUBBcITsaIgUGkbqAxDxl8Xfm5A==} + eslint-plugin-react-compiler@19.1.0-rc.1: + resolution: {integrity: sha512-3umw5eqZXapBl7aQGmvcjheKhUbsElb9jTETxRZg371e1LG4EPs/zCHt2JzP+wNcdaZWzjU/R730zPUJblY2zw==} engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} peerDependencies: eslint: '>=7' - eslint-plugin-react-hooks@5.2.0: - resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} - engines: {node: '>=10'} + eslint-plugin-react-hooks@6.0.0-rc1: + resolution: {integrity: sha512-I4ntWyjqgGemGtOU85FUdVo00h0i0Y5xvQ7a8EVxyzjOZsxXaxvkKBcYoXbP97QDvDjMzY/nGIvfdB/WRLTGxQ==} + engines: {node: '>=18'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 @@ -4312,18 +4214,8 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.24.0: - resolution: {integrity: sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - eslint@9.25.0: - resolution: {integrity: sha512-MsBdObhM4cEwkzCiraDv7A6txFXEqtNXOb877TsSp2FCkBNl8JfVQrmiuDqC1IkejT6JLPzYBXx/xAiYhyzgGA==} + eslint@9.25.1: + resolution: {integrity: sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -4487,8 +4379,8 @@ packages: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} - framer-motion@12.7.4: - resolution: {integrity: sha512-jX0bPsTmU0oPZTYz/dVyD0dmOyEOEJvdn0TaZBE5I8g2GvVnnQnW9f65cJnoVfUkY3WZWNXGXnPbVA9YnaIfVA==} + framer-motion@12.9.2: + resolution: {integrity: sha512-R0O3Jdqbfwywpm45obP+8sTgafmdEcUoShQTAV+rB5pi+Y1Px/FYL5qLLRe5tPtBdN1J4jos7M+xN2VV2oEAbQ==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -4511,8 +4403,8 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - fumadocs-core@15.2.8: - resolution: {integrity: sha512-+ySqGximB5/6Tu2/g+r0muAN9DJUfScBhTqxdlpFyie2K5sprYbak0aMWXHzHoGDOVu/IbYpSGwe6r7XkdYAsA==} + fumadocs-core@15.2.11: + resolution: {integrity: sha512-pFAhe2s8YU4pl1sXtLWd63rX6NHfeAK8+5/HRMUzAKwPqJYXv5Kv4KxE9mxVEd+3jbtjEjJC4o2GpdJV31oivQ==} peerDependencies: '@oramacloud/client': 1.x.x || 2.x.x algoliasearch: 4.24.0 @@ -4531,8 +4423,8 @@ packages: react-dom: optional: true - fumadocs-mdx@11.6.0: - resolution: {integrity: sha512-g0mArgliPBcZgi4691lwTCIw52y2BbxwIila7a6fQ6AEcu236uiBsDHWT4dm+xyjR3S84MlYkty9z2BWVTTNhg==} + fumadocs-mdx@11.6.1: + resolution: {integrity: sha512-z+H/eOJC4II0VW7rgf6btqeEkD9DEG1SNToNCYKMklCJAc9Y6l+NuQozKuknP2Ey6NK+Qqhvwhi2MOq38YLSeQ==} hasBin: true peerDependencies: '@fumadocs/mdx-remote': ^1.2.0 @@ -4542,8 +4434,8 @@ packages: '@fumadocs/mdx-remote': optional: true - fumadocs-ui@15.2.8: - resolution: {integrity: sha512-N70PXNbzWMKAEvImiTXLJIXLUiS2QGdiVwKBp7RLEZgn/WA3lrLVb7ug0S72p2RtmiADTb1yEbmJrIGwRWlrQQ==} + fumadocs-ui@15.2.11: + resolution: {integrity: sha512-0m9L0zPQHXyJocSS8vWhXCb/GvfD8IMdSUTIWLGirczN59TDMmJ3QgDIgAegO8IF/StxtUY5/REcq4mtQnxahg==} peerDependencies: next: 14.x.x || 15.x.x react: 18.x.x || 19.x.x @@ -4639,6 +4531,10 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -4705,10 +4601,6 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.7.6: - resolution: {integrity: sha512-564rVzELU+9BRqqx5k8sT2NFwGD3I3Vifdb6P7CmM6FiarOSY+fDC+6B+k9wcCb86ReoayteZP2ki0cRLN1jbw==} - engines: {node: '>=16.9.0'} - hono@4.7.7: resolution: {integrity: sha512-2PCpQRbN87Crty8/L/7akZN3UyZIAopSoRxCwRbJgUuV1+MHNFHzYFxZTg4v/03cXUm+jce/qa2VSBZpKBm3Qw==} engines: {node: '>=16.9.0'} @@ -4795,6 +4687,10 @@ packages: resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} engines: {node: '>= 0.4'} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + is-boolean-object@1.2.2: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} @@ -4995,8 +4891,8 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - keyv@5.3.2: - resolution: {integrity: sha512-Lji2XRxqqa5Wg+CHLVfFKBImfJZ4pCSccu9eVWK6w4c2SDFLd8JAn1zqTuSFnsxb7ope6rMsnIHfp+eBbRBRZQ==} + keyv@5.3.3: + resolution: {integrity: sha512-Rwu4+nXI9fqcxiEHtbkvoes2X+QfkTRo1TMkPfwzipGsJlJO/z69vqB4FNl9xJ3xCpAcbkvmEabZfPzrwN3+gQ==} kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} @@ -5379,14 +5275,14 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - motion-dom@12.7.4: - resolution: {integrity: sha512-1ZUHAoSUMMxP6jPqyxlk9XUfb6NxMsnWPnH2YGhrOhTURLcXWbETi6eemoKb60Pe32NVJYduL4B62VQSO5Jq8Q==} + motion-dom@12.9.1: + resolution: {integrity: sha512-xqXEwRLDYDTzOgXobSoWtytRtGlf7zdkRfFbrrdP7eojaGQZ5Go4OOKtgnx7uF8sAkfr1ZjMvbCJSCIT2h6fkQ==} - motion-utils@12.7.2: - resolution: {integrity: sha512-XhZwqctxyJs89oX00zn3OGCuIIpVevbTa+u82usWBC6pSHUd2AoNWiYa7Du8tJxJy9TFbZ82pcn5t7NOm1PHAw==} + motion-utils@12.8.3: + resolution: {integrity: sha512-GYVauZEbca8/zOhEiYOY9/uJeedYQld6co/GJFKOy//0c/4lDqk0zB549sBYqqV2iMuX+uHrY1E5zd8A2L+1Lw==} - motion@12.7.4: - resolution: {integrity: sha512-MBGrMbYageHw4iZJn+pGTr7abq5n53jCxYkhFC1It3vYukQPRWg5zij46MnwYGpLR8KG465MLHSASXot9edYOw==} + motion@12.9.2: + resolution: {integrity: sha512-2hwi4wlOpt/zDHcDZATL2FFhYgj2n6t5Hd0UT91swMup6dx6KpFRkTydYJkkV0PUImT1QfC+WT5d0eRekTKpcg==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -5410,6 +5306,10 @@ packages: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} + mylas@2.1.13: + resolution: {integrity: sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==} + engines: {node: '>=12.0.0'} + mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -5433,8 +5333,8 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} - next-intl@4.0.2: - resolution: {integrity: sha512-3cKVflwdrqxCOvAL+DtGN68qR802i0PEj0dttkAD5IK5XxOjugQs4yU8aSakvPMbkOrhEJ+89z5lG2EAqi7Gkw==} + next-intl@4.1.0: + resolution: {integrity: sha512-JNJRjc7sdnfUxhZmGcvzDszZ60tQKrygV/VLsgzXhnJDxQPn1cN2rVpc53adA1SvBJwPK2O6Sc6b4gYSILjCzw==} peerDependencies: next: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 @@ -5470,27 +5370,6 @@ packages: sass: optional: true - next@15.3.0: - resolution: {integrity: sha512-k0MgP6BsK8cZ73wRjMazl2y2UcXj49ZXLDEgx6BikWuby/CN+nh81qFFI16edgd7xYpe/jj2OZEIwCoqnzz0bQ==} - engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 - babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - next@15.3.1: resolution: {integrity: sha512-8+dDV0xNLOgHlyBxP1GwHGVaNXsmp+2NhZEYrXr24GWLHtt27YrBPbPuHvzlhi7kZNYjeJNR93IF5zfFu5UL0g==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} @@ -5570,11 +5449,11 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} - oniguruma-parser@0.11.2: - resolution: {integrity: sha512-F7Ld4oDZJCI5/wCZ8AOffQbqjSzIRpKH7I/iuSs1SkhZeCj0wS6PMZ4W6VA16TWHrAo0Y9bBKEJOe7tvwcTXnw==} + oniguruma-parser@0.12.0: + resolution: {integrity: sha512-fD9o5ebCmEAA9dLysajdQvuKzLL7cj+w7DQjuO3Cb6IwafENfx6iL+RGkmyW82pVRsvgzixsWinHvgxTMJvdIA==} - oniguruma-to-es@4.2.0: - resolution: {integrity: sha512-MDPs6KSOLS0tKQ7joqg44dRIRZUyotfTy0r+7oEEs6VwWWP0+E2PPDYWMFN0aqOjRyWHBYq7RfKw9GQk2S2z5g==} + oniguruma-to-es@4.3.1: + resolution: {integrity: sha512-VtX1kepWO+7HG7IWV5v72JhiqofK7XsiHmtgnvurnNOTdIvE5mrdWYtsOrQyrXCv1L2Ckm08hywp+MFO7rC4Ug==} openapi3-ts@4.4.0: resolution: {integrity: sha512-9asTNB9IkKEzWMcHmVZE7Ts3kC9G7AFHfs8i7caD8HbI76gEjdkId4z/AkP83xdZsH7PLAnnbl47qZkXuxpArw==} @@ -5639,6 +5518,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + peberminta@0.9.0: resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} @@ -5649,11 +5532,11 @@ packages: pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - pg-cloudflare@1.1.1: - resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} + pg-cloudflare@1.2.5: + resolution: {integrity: sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==} - pg-connection-string@2.7.0: - resolution: {integrity: sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==} + pg-connection-string@2.8.5: + resolution: {integrity: sha512-Ni8FuZ8yAF+sWZzojvtLE2b03cqjO5jNULcHFfM9ZZ0/JXrgom5pBREbtnAw7oxsxJqHw9Nz/XWORUEL3/IFow==} pg-int8@1.0.1: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} @@ -5663,13 +5546,13 @@ packages: resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} engines: {node: '>=4'} - pg-pool@3.8.0: - resolution: {integrity: sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==} + pg-pool@3.9.6: + resolution: {integrity: sha512-rFen0G7adh1YmgvrmE5IPIqbb+IgEzENUm+tzm6MLLDSlPRoZVhzU1WdML9PV2W5GOdRA9qBKURlbt1OsXOsPw==} peerDependencies: pg: '>=8.0' - pg-protocol@1.8.0: - resolution: {integrity: sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==} + pg-protocol@1.9.5: + resolution: {integrity: sha512-DYTWtWpfd5FOro3UnAfwvhD8jh59r2ig8bPtc9H8Ds7MscE/9NYruUQWFAOuraRl29jwcT2kyMFQ3MxeaVjUhg==} pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} @@ -5719,6 +5602,10 @@ packages: engines: {node: '>=18'} hasBin: true + plimit-lit@1.6.1: + resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==} + engines: {node: '>=12'} + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -5886,6 +5773,10 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + queue-lit@1.5.2: + resolution: {integrity: sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==} + engines: {node: '>=12'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -5903,8 +5794,8 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - react-hook-form@7.55.0: - resolution: {integrity: sha512-XRnjsH3GVMQz1moZTW53MxfoWN7aDpUg/GpVNc4A3eXRVNdGXfbzJ4vM4aLQ8g6XCUh1nIbx70aaNCl7kxnjog==} + react-hook-form@7.56.1: + resolution: {integrity: sha512-qWAVokhSpshhcEuQDSANHx3jiAEFzu2HAaaQIzi/r9FNPm1ioAvuJSD4EuZzWd7Al7nTRKcKPnBKO7sRn+zavQ==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -5979,6 +5870,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + readdirp@4.1.2: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} @@ -6037,8 +5932,8 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - resend@4.3.0: - resolution: {integrity: sha512-4OBHeusMVSl0vcba2J3AaGzdZ1SXAAhX/Wkcwobe16AHmlW9h3li8wG62Fhvlsc61e+wlQoxcwJZP6WrBTbghQ==} + resend@4.4.1: + resolution: {integrity: sha512-FR22bzMW3VfoyZSBc8ScGo8ShrMWHmWB0G3FrispzWCnYSEEK5M7pyRvZtInKmM/09lsJETKc2q66mX+dXPSmg==} engines: {node: '>=18'} resolve-alpn@1.2.1: @@ -6176,8 +6071,8 @@ packages: resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} engines: {node: '>= 0.4'} - shiki@3.2.2: - resolution: {integrity: sha512-0qWBkM2t/0NXPRcVgtLhtHv6Ak3Q5yI4K/ggMqcgLRKm4+pCs3namgZlhlat/7u2CuqNtlShNs9lENOG6n7UaQ==} + shiki@3.3.0: + resolution: {integrity: sha512-j0Z1tG5vlOFGW8JVj0Cpuatzvshes7VJy5ncDmmMaYcmnGW0Js1N81TOW98ivTFNZfKRn9uwEg/aIm638o368g==} side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} @@ -6421,8 +6316,8 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyglobby@0.2.12: - resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + tinyglobby@0.2.13: + resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} engines: {node: '>=12.0.0'} tmp@0.0.33: @@ -6459,6 +6354,11 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tsc-alias@1.8.15: + resolution: {integrity: sha512-yKLVx8ddUurRwhVcS6JFF2ZjksOX2ZWDRIdgt+PQhJBDegIdAdilptiHsuAbx9UFxa16GFrxeKQ2kTcGvR6fkQ==} + engines: {node: '>=16.20.2'} + hasBin: true + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -6486,42 +6386,42 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - turbo-darwin-64@2.5.0: - resolution: {integrity: sha512-fP1hhI9zY8hv0idym3hAaXdPi80TLovmGmgZFocVAykFtOxF+GlfIgM/l4iLAV9ObIO4SUXPVWHeBZQQ+Hpjag==} + turbo-darwin-64@2.5.2: + resolution: {integrity: sha512-2aIl0Sx230nLk+Cg2qSVxvPOBWCZpwKNuAMKoROTvWKif6VMpkWWiR9XEPoz7sHeLmCOed4GYGMjL1bqAiIS/g==} cpu: [x64] os: [darwin] - turbo-darwin-arm64@2.5.0: - resolution: {integrity: sha512-p9sYq7kXH7qeJwIQE86cOWv/xNqvow846l6c/qWc26Ib1ci5W7V0sI5thsrP3eH+VA0d+SHalTKg5SQXgNQBWA==} + turbo-darwin-arm64@2.5.2: + resolution: {integrity: sha512-MrFYhK/jYu8N6QlqZtqSHi3e4QVxlzqU3ANHTKn3/tThuwTLbNHEvzBPWSj5W7nZcM58dCqi6gYrfRz6bJZyAA==} cpu: [arm64] os: [darwin] - turbo-linux-64@2.5.0: - resolution: {integrity: sha512-1iEln2GWiF3iPPPS1HQJT6ZCFXynJPd89gs9SkggH2EJsj3eRUSVMmMC8y6d7bBbhBFsiGGazwFIYrI12zs6uQ==} + turbo-linux-64@2.5.2: + resolution: {integrity: sha512-LxNqUE2HmAJQ/8deoLgMUDzKxd5bKxqH0UBogWa+DF+JcXhtze3UTMr6lEr0dEofdsEUYK1zg8FRjglmwlN5YA==} cpu: [x64] os: [linux] - turbo-linux-arm64@2.5.0: - resolution: {integrity: sha512-bKBcbvuQHmsX116KcxHJuAcppiiBOfivOObh2O5aXNER6mce7YDDQJy00xQQNp1DhEfcSV2uOsvb3O3nN2cbcA==} + turbo-linux-arm64@2.5.2: + resolution: {integrity: sha512-0MI1Ao1q8zhd+UUbIEsrM+yLq1BsrcJQRGZkxIsHFlGp7WQQH1oR3laBgfnUCNdCotCMD6w4moc9pUbXdOR3bg==} cpu: [arm64] os: [linux] - turbo-windows-64@2.5.0: - resolution: {integrity: sha512-9BCo8oQ7BO7J0K913Czbc3tw8QwLqn2nTe4E47k6aVYkM12ASTScweXPTuaPFP5iYXAT6z5Dsniw704Ixa5eGg==} + turbo-windows-64@2.5.2: + resolution: {integrity: sha512-hOLcbgZzE5ttACHHyc1ajmWYq4zKT42IC3G6XqgiXxMbS+4eyVYTL+7UvCZBd3Kca1u4TLQdLQjeO76zyDJc2A==} cpu: [x64] os: [win32] - turbo-windows-arm64@2.5.0: - resolution: {integrity: sha512-OUHCV+ueXa3UzfZ4co/ueIHgeq9B2K48pZwIxKSm5VaLVuv8M13MhM7unukW09g++dpdrrE1w4IOVgxKZ0/exg==} + turbo-windows-arm64@2.5.2: + resolution: {integrity: sha512-fMU41ABhSLa18H8V3Z7BMCGynQ8x+wj9WyBMvWm1jeyRKgkvUYJsO2vkIsy8m0vrwnIeVXKOIn6eSe1ddlBVqw==} cpu: [arm64] os: [win32] - turbo@2.5.0: - resolution: {integrity: sha512-PvSRruOsitjy6qdqwIIyolv99+fEn57gP6gn4zhsHTEcCYgXPhv6BAxzAjleS8XKpo+Y582vTTA9nuqYDmbRuA==} + turbo@2.5.2: + resolution: {integrity: sha512-Qo5lfuStr6LQh3sPQl7kIi243bGU4aHGDQJUf6ylAdGwks30jJFloc9NYHP7Y373+gGU9OS0faA4Mb5Sy8X9Xw==} hasBin: true - tw-animate-css@1.2.5: - resolution: {integrity: sha512-ABzjfgVo+fDbhRREGL4KQZUqqdPgvc5zVrLyeW9/6mVqvaDepXc7EvedA+pYmMnIOsUAQMwcWzNvom26J2qYvQ==} + tw-animate-css@1.2.8: + resolution: {integrity: sha512-AxSnYRvyFnAiZCUndS3zQZhNfV/B77ZhJ+O7d3K6wfg/jKJY+yv6ahuyXwnyaYA9UdLqnpCwhTRv9pPTBnPR2g==} type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} @@ -6547,8 +6447,8 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typescript-eslint@8.30.1: - resolution: {integrity: sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==} + typescript-eslint@8.31.0: + resolution: {integrity: sha512-u+93F0sB0An8WEAPtwxVhFby573E8ckdjwUUQUj9QA4v8JAvgtoDdIyYR3XFwFHq2W1KJ1AurwJCO+w+Y1ixyQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -6620,8 +6520,8 @@ packages: '@types/react': optional: true - use-intl@4.0.2: - resolution: {integrity: sha512-6RAP/5KJMRzLMLS25/BVh2u09cRK8S6HRGc1RnZvqR547qAKZCpjYylOqMPU9eNIirAiKoGmsoUPa7JrlaA/yg==} + use-intl@4.1.0: + resolution: {integrity: sha512-mQvDYFvoGn+bm/PWvlQOtluKCknsQ5a9F1Cj0hMfBjMBVTwnOqLPd6srhjvVdEQEQFVyHM1PfyifKqKYb11M9Q==} peerDependencies: react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 @@ -6918,6 +6818,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + '@babel/template@7.27.0': dependencies: '@babel/code-frame': 7.26.2 @@ -7008,7 +6916,7 @@ snapshots: '@esbuild/aix-ppc64@0.25.0': optional: true - '@esbuild/aix-ppc64@0.25.2': + '@esbuild/aix-ppc64@0.25.3': optional: true '@esbuild/android-arm64@0.18.20': @@ -7023,7 +6931,7 @@ snapshots: '@esbuild/android-arm64@0.25.0': optional: true - '@esbuild/android-arm64@0.25.2': + '@esbuild/android-arm64@0.25.3': optional: true '@esbuild/android-arm@0.18.20': @@ -7038,7 +6946,7 @@ snapshots: '@esbuild/android-arm@0.25.0': optional: true - '@esbuild/android-arm@0.25.2': + '@esbuild/android-arm@0.25.3': optional: true '@esbuild/android-x64@0.18.20': @@ -7053,7 +6961,7 @@ snapshots: '@esbuild/android-x64@0.25.0': optional: true - '@esbuild/android-x64@0.25.2': + '@esbuild/android-x64@0.25.3': optional: true '@esbuild/darwin-arm64@0.18.20': @@ -7068,7 +6976,7 @@ snapshots: '@esbuild/darwin-arm64@0.25.0': optional: true - '@esbuild/darwin-arm64@0.25.2': + '@esbuild/darwin-arm64@0.25.3': optional: true '@esbuild/darwin-x64@0.18.20': @@ -7083,7 +6991,7 @@ snapshots: '@esbuild/darwin-x64@0.25.0': optional: true - '@esbuild/darwin-x64@0.25.2': + '@esbuild/darwin-x64@0.25.3': optional: true '@esbuild/freebsd-arm64@0.18.20': @@ -7098,7 +7006,7 @@ snapshots: '@esbuild/freebsd-arm64@0.25.0': optional: true - '@esbuild/freebsd-arm64@0.25.2': + '@esbuild/freebsd-arm64@0.25.3': optional: true '@esbuild/freebsd-x64@0.18.20': @@ -7113,7 +7021,7 @@ snapshots: '@esbuild/freebsd-x64@0.25.0': optional: true - '@esbuild/freebsd-x64@0.25.2': + '@esbuild/freebsd-x64@0.25.3': optional: true '@esbuild/linux-arm64@0.18.20': @@ -7128,7 +7036,7 @@ snapshots: '@esbuild/linux-arm64@0.25.0': optional: true - '@esbuild/linux-arm64@0.25.2': + '@esbuild/linux-arm64@0.25.3': optional: true '@esbuild/linux-arm@0.18.20': @@ -7143,7 +7051,7 @@ snapshots: '@esbuild/linux-arm@0.25.0': optional: true - '@esbuild/linux-arm@0.25.2': + '@esbuild/linux-arm@0.25.3': optional: true '@esbuild/linux-ia32@0.18.20': @@ -7158,7 +7066,7 @@ snapshots: '@esbuild/linux-ia32@0.25.0': optional: true - '@esbuild/linux-ia32@0.25.2': + '@esbuild/linux-ia32@0.25.3': optional: true '@esbuild/linux-loong64@0.18.20': @@ -7173,7 +7081,7 @@ snapshots: '@esbuild/linux-loong64@0.25.0': optional: true - '@esbuild/linux-loong64@0.25.2': + '@esbuild/linux-loong64@0.25.3': optional: true '@esbuild/linux-mips64el@0.18.20': @@ -7188,7 +7096,7 @@ snapshots: '@esbuild/linux-mips64el@0.25.0': optional: true - '@esbuild/linux-mips64el@0.25.2': + '@esbuild/linux-mips64el@0.25.3': optional: true '@esbuild/linux-ppc64@0.18.20': @@ -7203,7 +7111,7 @@ snapshots: '@esbuild/linux-ppc64@0.25.0': optional: true - '@esbuild/linux-ppc64@0.25.2': + '@esbuild/linux-ppc64@0.25.3': optional: true '@esbuild/linux-riscv64@0.18.20': @@ -7218,7 +7126,7 @@ snapshots: '@esbuild/linux-riscv64@0.25.0': optional: true - '@esbuild/linux-riscv64@0.25.2': + '@esbuild/linux-riscv64@0.25.3': optional: true '@esbuild/linux-s390x@0.18.20': @@ -7233,7 +7141,7 @@ snapshots: '@esbuild/linux-s390x@0.25.0': optional: true - '@esbuild/linux-s390x@0.25.2': + '@esbuild/linux-s390x@0.25.3': optional: true '@esbuild/linux-x64@0.18.20': @@ -7248,7 +7156,7 @@ snapshots: '@esbuild/linux-x64@0.25.0': optional: true - '@esbuild/linux-x64@0.25.2': + '@esbuild/linux-x64@0.25.3': optional: true '@esbuild/netbsd-arm64@0.24.2': @@ -7257,7 +7165,7 @@ snapshots: '@esbuild/netbsd-arm64@0.25.0': optional: true - '@esbuild/netbsd-arm64@0.25.2': + '@esbuild/netbsd-arm64@0.25.3': optional: true '@esbuild/netbsd-x64@0.18.20': @@ -7272,7 +7180,7 @@ snapshots: '@esbuild/netbsd-x64@0.25.0': optional: true - '@esbuild/netbsd-x64@0.25.2': + '@esbuild/netbsd-x64@0.25.3': optional: true '@esbuild/openbsd-arm64@0.24.2': @@ -7281,7 +7189,7 @@ snapshots: '@esbuild/openbsd-arm64@0.25.0': optional: true - '@esbuild/openbsd-arm64@0.25.2': + '@esbuild/openbsd-arm64@0.25.3': optional: true '@esbuild/openbsd-x64@0.18.20': @@ -7296,7 +7204,7 @@ snapshots: '@esbuild/openbsd-x64@0.25.0': optional: true - '@esbuild/openbsd-x64@0.25.2': + '@esbuild/openbsd-x64@0.25.3': optional: true '@esbuild/sunos-x64@0.18.20': @@ -7311,7 +7219,7 @@ snapshots: '@esbuild/sunos-x64@0.25.0': optional: true - '@esbuild/sunos-x64@0.25.2': + '@esbuild/sunos-x64@0.25.3': optional: true '@esbuild/win32-arm64@0.18.20': @@ -7326,7 +7234,7 @@ snapshots: '@esbuild/win32-arm64@0.25.0': optional: true - '@esbuild/win32-arm64@0.25.2': + '@esbuild/win32-arm64@0.25.3': optional: true '@esbuild/win32-ia32@0.18.20': @@ -7341,7 +7249,7 @@ snapshots: '@esbuild/win32-ia32@0.25.0': optional: true - '@esbuild/win32-ia32@0.25.2': + '@esbuild/win32-ia32@0.25.3': optional: true '@esbuild/win32-x64@0.18.20': @@ -7356,17 +7264,12 @@ snapshots: '@esbuild/win32-x64@0.25.0': optional: true - '@esbuild/win32-x64@0.25.2': + '@esbuild/win32-x64@0.25.3': optional: true - '@eslint-community/eslint-utils@4.6.1(eslint@9.24.0(jiti@2.4.2))': + '@eslint-community/eslint-utils@4.6.1(eslint@9.25.1(jiti@2.4.2))': dependencies: - eslint: 9.24.0(jiti@2.4.2) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/eslint-utils@4.6.1(eslint@9.25.0(jiti@2.4.2))': - dependencies: - eslint: 9.25.0(jiti@2.4.2) + eslint: 9.25.1(jiti@2.4.2) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -7381,10 +7284,6 @@ snapshots: '@eslint/config-helpers@0.2.1': {} - '@eslint/core@0.12.0': - dependencies: - '@types/json-schema': 7.0.15 - '@eslint/core@0.13.0': dependencies: '@types/json-schema': 7.0.15 @@ -7403,9 +7302,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.24.0': {} - - '@eslint/js@9.25.0': {} + '@eslint/js@9.25.1': {} '@eslint/object-schema@2.1.6': {} @@ -7461,10 +7358,10 @@ snapshots: dependencies: tslib: 2.8.1 - '@fumadocs/mdx-remote@1.3.0(acorn@8.14.1)(fumadocs-core@15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)': + '@fumadocs/mdx-remote@1.3.0(acorn@8.14.1)(fumadocs-core@15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)': dependencies: '@mdx-js/mdx': 3.1.0(acorn@8.14.1) - fumadocs-core: 15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + fumadocs-core: 15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) gray-matter: 4.0.3 react: 19.1.0 zod: 3.24.3 @@ -7477,13 +7374,6 @@ snapshots: dependencies: hono: 4.7.7 - '@hono/zod-openapi@0.19.5(hono@4.7.6)(zod@3.24.3)': - dependencies: - '@asteasolutions/zod-to-openapi': 7.3.0(zod@3.24.3) - '@hono/zod-validator': 0.4.3(hono@4.7.6)(zod@3.24.3) - hono: 4.7.6 - zod: 3.24.3 - '@hono/zod-openapi@0.19.5(hono@4.7.7)(zod@3.24.3)': dependencies: '@asteasolutions/zod-to-openapi': 7.3.0(zod@3.24.3) @@ -7491,20 +7381,15 @@ snapshots: hono: 4.7.7 zod: 3.24.3 - '@hono/zod-validator@0.4.3(hono@4.7.6)(zod@3.24.3)': - dependencies: - hono: 4.7.6 - zod: 3.24.3 - '@hono/zod-validator@0.4.3(hono@4.7.7)(zod@3.24.3)': dependencies: hono: 4.7.7 zod: 3.24.3 - '@hookform/resolvers@5.0.1(react-hook-form@7.55.0(react@19.1.0))': + '@hookform/resolvers@5.0.1(react-hook-form@7.56.1(react@19.1.0))': dependencies: '@standard-schema/utils': 0.3.0 - react-hook-form: 7.55.0(react@19.1.0) + react-hook-form: 7.56.1(react@19.1.0) '@humanfs/core@0.19.1': {} @@ -7672,27 +7557,27 @@ snapshots: '@img/sharp-win32-x64@0.34.1': optional: true - '@inquirer/checkbox@4.1.5(@types/node@22.14.1)': + '@inquirer/checkbox@4.1.5(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/type': 3.0.6(@types/node@22.15.2) ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/confirm@5.1.9(@types/node@22.14.1)': + '@inquirer/confirm@5.1.9(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) + '@inquirer/type': 3.0.6(@types/node@22.15.2) optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/core@10.1.10(@types/node@22.14.1)': + '@inquirer/core@10.1.10(@types/node@22.15.2)': dependencies: '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/type': 3.0.6(@types/node@22.15.2) ansi-escapes: 4.3.2 cli-width: 4.1.0 mute-stream: 2.0.0 @@ -7700,93 +7585,93 @@ snapshots: wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/editor@4.2.10(@types/node@22.14.1)': + '@inquirer/editor@4.2.10(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) + '@inquirer/type': 3.0.6(@types/node@22.15.2) external-editor: 3.1.0 optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/expand@4.0.12(@types/node@22.14.1)': + '@inquirer/expand@4.0.12(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) + '@inquirer/type': 3.0.6(@types/node@22.15.2) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 '@inquirer/figures@1.0.11': {} - '@inquirer/input@4.1.9(@types/node@22.14.1)': + '@inquirer/input@4.1.9(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) + '@inquirer/type': 3.0.6(@types/node@22.15.2) optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/number@3.0.12(@types/node@22.14.1)': + '@inquirer/number@3.0.12(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) + '@inquirer/type': 3.0.6(@types/node@22.15.2) optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/password@4.0.12(@types/node@22.14.1)': + '@inquirer/password@4.0.12(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) + '@inquirer/type': 3.0.6(@types/node@22.15.2) ansi-escapes: 4.3.2 optionalDependencies: - '@types/node': 22.14.1 - - '@inquirer/prompts@7.4.1(@types/node@22.14.1)': - dependencies: - '@inquirer/checkbox': 4.1.5(@types/node@22.14.1) - '@inquirer/confirm': 5.1.9(@types/node@22.14.1) - '@inquirer/editor': 4.2.10(@types/node@22.14.1) - '@inquirer/expand': 4.0.12(@types/node@22.14.1) - '@inquirer/input': 4.1.9(@types/node@22.14.1) - '@inquirer/number': 3.0.12(@types/node@22.14.1) - '@inquirer/password': 4.0.12(@types/node@22.14.1) - '@inquirer/rawlist': 4.0.12(@types/node@22.14.1) - '@inquirer/search': 3.0.12(@types/node@22.14.1) - '@inquirer/select': 4.1.1(@types/node@22.14.1) + '@types/node': 22.15.2 + + '@inquirer/prompts@7.5.0(@types/node@22.15.2)': + dependencies: + '@inquirer/checkbox': 4.1.5(@types/node@22.15.2) + '@inquirer/confirm': 5.1.9(@types/node@22.15.2) + '@inquirer/editor': 4.2.10(@types/node@22.15.2) + '@inquirer/expand': 4.0.12(@types/node@22.15.2) + '@inquirer/input': 4.1.9(@types/node@22.15.2) + '@inquirer/number': 3.0.12(@types/node@22.15.2) + '@inquirer/password': 4.0.12(@types/node@22.15.2) + '@inquirer/rawlist': 4.1.0(@types/node@22.15.2) + '@inquirer/search': 3.0.12(@types/node@22.15.2) + '@inquirer/select': 4.2.0(@types/node@22.15.2) optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/rawlist@4.0.12(@types/node@22.14.1)': + '@inquirer/rawlist@4.1.0(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) + '@inquirer/type': 3.0.6(@types/node@22.15.2) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/search@3.0.12(@types/node@22.14.1)': + '@inquirer/search@3.0.12(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/type': 3.0.6(@types/node@22.15.2) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/select@4.1.1(@types/node@22.14.1)': + '@inquirer/select@4.2.0(@types/node@22.15.2)': dependencies: - '@inquirer/core': 10.1.10(@types/node@22.14.1) + '@inquirer/core': 10.1.10(@types/node@22.15.2) '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.6(@types/node@22.14.1) + '@inquirer/type': 3.0.6(@types/node@22.15.2) ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 - '@inquirer/type@3.0.6(@types/node@22.14.1)': + '@inquirer/type@3.0.6(@types/node@22.15.2)': optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 '@isaacs/cliui@8.0.2': dependencies: @@ -7923,79 +7808,53 @@ snapshots: '@next/env@15.2.4': {} - '@next/env@15.3.0': {} - '@next/env@15.3.1': {} '@next/swc-darwin-arm64@15.2.4': optional: true - '@next/swc-darwin-arm64@15.3.0': - optional: true - '@next/swc-darwin-arm64@15.3.1': optional: true '@next/swc-darwin-x64@15.2.4': optional: true - '@next/swc-darwin-x64@15.3.0': - optional: true - '@next/swc-darwin-x64@15.3.1': optional: true '@next/swc-linux-arm64-gnu@15.2.4': optional: true - '@next/swc-linux-arm64-gnu@15.3.0': - optional: true - '@next/swc-linux-arm64-gnu@15.3.1': optional: true '@next/swc-linux-arm64-musl@15.2.4': optional: true - '@next/swc-linux-arm64-musl@15.3.0': - optional: true - '@next/swc-linux-arm64-musl@15.3.1': optional: true '@next/swc-linux-x64-gnu@15.2.4': optional: true - '@next/swc-linux-x64-gnu@15.3.0': - optional: true - '@next/swc-linux-x64-gnu@15.3.1': optional: true '@next/swc-linux-x64-musl@15.2.4': optional: true - '@next/swc-linux-x64-musl@15.3.0': - optional: true - '@next/swc-linux-x64-musl@15.3.1': optional: true '@next/swc-win32-arm64-msvc@15.2.4': optional: true - '@next/swc-win32-arm64-msvc@15.3.0': - optional: true - '@next/swc-win32-arm64-msvc@15.3.1': optional: true '@next/swc-win32-x64-msvc@15.2.4': optional: true - '@next/swc-win32-x64-msvc@15.3.0': - optional: true - '@next/swc-win32-x64-msvc@15.3.1': optional: true @@ -8039,10 +7898,10 @@ snapshots: '@radix-ui/primitive@1.1.2': {} - '@radix-ui/react-accordion@1.2.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-accordion@1.2.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collapsible': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-collapsible': 1.1.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-collection': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) @@ -8056,12 +7915,12 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-alert-dialog@1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-alert-dialog@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-dialog': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-dialog': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-slot': 1.2.0(@types/react@19.1.2)(react@19.1.0) react: 19.1.0 @@ -8079,12 +7938,12 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-checkbox@1.2.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-checkbox@1.2.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.2)(react@19.1.0) @@ -8095,13 +7954,13 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-collapsible@1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-collapsible@1.1.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.2)(react@19.1.0) @@ -8129,11 +7988,11 @@ snapshots: optionalDependencies: '@types/react': 19.1.2 - '@radix-ui/react-context-menu@2.2.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-context-menu@2.2.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-menu': 2.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-menu': 2.1.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) @@ -8149,7 +8008,7 @@ snapshots: optionalDependencies: '@types/react': 19.1.2 - '@radix-ui/react-dialog@1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-dialog@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) @@ -8159,7 +8018,7 @@ snapshots: '@radix-ui/react-focus-scope': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-portal': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-slot': 1.2.0(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) @@ -8190,13 +8049,13 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-dropdown-menu@2.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-dropdown-menu@2.1.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-menu': 2.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-menu': 2.1.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) react: 19.1.0 @@ -8222,7 +8081,7 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-hover-card@1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-hover-card@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) @@ -8230,7 +8089,7 @@ snapshots: '@radix-ui/react-dismissable-layer': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-popper': 1.2.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-portal': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) react: 19.1.0 @@ -8255,7 +8114,7 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-menu@2.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-menu@2.1.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-collection': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -8268,9 +8127,9 @@ snapshots: '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-popper': 1.2.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-portal': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-roving-focus': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-slot': 1.2.0(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.2)(react@19.1.0) aria-hidden: 1.2.4 @@ -8281,7 +8140,7 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-menubar@1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-menubar@1.1.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-collection': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -8289,9 +8148,9 @@ snapshots: '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-menu': 2.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-menu': 2.1.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-roving-focus': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -8299,7 +8158,7 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-navigation-menu@1.2.9(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-navigation-menu@1.2.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-collection': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -8308,7 +8167,7 @@ snapshots: '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-dismissable-layer': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) @@ -8321,7 +8180,7 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-popover@1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-popover@1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) @@ -8332,7 +8191,7 @@ snapshots: '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-popper': 1.2.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-portal': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-slot': 1.2.0(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) @@ -8372,7 +8231,7 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-presence@1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-presence@1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.2)(react@19.1.0) @@ -8401,15 +8260,15 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-radio-group@1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-radio-group@1.3.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-roving-focus': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.2)(react@19.1.0) @@ -8419,7 +8278,7 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-roving-focus@1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-roving-focus@1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-collection': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -8436,14 +8295,14 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-scroll-area@1.2.5(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-scroll-area@1.2.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.2)(react@19.1.0) @@ -8532,15 +8391,15 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-tabs@1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-tabs@1.1.9(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-roving-focus': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -8548,13 +8407,13 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-toggle-group@1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-toggle-group@1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-roving-focus': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-toggle': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) react: 19.1.0 @@ -8574,7 +8433,7 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) - '@radix-ui/react-tooltip@1.2.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-tooltip@1.2.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) @@ -8583,7 +8442,7 @@ snapshots: '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-popper': 1.2.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-portal': 1.1.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-slot': 1.2.0(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) @@ -8848,47 +8707,47 @@ snapshots: domhandler: 5.0.3 selderee: 0.11.0 - '@shikijs/core@3.2.2': + '@shikijs/core@3.3.0': dependencies: - '@shikijs/types': 3.2.2 + '@shikijs/types': 3.3.0 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 hast-util-to-html: 9.0.5 - '@shikijs/engine-javascript@3.2.2': + '@shikijs/engine-javascript@3.3.0': dependencies: - '@shikijs/types': 3.2.2 + '@shikijs/types': 3.3.0 '@shikijs/vscode-textmate': 10.0.2 - oniguruma-to-es: 4.2.0 + oniguruma-to-es: 4.3.1 - '@shikijs/engine-oniguruma@3.2.2': + '@shikijs/engine-oniguruma@3.3.0': dependencies: - '@shikijs/types': 3.2.2 + '@shikijs/types': 3.3.0 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@3.2.2': + '@shikijs/langs@3.3.0': dependencies: - '@shikijs/types': 3.2.2 + '@shikijs/types': 3.3.0 - '@shikijs/rehype@3.2.2': + '@shikijs/rehype@3.3.0': dependencies: - '@shikijs/types': 3.2.2 + '@shikijs/types': 3.3.0 '@types/hast': 3.0.4 hast-util-to-string: 3.0.1 - shiki: 3.2.2 + shiki: 3.3.0 unified: 11.0.5 unist-util-visit: 5.0.0 - '@shikijs/themes@3.2.2': + '@shikijs/themes@3.3.0': dependencies: - '@shikijs/types': 3.2.2 + '@shikijs/types': 3.3.0 - '@shikijs/transformers@3.2.2': + '@shikijs/transformers@3.3.0': dependencies: - '@shikijs/core': 3.2.2 - '@shikijs/types': 3.2.2 + '@shikijs/core': 3.3.0 + '@shikijs/types': 3.3.0 - '@shikijs/types@3.2.2': + '@shikijs/types@3.3.0': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 @@ -8903,24 +8762,9 @@ snapshots: '@standard-schema/utils@0.3.0': {} - '@swc/cli@0.6.0(@swc/core@1.11.20)(chokidar@4.0.3)': - dependencies: - '@swc/core': 1.11.20 - '@swc/counter': 0.1.3 - '@xhmikosr/bin-wrapper': 13.0.5 - commander: 8.3.0 - fast-glob: 3.3.3 - minimatch: 9.0.5 - piscina: 4.9.2 - semver: 7.7.1 - slash: 3.0.0 - source-map: 0.7.4 - optionalDependencies: - chokidar: 4.0.3 - - '@swc/cli@0.6.0(@swc/core@1.11.21)(chokidar@4.0.3)': + '@swc/cli@0.6.0(@swc/core@1.11.22)(chokidar@4.0.3)': dependencies: - '@swc/core': 1.11.21 + '@swc/core': 1.11.22 '@swc/counter': 0.1.3 '@xhmikosr/bin-wrapper': 13.0.5 commander: 8.3.0 @@ -8933,97 +8777,51 @@ snapshots: optionalDependencies: chokidar: 4.0.3 - '@swc/core-darwin-arm64@1.11.20': + '@swc/core-darwin-arm64@1.11.22': optional: true - '@swc/core-darwin-arm64@1.11.21': + '@swc/core-darwin-x64@1.11.22': optional: true - '@swc/core-darwin-x64@1.11.20': + '@swc/core-linux-arm-gnueabihf@1.11.22': optional: true - '@swc/core-darwin-x64@1.11.21': + '@swc/core-linux-arm64-gnu@1.11.22': optional: true - '@swc/core-linux-arm-gnueabihf@1.11.20': + '@swc/core-linux-arm64-musl@1.11.22': optional: true - '@swc/core-linux-arm-gnueabihf@1.11.21': + '@swc/core-linux-x64-gnu@1.11.22': optional: true - '@swc/core-linux-arm64-gnu@1.11.20': + '@swc/core-linux-x64-musl@1.11.22': optional: true - '@swc/core-linux-arm64-gnu@1.11.21': + '@swc/core-win32-arm64-msvc@1.11.22': optional: true - '@swc/core-linux-arm64-musl@1.11.20': + '@swc/core-win32-ia32-msvc@1.11.22': optional: true - '@swc/core-linux-arm64-musl@1.11.21': + '@swc/core-win32-x64-msvc@1.11.22': optional: true - '@swc/core-linux-x64-gnu@1.11.20': - optional: true - - '@swc/core-linux-x64-gnu@1.11.21': - optional: true - - '@swc/core-linux-x64-musl@1.11.20': - optional: true - - '@swc/core-linux-x64-musl@1.11.21': - optional: true - - '@swc/core-win32-arm64-msvc@1.11.20': - optional: true - - '@swc/core-win32-arm64-msvc@1.11.21': - optional: true - - '@swc/core-win32-ia32-msvc@1.11.20': - optional: true - - '@swc/core-win32-ia32-msvc@1.11.21': - optional: true - - '@swc/core-win32-x64-msvc@1.11.20': - optional: true - - '@swc/core-win32-x64-msvc@1.11.21': - optional: true - - '@swc/core@1.11.20': - dependencies: - '@swc/counter': 0.1.3 - '@swc/types': 0.1.21 - optionalDependencies: - '@swc/core-darwin-arm64': 1.11.20 - '@swc/core-darwin-x64': 1.11.20 - '@swc/core-linux-arm-gnueabihf': 1.11.20 - '@swc/core-linux-arm64-gnu': 1.11.20 - '@swc/core-linux-arm64-musl': 1.11.20 - '@swc/core-linux-x64-gnu': 1.11.20 - '@swc/core-linux-x64-musl': 1.11.20 - '@swc/core-win32-arm64-msvc': 1.11.20 - '@swc/core-win32-ia32-msvc': 1.11.20 - '@swc/core-win32-x64-msvc': 1.11.20 - - '@swc/core@1.11.21': + '@swc/core@1.11.22': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.21 optionalDependencies: - '@swc/core-darwin-arm64': 1.11.21 - '@swc/core-darwin-x64': 1.11.21 - '@swc/core-linux-arm-gnueabihf': 1.11.21 - '@swc/core-linux-arm64-gnu': 1.11.21 - '@swc/core-linux-arm64-musl': 1.11.21 - '@swc/core-linux-x64-gnu': 1.11.21 - '@swc/core-linux-x64-musl': 1.11.21 - '@swc/core-win32-arm64-msvc': 1.11.21 - '@swc/core-win32-ia32-msvc': 1.11.21 - '@swc/core-win32-x64-msvc': 1.11.21 + '@swc/core-darwin-arm64': 1.11.22 + '@swc/core-darwin-x64': 1.11.22 + '@swc/core-linux-arm-gnueabihf': 1.11.22 + '@swc/core-linux-arm64-gnu': 1.11.22 + '@swc/core-linux-arm64-musl': 1.11.22 + '@swc/core-linux-x64-gnu': 1.11.22 + '@swc/core-linux-x64-musl': 1.11.22 + '@swc/core-win32-arm64-msvc': 1.11.22 + '@swc/core-win32-ia32-msvc': 1.11.22 + '@swc/core-win32-x64-msvc': 1.11.22 '@swc/counter@0.1.3': {} @@ -9116,7 +8914,7 @@ snapshots: '@types/cors@2.8.17': dependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 '@types/debug@4.1.12': dependencies: @@ -9150,35 +8948,35 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@20.17.30': + '@types/node@20.17.31': dependencies: undici-types: 6.19.8 - '@types/node@22.14.1': + '@types/node@22.15.2': dependencies: undici-types: 6.21.0 '@types/nodemailer@6.4.17': dependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 '@types/pg@8.11.10': dependencies: - '@types/node': 22.14.1 - pg-protocol: 1.8.0 + '@types/node': 22.15.2 + pg-protocol: 1.9.5 pg-types: 4.0.2 optional: true '@types/pg@8.11.6': dependencies: - '@types/node': 22.14.1 - pg-protocol: 1.8.0 + '@types/node': 22.15.2 + pg-protocol: 1.9.5 pg-types: 4.0.2 optional: true '@types/prompts@2.4.9': dependencies: - '@types/node': 22.14.1 + '@types/node': 22.15.2 kleur: 3.0.3 '@types/react-dom@19.1.2(@types/react@19.1.2)': @@ -9197,15 +8995,15 @@ snapshots: '@types/unist@3.0.3': {} - '@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.31.0(@typescript-eslint/parser@8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.30.1 - '@typescript-eslint/type-utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.30.1 - eslint: 9.25.0(jiti@2.4.2) + '@typescript-eslint/parser': 8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.31.0 + '@typescript-eslint/type-utils': 8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.31.0 + eslint: 9.25.1(jiti@2.4.2) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -9214,40 +9012,40 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3)': + '@typescript-eslint/parser@8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)': dependencies: - '@typescript-eslint/scope-manager': 8.30.1 - '@typescript-eslint/types': 8.30.1 - '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.30.1 + '@typescript-eslint/scope-manager': 8.31.0 + '@typescript-eslint/types': 8.31.0 + '@typescript-eslint/typescript-estree': 8.31.0(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.31.0 debug: 4.4.0 - eslint: 9.25.0(jiti@2.4.2) + eslint: 9.25.1(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.30.1': + '@typescript-eslint/scope-manager@8.31.0': dependencies: - '@typescript-eslint/types': 8.30.1 - '@typescript-eslint/visitor-keys': 8.30.1 + '@typescript-eslint/types': 8.31.0 + '@typescript-eslint/visitor-keys': 8.31.0 - '@typescript-eslint/type-utils@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3)': + '@typescript-eslint/type-utils@8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) - '@typescript-eslint/utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.31.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) debug: 4.4.0 - eslint: 9.25.0(jiti@2.4.2) + eslint: 9.25.1(jiti@2.4.2) ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.30.1': {} + '@typescript-eslint/types@8.31.0': {} - '@typescript-eslint/typescript-estree@8.30.1(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.31.0(typescript@5.8.3)': dependencies: - '@typescript-eslint/types': 8.30.1 - '@typescript-eslint/visitor-keys': 8.30.1 + '@typescript-eslint/types': 8.31.0 + '@typescript-eslint/visitor-keys': 8.31.0 debug: 4.4.0 fast-glob: 3.3.3 is-glob: 4.0.3 @@ -9258,20 +9056,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3)': + '@typescript-eslint/utils@8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.0(jiti@2.4.2)) - '@typescript-eslint/scope-manager': 8.30.1 - '@typescript-eslint/types': 8.30.1 - '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) - eslint: 9.25.0(jiti@2.4.2) + '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.1(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.31.0 + '@typescript-eslint/types': 8.31.0 + '@typescript-eslint/typescript-estree': 8.31.0(typescript@5.8.3) + eslint: 9.25.1(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.30.1': + '@typescript-eslint/visitor-keys@8.31.0': dependencies: - '@typescript-eslint/types': 8.30.1 + '@typescript-eslint/types': 8.31.0 eslint-visitor-keys: 4.2.0 '@ungap/structured-clone@1.3.0': {} @@ -9378,6 +9176,11 @@ snapshots: any-promise@1.3.0: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + arch@3.0.0: {} argparse@1.0.10: @@ -9406,6 +9209,8 @@ snapshots: get-intrinsic: 1.3.0 is-string: 1.1.1 + array-union@2.1.0: {} + array.prototype.findlast@1.2.5: dependencies: call-bind: 1.0.8 @@ -9463,7 +9268,7 @@ snapshots: b4a@1.6.7: {} - babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411: + babel-plugin-react-compiler@19.1.0-rc.1: dependencies: '@babel/types': 7.27.0 @@ -9489,6 +9294,8 @@ snapshots: execa: 5.1.1 find-versions: 5.1.0 + binary-extensions@2.3.0: {} + bippy@0.3.9(@types/react@19.1.2)(react@19.1.0): dependencies: '@types/react-reconciler': 0.28.9(@types/react@19.1.2) @@ -9517,8 +9324,8 @@ snapshots: browserslist@4.24.4: dependencies: - caniuse-lite: 1.0.30001714 - electron-to-chromium: 1.5.139 + caniuse-lite: 1.0.30001715 + electron-to-chromium: 1.5.142 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.4) @@ -9536,9 +9343,9 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - bundle-require@5.1.0(esbuild@0.25.2): + bundle-require@5.1.0(esbuild@0.25.3): dependencies: - esbuild: 0.25.2 + esbuild: 0.25.3 load-tsconfig: 0.2.5 busboy@1.6.0: @@ -9549,7 +9356,7 @@ snapshots: cache-manager@6.4.2: dependencies: - keyv: 5.3.2 + keyv: 5.3.3 cacheable-lookup@7.0.0: {} @@ -9582,9 +9389,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001712: {} - - caniuse-lite@1.0.30001714: {} + caniuse-lite@1.0.30001715: {} ccount@2.0.1: {} @@ -9605,6 +9410,18 @@ snapshots: chardet@0.7.0: {} + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + chokidar@4.0.3: dependencies: readdirp: 4.1.2 @@ -9640,7 +9457,7 @@ snapshots: cmdk@1.1.1(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-dialog': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-dialog': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 @@ -9681,6 +9498,8 @@ snapshots: commander@8.3.0: {} + commander@9.5.0: {} + compute-scroll-into-view@3.1.1: {} concat-map@0.0.1: {} @@ -9786,7 +9605,7 @@ snapshots: dequal@2.0.3: {} - detect-libc@2.0.3: {} + detect-libc@2.0.4: {} detect-node-es@1.1.0: {} @@ -9794,6 +9613,10 @@ snapshots: dependencies: dequal: 2.0.3 + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -9832,8 +9655,8 @@ snapshots: dependencies: '@drizzle-team/brocli': 0.10.2 '@esbuild-kit/esm-loader': 2.6.5 - esbuild: 0.25.2 - esbuild-register: 3.6.0(esbuild@0.25.2) + esbuild: 0.25.3 + esbuild-register: 3.6.0(esbuild@0.25.3) transitivePeerDependencies: - supports-color @@ -9861,9 +9684,7 @@ snapshots: eastasianwidth@0.2.0: {} - electron-to-chromium@1.5.139: {} - - emoji-regex-xs@1.0.0: {} + electron-to-chromium@1.5.142: {} emoji-regex@10.4.0: {} @@ -9876,7 +9697,7 @@ snapshots: engine.io@6.6.4: dependencies: '@types/cors': 2.8.17 - '@types/node': 22.14.1 + '@types/node': 22.15.2 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -10017,10 +9838,10 @@ snapshots: transitivePeerDependencies: - supports-color - esbuild-register@3.6.0(esbuild@0.25.2): + esbuild-register@3.6.0(esbuild@0.25.3): dependencies: debug: 4.4.0 - esbuild: 0.25.2 + esbuild: 0.25.3 transitivePeerDependencies: - supports-color @@ -10131,33 +9952,33 @@ snapshots: '@esbuild/win32-ia32': 0.25.0 '@esbuild/win32-x64': 0.25.0 - esbuild@0.25.2: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.2 - '@esbuild/android-arm': 0.25.2 - '@esbuild/android-arm64': 0.25.2 - '@esbuild/android-x64': 0.25.2 - '@esbuild/darwin-arm64': 0.25.2 - '@esbuild/darwin-x64': 0.25.2 - '@esbuild/freebsd-arm64': 0.25.2 - '@esbuild/freebsd-x64': 0.25.2 - '@esbuild/linux-arm': 0.25.2 - '@esbuild/linux-arm64': 0.25.2 - '@esbuild/linux-ia32': 0.25.2 - '@esbuild/linux-loong64': 0.25.2 - '@esbuild/linux-mips64el': 0.25.2 - '@esbuild/linux-ppc64': 0.25.2 - '@esbuild/linux-riscv64': 0.25.2 - '@esbuild/linux-s390x': 0.25.2 - '@esbuild/linux-x64': 0.25.2 - '@esbuild/netbsd-arm64': 0.25.2 - '@esbuild/netbsd-x64': 0.25.2 - '@esbuild/openbsd-arm64': 0.25.2 - '@esbuild/openbsd-x64': 0.25.2 - '@esbuild/sunos-x64': 0.25.2 - '@esbuild/win32-arm64': 0.25.2 - '@esbuild/win32-ia32': 0.25.2 - '@esbuild/win32-x64': 0.25.2 + esbuild@0.25.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.3 + '@esbuild/android-arm': 0.25.3 + '@esbuild/android-arm64': 0.25.3 + '@esbuild/android-x64': 0.25.3 + '@esbuild/darwin-arm64': 0.25.3 + '@esbuild/darwin-x64': 0.25.3 + '@esbuild/freebsd-arm64': 0.25.3 + '@esbuild/freebsd-x64': 0.25.3 + '@esbuild/linux-arm': 0.25.3 + '@esbuild/linux-arm64': 0.25.3 + '@esbuild/linux-ia32': 0.25.3 + '@esbuild/linux-loong64': 0.25.3 + '@esbuild/linux-mips64el': 0.25.3 + '@esbuild/linux-ppc64': 0.25.3 + '@esbuild/linux-riscv64': 0.25.3 + '@esbuild/linux-s390x': 0.25.3 + '@esbuild/linux-x64': 0.25.3 + '@esbuild/netbsd-arm64': 0.25.3 + '@esbuild/netbsd-x64': 0.25.3 + '@esbuild/openbsd-arm64': 0.25.3 + '@esbuild/openbsd-x64': 0.25.3 + '@esbuild/sunos-x64': 0.25.3 + '@esbuild/win32-arm64': 0.25.3 + '@esbuild/win32-ia32': 0.25.3 + '@esbuild/win32-x64': 0.25.3 escalade@3.2.0: {} @@ -10165,11 +9986,11 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-prettier@10.1.2(eslint@9.25.0(jiti@2.4.2)): + eslint-config-prettier@10.1.2(eslint@9.25.1(jiti@2.4.2)): dependencies: - eslint: 9.25.0(jiti@2.4.2) + eslint: 9.25.1(jiti@2.4.2) - eslint-plugin-jsx-a11y@6.10.2(eslint@9.25.0(jiti@2.4.2)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.25.1(jiti@2.4.2)): dependencies: aria-query: 5.3.2 array-includes: 3.1.8 @@ -10179,7 +10000,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.25.0(jiti@2.4.2) + eslint: 9.25.1(jiti@2.4.2) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -10188,43 +10009,51 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-perfectionist@4.11.0(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3): + eslint-plugin-perfectionist@4.12.3(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3): dependencies: - '@typescript-eslint/types': 8.30.1 - '@typescript-eslint/utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) - eslint: 9.25.0(jiti@2.4.2) + '@typescript-eslint/types': 8.31.0 + '@typescript-eslint/utils': 8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) + eslint: 9.25.1(jiti@2.4.2) natural-orderby: 5.0.0 transitivePeerDependencies: - supports-color - typescript - eslint-plugin-prettier@5.2.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.2(eslint@9.25.0(jiti@2.4.2)))(eslint@9.25.0(jiti@2.4.2))(prettier@3.5.3): + eslint-plugin-prettier@5.2.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.2(eslint@9.25.1(jiti@2.4.2)))(eslint@9.25.1(jiti@2.4.2))(prettier@3.5.3): dependencies: - eslint: 9.25.0(jiti@2.4.2) + eslint: 9.25.1(jiti@2.4.2) prettier: 3.5.3 prettier-linter-helpers: 1.0.0 synckit: 0.11.4 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.2(eslint@9.25.0(jiti@2.4.2)) + eslint-config-prettier: 10.1.2(eslint@9.25.1(jiti@2.4.2)) - eslint-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411(eslint@9.25.0(jiti@2.4.2)): + eslint-plugin-react-compiler@19.1.0-rc.1(eslint@9.25.1(jiti@2.4.2)): dependencies: '@babel/core': 7.26.10 '@babel/parser': 7.27.0 '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.26.10) - eslint: 9.25.0(jiti@2.4.2) + eslint: 9.25.1(jiti@2.4.2) hermes-parser: 0.25.1 zod: 3.24.3 zod-validation-error: 3.4.0(zod@3.24.3) transitivePeerDependencies: - supports-color - eslint-plugin-react-hooks@5.2.0(eslint@9.25.0(jiti@2.4.2)): + eslint-plugin-react-hooks@6.0.0-rc1(eslint@9.25.1(jiti@2.4.2)): dependencies: - eslint: 9.25.0(jiti@2.4.2) + '@babel/core': 7.26.10 + '@babel/parser': 7.27.0 + '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.10) + eslint: 9.25.1(jiti@2.4.2) + hermes-parser: 0.25.1 + zod: 3.24.3 + zod-validation-error: 3.4.0(zod@3.24.3) + transitivePeerDependencies: + - supports-color - eslint-plugin-react@7.37.5(eslint@9.25.0(jiti@2.4.2)): + eslint-plugin-react@7.37.5(eslint@9.25.1(jiti@2.4.2)): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -10232,7 +10061,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.25.0(jiti@2.4.2) + eslint: 9.25.1(jiti@2.4.2) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -10255,57 +10084,15 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.24.0(jiti@2.4.2): + eslint@9.25.1(jiti@2.4.2): dependencies: - '@eslint-community/eslint-utils': 4.6.1(eslint@9.24.0(jiti@2.4.2)) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.20.0 - '@eslint/config-helpers': 0.2.1 - '@eslint/core': 0.12.0 - '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.24.0 - '@eslint/plugin-kit': 0.2.8 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.2 - '@types/estree': 1.0.7 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.0 - escape-string-regexp: 4.0.0 - eslint-scope: 8.3.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.4.2 - transitivePeerDependencies: - - supports-color - - eslint@9.25.0(jiti@2.4.2): - dependencies: - '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.1(jiti@2.4.2)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.20.0 '@eslint/config-helpers': 0.2.1 '@eslint/core': 0.13.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.25.0 + '@eslint/js': 9.25.1 '@eslint/plugin-kit': 0.2.8 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 @@ -10507,10 +10294,10 @@ snapshots: form-data-encoder@2.1.4: {} - framer-motion@12.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + framer-motion@12.9.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: - motion-dom: 12.7.4 - motion-utils: 12.7.2 + motion-dom: 12.9.1 + motion-utils: 12.8.3 tslib: 2.8.1 optionalDependencies: react: 19.1.0 @@ -10522,12 +10309,12 @@ snapshots: fsevents@2.3.3: optional: true - fumadocs-core@15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + fumadocs-core@15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@formatjs/intl-localematcher': 0.6.1 '@orama/orama': 3.1.6 - '@shikijs/rehype': 3.2.2 - '@shikijs/transformers': 3.2.2 + '@shikijs/rehype': 3.3.0 + '@shikijs/transformers': 3.3.0 github-slugger: 2.0.0 hast-util-to-estree: 3.1.3 hast-util-to-jsx-runtime: 2.3.6 @@ -10537,54 +10324,53 @@ snapshots: remark: 15.0.1 remark-gfm: 4.0.1 scroll-into-view-if-needed: 3.1.0 - shiki: 3.2.2 + shiki: 3.3.0 unist-util-visit: 5.0.0 optionalDependencies: - next: 15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) transitivePeerDependencies: - '@types/react' - supports-color - fumadocs-mdx@11.6.0(@fumadocs/mdx-remote@1.3.0(acorn@8.14.1)(fumadocs-core@15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0))(acorn@8.14.1)(fumadocs-core@15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)): + fumadocs-mdx@11.6.1(@fumadocs/mdx-remote@1.3.0(acorn@8.14.1)(fumadocs-core@15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0))(acorn@8.14.1)(fumadocs-core@15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)): dependencies: '@mdx-js/mdx': 3.1.0(acorn@8.14.1) '@standard-schema/spec': 1.0.0 chokidar: 4.0.3 cross-spawn: 7.0.6 - esbuild: 0.25.2 + esbuild: 0.25.3 estree-util-value-to-estree: 3.3.3 fast-glob: 3.3.3 - fumadocs-core: 15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + fumadocs-core: 15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) gray-matter: 4.0.3 lru-cache: 11.1.0 - next: 15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) picocolors: 1.1.1 unist-util-visit: 5.0.0 zod: 3.24.3 optionalDependencies: - '@fumadocs/mdx-remote': 1.3.0(acorn@8.14.1)(fumadocs-core@15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0) + '@fumadocs/mdx-remote': 1.3.0(acorn@8.14.1)(fumadocs-core@15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0) transitivePeerDependencies: - acorn - supports-color - fumadocs-ui@15.2.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tailwindcss@4.1.4): + fumadocs-ui@15.2.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tailwindcss@4.1.4): dependencies: - '@radix-ui/react-accordion': 1.2.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-collapsible': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-dialog': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-accordion': 1.2.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-collapsible': 1.1.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-dialog': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-navigation-menu': 1.2.9(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-popover': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-scroll-area': 1.2.5(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-navigation-menu': 1.2.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-popover': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-scroll-area': 1.2.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-slot': 1.2.0(@types/react@19.1.2)(react@19.1.0) - '@radix-ui/react-tabs': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-tabs': 1.1.9(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) class-variance-authority: 0.7.1 - fumadocs-core: 15.2.8(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + fumadocs-core: 15.2.11(@types/react@19.1.2)(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) lodash.merge: 4.6.2 - lucide-react: 0.488.0(react@19.1.0) - next: 15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next-themes: 0.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) postcss-selector-parser: 7.1.0 react: 19.1.0 @@ -10703,6 +10489,15 @@ snapshots: define-properties: 1.2.1 gopd: 1.2.0 + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + gopd@1.2.0: {} got@13.0.0: @@ -10821,8 +10616,6 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.7.6: {} - hono@4.7.7: {} html-to-text@9.0.5: @@ -10917,6 +10710,10 @@ snapshots: dependencies: has-bigints: 1.1.0 + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + is-boolean-object@1.2.2: dependencies: call-bound: 1.0.4 @@ -11093,7 +10890,7 @@ snapshots: dependencies: json-buffer: 3.0.1 - keyv@5.3.2: + keyv@5.3.3: dependencies: '@keyv/serialize': 1.0.3 @@ -11148,7 +10945,7 @@ snapshots: lightningcss@1.29.2: dependencies: - detect-libc: 2.0.3 + detect-libc: 2.0.4 optionalDependencies: lightningcss-darwin-arm64: 1.29.2 lightningcss-darwin-x64: 1.29.2 @@ -11690,15 +11487,15 @@ snapshots: minipass@7.1.2: {} - motion-dom@12.7.4: + motion-dom@12.9.1: dependencies: - motion-utils: 12.7.2 + motion-utils: 12.8.3 - motion-utils@12.7.2: {} + motion-utils@12.8.3: {} - motion@12.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + motion@12.9.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: - framer-motion: 12.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + framer-motion: 12.9.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) tslib: 2.8.1 optionalDependencies: react: 19.1.0 @@ -11710,6 +11507,8 @@ snapshots: mute-stream@2.0.0: {} + mylas@2.1.13: {} + mz@2.7.0: dependencies: any-promise: 1.3.0 @@ -11726,33 +11525,23 @@ snapshots: negotiator@1.0.0: {} - next-intl@4.0.2(next@15.3.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3): - dependencies: - '@formatjs/intl-localematcher': 0.5.10 - negotiator: 1.0.0 - next: 15.3.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react: 19.1.0 - use-intl: 4.0.2(react@19.1.0) - optionalDependencies: - typescript: 5.8.3 - - next-intl@4.0.2(next@15.3.1(@babel/core@7.26.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3): + next-intl@4.1.0(next@15.3.1(@babel/core@7.26.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3): dependencies: '@formatjs/intl-localematcher': 0.5.10 negotiator: 1.0.0 next: 15.3.1(@babel/core@7.26.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 - use-intl: 4.0.2(react@19.1.0) + use-intl: 4.1.0(react@19.1.0) optionalDependencies: typescript: 5.8.3 - next-intl@4.0.2(next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3): + next-intl@4.1.0(next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(typescript@5.8.3): dependencies: '@formatjs/intl-localematcher': 0.5.10 negotiator: 1.0.0 - next: 15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 - use-intl: 4.0.2(react@19.1.0) + use-intl: 4.1.0(react@19.1.0) optionalDependencies: typescript: 5.8.3 @@ -11767,7 +11556,7 @@ snapshots: '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 - caniuse-lite: 1.0.30001714 + caniuse-lite: 1.0.30001715 postcss: 8.4.31 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -11786,13 +11575,13 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@15.2.4(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next@15.2.4(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@next/env': 15.2.4 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 - caniuse-lite: 1.0.30001714 + caniuse-lite: 1.0.30001715 postcss: 8.4.31 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -11806,44 +11595,19 @@ snapshots: '@next/swc-linux-x64-musl': 15.2.4 '@next/swc-win32-arm64-msvc': 15.2.4 '@next/swc-win32-x64-msvc': 15.2.4 - babel-plugin-react-compiler: 19.0.0-beta-ebf51a3-20250411 + babel-plugin-react-compiler: 19.1.0-rc.1 sharp: 0.33.5 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@15.3.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): - dependencies: - '@next/env': 15.3.0 - '@swc/counter': 0.1.3 - '@swc/helpers': 0.5.15 - busboy: 1.6.0 - caniuse-lite: 1.0.30001712 - postcss: 8.4.31 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - styled-jsx: 5.1.6(@babel/core@7.26.10)(react@19.1.0) - optionalDependencies: - '@next/swc-darwin-arm64': 15.3.0 - '@next/swc-darwin-x64': 15.3.0 - '@next/swc-linux-arm64-gnu': 15.3.0 - '@next/swc-linux-arm64-musl': 15.3.0 - '@next/swc-linux-x64-gnu': 15.3.0 - '@next/swc-linux-x64-musl': 15.3.0 - '@next/swc-win32-arm64-msvc': 15.3.0 - '@next/swc-win32-x64-msvc': 15.3.0 - sharp: 0.34.1 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - next@15.3.1(@babel/core@7.26.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@next/env': 15.3.1 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 - caniuse-lite: 1.0.30001714 + caniuse-lite: 1.0.30001715 postcss: 8.4.31 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -11862,13 +11626,13 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@15.3.1(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next@15.3.1(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@next/env': 15.3.1 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 - caniuse-lite: 1.0.30001714 + caniuse-lite: 1.0.30001715 postcss: 8.4.31 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -11882,7 +11646,7 @@ snapshots: '@next/swc-linux-x64-musl': 15.3.1 '@next/swc-win32-arm64-msvc': 15.3.1 '@next/swc-win32-x64-msvc': 15.3.1 - babel-plugin-react-compiler: 19.0.0-beta-ebf51a3-20250411 + babel-plugin-react-compiler: 19.1.0-rc.1 sharp: 0.34.1 transitivePeerDependencies: - '@babel/core' @@ -11947,12 +11711,11 @@ snapshots: dependencies: mimic-function: 5.0.1 - oniguruma-parser@0.11.2: {} + oniguruma-parser@0.12.0: {} - oniguruma-to-es@4.2.0: + oniguruma-to-es@4.3.1: dependencies: - emoji-regex-xs: 1.0.0 - oniguruma-parser: 0.11.2 + oniguruma-parser: 0.12.0 regex: 6.0.1 regex-recursion: 6.0.2 @@ -12043,16 +11806,18 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 + path-type@4.0.0: {} + peberminta@0.9.0: {} peek-readable@5.4.2: {} pend@1.2.0: {} - pg-cloudflare@1.1.1: + pg-cloudflare@1.2.5: optional: true - pg-connection-string@2.7.0: + pg-connection-string@2.8.5: optional: true pg-int8@1.0.1: @@ -12061,12 +11826,12 @@ snapshots: pg-numeric@1.0.2: optional: true - pg-pool@3.8.0(pg@8.13.1): + pg-pool@3.9.6(pg@8.13.1): dependencies: pg: 8.13.1 optional: true - pg-protocol@1.8.0: + pg-protocol@1.9.5: optional: true pg-types@2.2.0: @@ -12091,13 +11856,13 @@ snapshots: pg@8.13.1: dependencies: - pg-connection-string: 2.7.0 - pg-pool: 3.8.0(pg@8.13.1) - pg-protocol: 1.8.0 + pg-connection-string: 2.8.5 + pg-pool: 3.9.6(pg@8.13.1) + pg-protocol: 1.9.5 pg-types: 2.2.0 pgpass: 1.0.5 optionalDependencies: - pg-cloudflare: 1.1.1 + pg-cloudflare: 1.2.5 optional: true pgpass@1.0.5: @@ -12125,6 +11890,10 @@ snapshots: optionalDependencies: fsevents: 2.3.2 + plimit-lit@1.6.1: + dependencies: + queue-lit: 1.5.2 + possible-typed-array-names@1.1.0: {} postcss-load-config@6.0.1(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.3)(yaml@2.7.1): @@ -12225,6 +11994,8 @@ snapshots: punycode@2.3.1: {} + queue-lit@1.5.2: {} + queue-microtask@1.2.3: {} quick-lru@5.1.1: {} @@ -12263,7 +12034,7 @@ snapshots: - supports-color - utf-8-validate - react-email@4.0.7(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + react-email@4.0.7(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@babel/parser': 7.24.5 '@babel/traverse': 7.25.6 @@ -12275,7 +12046,7 @@ snapshots: glob: 10.3.4 log-symbols: 4.1.0 mime-types: 2.1.35 - next: 15.2.4(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.2.4(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) normalize-path: 3.0.0 ora: 5.4.1 socket.io: 4.8.1 @@ -12292,7 +12063,7 @@ snapshots: - supports-color - utf-8-validate - react-hook-form@7.55.0(react@19.1.0): + react-hook-form@7.56.1(react@19.1.0): dependencies: react: 19.1.0 @@ -12336,7 +12107,7 @@ snapshots: '@pivanov/utils': 0.0.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@preact/signals': 1.3.2(preact@10.26.5) '@rollup/pluginutils': 5.1.4(rollup@4.40.0) - '@types/node': 20.17.30 + '@types/node': 20.17.31 bippy: 0.3.9(@types/react@19.1.2)(react@19.1.0) esbuild: 0.24.2 estree-walker: 3.0.3 @@ -12371,6 +12142,10 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + readdirp@4.1.2: {} recma-build-jsx@1.0.0: @@ -12493,7 +12268,7 @@ snapshots: require-directory@2.1.1: {} - resend@4.3.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + resend@4.4.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@react-email/render': 1.0.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) transitivePeerDependencies: @@ -12649,7 +12424,7 @@ snapshots: sharp@0.33.5: dependencies: color: 4.2.3 - detect-libc: 2.0.3 + detect-libc: 2.0.4 semver: 7.7.1 optionalDependencies: '@img/sharp-darwin-arm64': 0.33.5 @@ -12676,7 +12451,7 @@ snapshots: sharp@0.34.1: dependencies: color: 4.2.3 - detect-libc: 2.0.3 + detect-libc: 2.0.4 semver: 7.7.1 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.1 @@ -12709,14 +12484,14 @@ snapshots: shell-quote@1.8.2: {} - shiki@3.2.2: + shiki@3.3.0: dependencies: - '@shikijs/core': 3.2.2 - '@shikijs/engine-javascript': 3.2.2 - '@shikijs/engine-oniguruma': 3.2.2 - '@shikijs/langs': 3.2.2 - '@shikijs/themes': 3.2.2 - '@shikijs/types': 3.2.2 + '@shikijs/core': 3.3.0 + '@shikijs/engine-javascript': 3.3.0 + '@shikijs/engine-oniguruma': 3.3.0 + '@shikijs/langs': 3.3.0 + '@shikijs/themes': 3.3.0 + '@shikijs/types': 3.3.0 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 @@ -13017,7 +12792,7 @@ snapshots: tinyexec@0.3.2: {} - tinyglobby@0.2.12: + tinyglobby@0.2.13: dependencies: fdir: 6.4.4(picomatch@4.0.2) picomatch: 4.0.2 @@ -13051,16 +12826,26 @@ snapshots: ts-interface-checker@0.1.13: {} + tsc-alias@1.8.15: + dependencies: + chokidar: 3.6.0 + commander: 9.5.0 + get-tsconfig: 4.10.0 + globby: 11.1.0 + mylas: 2.1.13 + normalize-path: 3.0.0 + plimit-lit: 1.6.1 + tslib@2.8.1: {} - tsup@8.4.0(@swc/core@1.11.21)(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.7.1): + tsup@8.4.0(@swc/core@1.11.22)(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.7.1): dependencies: - bundle-require: 5.1.0(esbuild@0.25.2) + bundle-require: 5.1.0(esbuild@0.25.3) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 debug: 4.4.0 - esbuild: 0.25.2 + esbuild: 0.25.3 joycon: 3.1.1 picocolors: 1.1.1 postcss-load-config: 6.0.1(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.3)(yaml@2.7.1) @@ -13069,10 +12854,10 @@ snapshots: source-map: 0.8.0-beta.0 sucrase: 3.35.0 tinyexec: 0.3.2 - tinyglobby: 0.2.12 + tinyglobby: 0.2.13 tree-kill: 1.2.2 optionalDependencies: - '@swc/core': 1.11.21 + '@swc/core': 1.11.22 postcss: 8.5.3 typescript: 5.8.3 transitivePeerDependencies: @@ -13083,39 +12868,39 @@ snapshots: tsx@4.19.3: dependencies: - esbuild: 0.25.2 + esbuild: 0.25.3 get-tsconfig: 4.10.0 optionalDependencies: fsevents: 2.3.3 - turbo-darwin-64@2.5.0: + turbo-darwin-64@2.5.2: optional: true - turbo-darwin-arm64@2.5.0: + turbo-darwin-arm64@2.5.2: optional: true - turbo-linux-64@2.5.0: + turbo-linux-64@2.5.2: optional: true - turbo-linux-arm64@2.5.0: + turbo-linux-arm64@2.5.2: optional: true - turbo-windows-64@2.5.0: + turbo-windows-64@2.5.2: optional: true - turbo-windows-arm64@2.5.0: + turbo-windows-arm64@2.5.2: optional: true - turbo@2.5.0: + turbo@2.5.2: optionalDependencies: - turbo-darwin-64: 2.5.0 - turbo-darwin-arm64: 2.5.0 - turbo-linux-64: 2.5.0 - turbo-linux-arm64: 2.5.0 - turbo-windows-64: 2.5.0 - turbo-windows-arm64: 2.5.0 + turbo-darwin-64: 2.5.2 + turbo-darwin-arm64: 2.5.2 + turbo-linux-64: 2.5.2 + turbo-linux-arm64: 2.5.2 + turbo-windows-64: 2.5.2 + turbo-windows-arm64: 2.5.2 - tw-animate-css@1.2.5: {} + tw-animate-css@1.2.8: {} type-check@0.4.0: dependencies: @@ -13156,12 +12941,12 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3): + typescript-eslint@8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/parser': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) - eslint: 9.25.0(jiti@2.4.2) + '@typescript-eslint/eslint-plugin': 8.31.0(@typescript-eslint/parser@8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/parser': 8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.31.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3) + eslint: 9.25.1(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -13246,7 +13031,7 @@ snapshots: optionalDependencies: '@types/react': 19.1.2 - use-intl@4.0.2(react@19.1.0): + use-intl@4.1.0(react@19.1.0): dependencies: '@formatjs/fast-memoize': 2.2.7 '@schummar/icu-type-parser': 1.21.5 @@ -13267,7 +13052,7 @@ snapshots: vaul@1.1.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: - '@radix-ui/react-dialog': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-dialog': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) transitivePeerDependencies: From 708ec47a5ffd8fe8685b364ad0f757cd5a117b9b Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 27 Apr 2025 14:20:04 +0200 Subject: [PATCH 08/11] perf: Add args into fetcher --- packages/vitnode/src/test/elo.ts | 194 +++++++++++++++---- packages/vitnode/src/test/test.ts | 2 + plugins/blog/src/modules/categories/route.ts | 5 + plugins/blog/src/modules/categories/test.ts | 5 + 4 files changed, 166 insertions(+), 40 deletions(-) diff --git a/packages/vitnode/src/test/elo.ts b/packages/vitnode/src/test/elo.ts index e8122f710..9c0b15356 100644 --- a/packages/vitnode/src/test/elo.ts +++ b/packages/vitnode/src/test/elo.ts @@ -1,6 +1,8 @@ import { BaseBuildModuleReturn, BuildModuleReturn } from '@/api/lib/module'; import { Route } from '@/api/lib/route'; import { usersModule } from '@/api/modules/users/users.module'; +import { RouteConfig } from '@hono/zod-openapi'; +import { z } from 'zod'; // --- Core Type Definitions --- @@ -46,8 +48,21 @@ type FindModuleNested< : // If Path is empty, it implies we are looking for the module M itself M; +// --- Simplified Module Path Types --- + +// Creates a string union type of all possible module paths up to 3 levels deep +type GetModulePaths< + MainModule extends string, + Modules extends readonly ModuleSpec[], +> = + | `${MainModule}/${Modules[number]['name']}/${Extract< + Modules[number]['modules'], + readonly ModuleSpec[] + >[number]['name']}` + | `${MainModule}/${Modules[number]['name']}` + | MainModule; + // Helper to get the target module specification based on the module path string -// It handles the base module case and nested module cases. type GetTargetModule< ModulePath extends string, MainModuleName extends string, @@ -73,9 +88,61 @@ type ExtractMethodForPath< P extends string, > = Extract['route']['method']; -// --- Derived Types for Fetcher --- +// --- Type extraction utilities --- + +// Helper to extract types from Zod schemas that might be in different structures +type ExtractZodType = T extends z.ZodTypeAny ? z.infer : never; + +// Infers the input type for a specific part of the route config (body, query, params) +type InferInputType< + RouteCfg extends RouteConfig, + Part extends 'body' | 'params' | 'query', +> = Part extends 'body' + ? RouteCfg extends { + request: { + body: { content: { 'application/json': { schema: infer S } } }; + }; + } + ? ExtractZodType + : RouteCfg extends { request: { body: { schema?: infer S } } } + ? ExtractZodType + : undefined + : Part extends 'query' + ? RouteCfg extends { request: { query: infer S } } + ? ExtractZodType + : undefined + : Part extends 'params' + ? RouteCfg extends { request: { params: infer S } } + ? ExtractZodType + : undefined + : never; + +// --- Route Configuration Extraction --- + +// Find the route configuration for a specific module path, route path, and method +type FindRouteConfig< + M extends { routes: readonly Route[] }, + P extends string, + Method extends string, +> = Extract< + M['routes'][number], + { route: { method: Method; path: P } } +>['route']; + +// Constructs the final Args type based on the inferred input types +type BuildArgsType = { + // Use key remapping to filter out keys where the inferred type is undefined + [K in 'body' | 'params' | 'query' as InferInputType< + RouteCfg, + K + > extends undefined + ? never + : K]: InferInputType; +}; -// Gets all valid path strings for a given module path (e.g., "users" or "users/sso") +// --- Fetcher Types --- + +// Gets all valid path strings for a given module path type GetValidPathsForModule< ModulePath extends string, MainModuleName extends string, @@ -85,7 +152,7 @@ type GetValidPathsForModule< GetTargetModule >; -// Gets the valid method (lowercase) for a given module path and a specific path within that module +// Gets the valid method for a given module path and route path type GetValidMethodForPath< ModulePath extends string, Path extends string, @@ -98,79 +165,126 @@ type GetValidMethodForPath< GetTargetModule, Path >, - string // Ensure we only get string methods + string > >; -// --- Fetcher Function Definition --- +// --- Fetcher Parameters --- -// Define the structure for the fetcher parameters, using the derived types for constraints -interface FetcherParams< - // Generic parameters from BuildModuleReturn - P extends string, +// Define the base parameters without args +interface BaseFetcherParams< M extends string, Routes extends Route[], - Modules extends BaseBuildModuleReturn

[], - // The specific module path string provided by the user (e.g., "users/sso") - // This complex union type accurately constrains valid module paths. - ModuleName extends - | `${M}/${Modules[number]['name']}/${Extract< - Modules[number]['modules'], - readonly BaseBuildModuleReturn

[] - >[number]['name']}` // Second level sub-module - | `${M}/${Modules[number]['name']}` // First level sub-module (e.g., "users/sso") - // Add support for deeper nesting if necessary: - | M, // Base module name (e.g., "users") - // The specific path string selected within the chosen module + Modules extends BaseBuildModuleReturn[], + ModuleName extends GetModulePaths, SelectedPath extends GetValidPathsForModule, > { - input?: unknown; // TODO: Define input type based on the route if possible method: GetValidMethodForPath; module: ModuleName; path: SelectedPath; } -// The fetcher function signature +// Use conditional type with intersection to define FetcherParams +type FetcherParams< + // Module definition parameters + M extends string, + Routes extends Route[], + Modules extends BaseBuildModuleReturn[], + // Dynamic parameters based on user selection + ModuleName extends GetModulePaths, + SelectedPath extends GetValidPathsForModule, + // Extract the route configuration and build the args type + RouteConfig extends FindRouteConfig< + GetTargetModule, + SelectedPath, + GetValidMethodForPath + > = FindRouteConfig< + GetTargetModule, + SelectedPath, + GetValidMethodForPath + >, + ArgsType extends BuildArgsType = BuildArgsType, +> = BaseFetcherParams & // Intersect with base + (keyof ArgsType extends never + ? { args?: undefined } // Args optional and undefined if ArgsType is empty + : { args: ArgsType }); // Args required if ArgsType is not empty + +// --- Fetcher Function --- + +// Simplified fetcher with fewer generic type parameters export function fetcher< - // Generic parameters matching BuildModuleReturn - P extends string, M extends string, Routes extends Route[], - Modules extends BaseBuildModuleReturn

[], - // Constrain ModuleName to valid possibilities based on the module structure - ModuleName extends - | `${M}/${Modules[number]['name']}/${Extract< - Modules[number]['modules'], - readonly BaseBuildModuleReturn

[] - >[number]['name']}` - | `${M}/${Modules[number]['name']}` - | M, - // SelectedPath is constrained based on the chosen ModuleName + Modules extends BaseBuildModuleReturn[], + ModuleName extends GetModulePaths, SelectedPath extends GetValidPathsForModule, >( - _moduleInput: BuildModuleReturn, // Mark as unused - params: FetcherParams, + _moduleInput: BuildModuleReturn, + params: FetcherParams, ): void { // Function implementation would go here void params; // Mark as unused for now } +// Test cases (() => { + // Assuming /sign_in requires a body, this would now potentially error if args is missing + // If it doesn't require args, this is fine. fetcher(usersModule, { - path: '/test', - method: 'get', + path: '/sign_in', + method: 'post', module: 'users', + args: { + body: { + email: 'string', + password: 'string', + }, + }, }); fetcher(usersModule, { path: '/{providerId}', method: 'post', module: 'users/sso', + args: { + // args is required because params exist + params: { + providerId: 'github', + }, + }, }); fetcher(usersModule, { path: '/{providerId}/callback', method: 'get', module: 'users/sso', + args: { + // args is required because params and query exist + params: { + providerId: 'github', + }, + query: { + code: 'some-code', + state: 'some-state', + }, + }, + }); + + // Assuming /test does not require args, this is fine. + fetcher(usersModule, { + path: '/test', + method: 'post', + module: 'users/sso/test', + // args is optional here if ArgsType is empty + }); + + // Should trigger error if required args are missing + /* Error example (assuming /sign_in requires args): + fetcher(usersModule, { + path: '/sign_in', + method: 'post', + module: 'users', + // Missing required 'args' property }); + */ })(); diff --git a/packages/vitnode/src/test/test.ts b/packages/vitnode/src/test/test.ts index 261805b46..b18c4ca68 100644 --- a/packages/vitnode/src/test/test.ts +++ b/packages/vitnode/src/test/test.ts @@ -80,3 +80,5 @@ export const test = new OpenAPIHono() .route('/something', test1); const client = hc('http://localhost:3000/api/core/test'); + +await client.something.test123[':test'].$get({}); diff --git a/plugins/blog/src/modules/categories/route.ts b/plugins/blog/src/modules/categories/route.ts index 32e20fcd0..6e8e92965 100644 --- a/plugins/blog/src/modules/categories/route.ts +++ b/plugins/blog/src/modules/categories/route.ts @@ -5,6 +5,11 @@ export const categoriesRoute = buildRoute({ route: { method: 'get', path: '/', + request: { + query: z.object({ + test: z.string(), + }), + }, responses: { 200: { content: { diff --git a/plugins/blog/src/modules/categories/test.ts b/plugins/blog/src/modules/categories/test.ts index f42ed08d8..e0687404c 100644 --- a/plugins/blog/src/modules/categories/test.ts +++ b/plugins/blog/src/modules/categories/test.ts @@ -7,5 +7,10 @@ export const test = () => { module: 'categories', path: '/', method: 'get', + args: { + query: { + test: 'test', + }, + }, }); }; From 42daebc22d8538f3d70bf54b5c3f7092cce044dc Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 27 Apr 2025 16:15:14 +0200 Subject: [PATCH 09/11] perf: Add ClientResponse type for fetcher --- .../api/modules/users/routes/sign-in.route.ts | 8 +- .../users/sso/test/routes/test.route.ts | 5 +- packages/vitnode/src/test/elo.ts | 170 ++++++++++-------- packages/vitnode/src/test/test.ts | 35 ++-- 4 files changed, 126 insertions(+), 92 deletions(-) diff --git a/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts b/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts index 2110861b5..4761fb0aa 100644 --- a/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts @@ -30,7 +30,7 @@ export const signInRoute = buildRoute({ }, }, responses: { - 200: { + 201: { content: { 'application/json': { schema: z.object({ @@ -43,6 +43,12 @@ export const signInRoute = buildRoute({ }, 403: { description: 'Access Denied', + 'application/json': { + schema: z.object({ + id: z.string(), + token: z.string(), + }), + }, }, }, }, diff --git a/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts b/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts index d9a857337..e5ad531b8 100644 --- a/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts +++ b/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts @@ -7,6 +7,9 @@ export const testRoute = buildRoute({ description: 'Test route', path: '/test', responses: { + 301: { + description: 'Redirect', + }, 200: { content: { 'text/plain': { @@ -26,6 +29,6 @@ export const testRoute = buildRoute({ }, }, handler: c => { - return c.text('test'); + return c.redirect('/', 301); }, }); diff --git a/packages/vitnode/src/test/elo.ts b/packages/vitnode/src/test/elo.ts index 9c0b15356..a928d92c5 100644 --- a/packages/vitnode/src/test/elo.ts +++ b/packages/vitnode/src/test/elo.ts @@ -2,11 +2,43 @@ import { BaseBuildModuleReturn, BuildModuleReturn } from '@/api/lib/module'; import { Route } from '@/api/lib/route'; import { usersModule } from '@/api/modules/users/users.module'; import { RouteConfig } from '@hono/zod-openapi'; +import { ResponseFormat } from 'hono/types'; +import { StatusCode, SuccessStatusCode } from 'hono/utils/http-status'; import { z } from 'zod'; -// --- Core Type Definitions --- +interface ClientResponse< + T, + U extends number = StatusCode, + F extends ResponseFormat = ResponseFormat, +> extends globalThis.Response { + arrayBuffer: () => Promise; + blob: () => Promise; + readonly body: null | ReadableStream; + readonly bodyUsed: boolean; + clone: () => Response; + formData: () => Promise; + headers: Headers; + json: () => F extends 'text/html' | 'text/plain' + ? Promise + : F extends 'application/json' + ? Promise + : Promise; + ok: U extends SuccessStatusCode + ? true + : U extends Exclude + ? false + : boolean; + redirect: (url: string, status: number) => Response; + status: U; + statusText: string; + text: () => F extends 'text/html' | 'text/plain' + ? T extends string + ? Promise + : Promise + : Promise; + url: string; +} -// Represents the expected shape of a route for type extraction interface RouteShape { readonly route: { readonly method: string; @@ -14,43 +46,31 @@ interface RouteShape { }; } -// Represents the expected shape of a module for type extraction interface ModuleSpec { readonly modules?: readonly ModuleSpec[]; readonly name: string; readonly routes: readonly RouteShape[]; } -// --- Utility Types --- - -// Splits a path string like "a/b/c" into ["a", "b", "c"] type SplitPath = S extends `${infer First}/${infer Rest}` ? [First, ...SplitPath] - : S extends '' // Handle empty string case + : S extends '' ? [] : [S]; -// Recursively finds a nested module definition based on a path array type FindModuleNested< M extends { modules?: readonly ModuleSpec[] }, Path extends string[], > = Path extends [infer First extends string, ...infer Rest extends string[]] - ? // Find the sub-module matching the first path segment - Extract[number] extends infer SubModule + ? Extract[number] extends infer SubModule ? SubModule extends ModuleSpec & { name: First } - ? // If this is the last segment, return the found sub-module - Rest['length'] extends 0 + ? Rest['length'] extends 0 ? SubModule - : // Otherwise, recurse into the found sub-module - FindModuleNested - : never // No sub-module found with that name - : never // M['modules'] is not an array or is empty - : // If Path is empty, it implies we are looking for the module M itself - M; - -// --- Simplified Module Path Types --- + : FindModuleNested + : never + : never + : M; -// Creates a string union type of all possible module paths up to 3 levels deep type GetModulePaths< MainModule extends string, Modules extends readonly ModuleSpec[], @@ -62,38 +82,31 @@ type GetModulePaths< | `${MainModule}/${Modules[number]['name']}` | MainModule; -// Helper to get the target module specification based on the module path string type GetTargetModule< ModulePath extends string, MainModuleName extends string, MainRoutes extends readonly RouteShape[], SubModules extends readonly ModuleSpec[], > = ModulePath extends MainModuleName - ? { modules: SubModules; name: MainModuleName; routes: MainRoutes } // Return the main module spec + ? { modules: SubModules; name: MainModuleName; routes: MainRoutes } : ModulePath extends `${MainModuleName}/${infer Rest}` ? SplitPath extends infer PathArray extends string[] ? PathArray['length'] extends 0 - ? never // Path like "main/" is invalid + ? never : FindModuleNested<{ modules: SubModules }, PathArray> : never - : never; // Path doesn't start with the main module name + : never; -// Extracts all possible path strings from a module's routes type ExtractPaths = M['routes'][number]['route']['path']; -// Extracts the method string for a specific path within a module's routes type ExtractMethodForPath< M extends { routes: readonly RouteShape[] }, P extends string, > = Extract['route']['method']; -// --- Type extraction utilities --- - -// Helper to extract types from Zod schemas that might be in different structures type ExtractZodType = T extends z.ZodTypeAny ? z.infer : never; -// Infers the input type for a specific part of the route config (body, query, params) type InferInputType< RouteCfg extends RouteConfig, Part extends 'body' | 'params' | 'query', @@ -117,9 +130,6 @@ type InferInputType< : undefined : never; -// --- Route Configuration Extraction --- - -// Find the route configuration for a specific module path, route path, and method type FindRouteConfig< M extends { routes: readonly Route[] }, P extends string, @@ -129,9 +139,7 @@ type FindRouteConfig< { route: { method: Method; path: P } } >['route']; -// Constructs the final Args type based on the inferred input types type BuildArgsType = { - // Use key remapping to filter out keys where the inferred type is undefined [K in 'body' | 'params' | 'query' as InferInputType< RouteCfg, K @@ -140,9 +148,6 @@ type BuildArgsType = { : K]: InferInputType; }; -// --- Fetcher Types --- - -// Gets all valid path strings for a given module path type GetValidPathsForModule< ModulePath extends string, MainModuleName extends string, @@ -152,7 +157,6 @@ type GetValidPathsForModule< GetTargetModule >; -// Gets the valid method for a given module path and route path type GetValidMethodForPath< ModulePath extends string, Path extends string, @@ -169,9 +173,6 @@ type GetValidMethodForPath< > >; -// --- Fetcher Parameters --- - -// Define the base parameters without args interface BaseFetcherParams< M extends string, Routes extends Route[], @@ -184,16 +185,12 @@ interface BaseFetcherParams< path: SelectedPath; } -// Use conditional type with intersection to define FetcherParams type FetcherParams< - // Module definition parameters M extends string, Routes extends Route[], Modules extends BaseBuildModuleReturn[], - // Dynamic parameters based on user selection ModuleName extends GetModulePaths, SelectedPath extends GetValidPathsForModule, - // Extract the route configuration and build the args type RouteConfig extends FindRouteConfig< GetTargetModule, SelectedPath, @@ -204,15 +201,43 @@ type FetcherParams< GetValidMethodForPath >, ArgsType extends BuildArgsType = BuildArgsType, -> = BaseFetcherParams & // Intersect with base - (keyof ArgsType extends never - ? { args?: undefined } // Args optional and undefined if ArgsType is empty - : { args: ArgsType }); // Args required if ArgsType is not empty +> = BaseFetcherParams & + (keyof ArgsType extends never ? { args?: undefined } : { args: ArgsType }); -// --- Fetcher Function --- +type InferResponseType< + M extends string, + Routes extends Route[], + Modules extends BaseBuildModuleReturn[], + ModuleName extends GetModulePaths, + SelectedPath extends GetValidPathsForModule, + RouteConfig extends FindRouteConfig< + GetTargetModule, + SelectedPath, + GetValidMethodForPath + > = FindRouteConfig< + GetTargetModule, + SelectedPath, + GetValidMethodForPath + >, +> = RouteConfig extends { responses: infer S } + ? { + [K in keyof S]: S[K] extends { content: infer C } + ? { + [Fmt in keyof C]: ClientResponse< + C[Fmt] extends { schema: infer S } ? ExtractZodType : never, + K extends `${infer N extends number}` + ? N + : K extends number + ? K + : never, + Fmt extends string ? Fmt : string + >; + }[keyof C] + : never; + }[keyof S] + : never; -// Simplified fetcher with fewer generic type parameters -export function fetcher< +export async function fetcher< M extends string, Routes extends Route[], Modules extends BaseBuildModuleReturn[], @@ -221,16 +246,17 @@ export function fetcher< >( _moduleInput: BuildModuleReturn, params: FetcherParams, -): void { - // Function implementation would go here - void params; // Mark as unused for now +): Promise> { + void params; + + await fetch(''); + + return {} as InferResponseType; } // Test cases -(() => { - // Assuming /sign_in requires a body, this would now potentially error if args is missing - // If it doesn't require args, this is fine. - fetcher(usersModule, { +void (async () => { + const test = await fetcher(usersModule, { path: '/sign_in', method: 'post', module: 'users', @@ -242,24 +268,24 @@ export function fetcher< }, }); - fetcher(usersModule, { + const tes123t = await test.json(); + + const test2 = await fetcher(usersModule, { path: '/{providerId}', method: 'post', module: 'users/sso', args: { - // args is required because params exist params: { providerId: 'github', }, }, }); - fetcher(usersModule, { + const test3 = await fetcher(usersModule, { path: '/{providerId}/callback', method: 'get', module: 'users/sso', args: { - // args is required because params and query exist params: { providerId: 'github', }, @@ -270,21 +296,9 @@ export function fetcher< }, }); - // Assuming /test does not require args, this is fine. - fetcher(usersModule, { + const test4 = await fetcher(usersModule, { path: '/test', method: 'post', module: 'users/sso/test', - // args is optional here if ArgsType is empty - }); - - // Should trigger error if required args are missing - /* Error example (assuming /sign_in requires args): - fetcher(usersModule, { - path: '/sign_in', - method: 'post', - module: 'users', - // Missing required 'args' property }); - */ })(); diff --git a/packages/vitnode/src/test/test.ts b/packages/vitnode/src/test/test.ts index b18c4ca68..a2ff2691a 100644 --- a/packages/vitnode/src/test/test.ts +++ b/packages/vitnode/src/test/test.ts @@ -13,30 +13,26 @@ const test1 = new OpenAPIHono().openapi( }), }, responses: { - 200: { + 201: { description: 'test', content: { - 'application/json': { - schema: z.object({ - test: z.string(), - }), + 'text/plain': { + schema: z.string(), }, }, }, 403: { description: 'test', content: { - 'application/json': { - schema: z.object({ - test: z.string(), - }), + 'text/plain': { + schema: z.string(), }, }, }, }, }), c => { - return c.json({ test: 'test' }); + return c.text('123'); }, ); @@ -51,7 +47,7 @@ export const test = new OpenAPIHono() }), }, responses: { - 200: { + 201: { description: 'test', content: { 'application/json': { @@ -81,4 +77,19 @@ export const test = new OpenAPIHono() const client = hc('http://localhost:3000/api/core/test'); -await client.something.test123[':test'].$get({}); +const test12 = await client.test.$get({ + query: { + test: '123', + }, +}); + +const elo = await test12.json(); + +// eslint-disable-next-line no-console +console.log(elo.test); + +const test124 = await client.something.test123[':test'].$get({ + param: { + test: '123', + }, +}); From 7098e0911a6f1e1ea1e5c9506573bc727126b8bc Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Mon, 28 Apr 2025 19:45:19 +0200 Subject: [PATCH 10/11] refactor: Apply new fetcher --- apps/docs/content/docs/dev/fetcher.mdx | 224 ++++-------------- apps/web/src/plugins/core/langs/en.json | 5 +- packages/vitnode/src/api/lib/module.ts | 4 +- packages/vitnode/src/api/lib/plugin.ts | 2 +- .../src/api/modules/admin/admin.module.ts | 2 - .../modules/middleware/middleware.module.ts | 4 - .../api/modules/users/routes/sign-in.route.ts | 16 +- .../src/api/modules/users/users.module.ts | 2 - .../vitnode/src/lib/api/get-middleware-api.ts | 15 +- .../src/lib/api/get-session-admin-api.ts | 13 +- .../vitnode/src/lib/api/get-session-api.ts | 15 +- packages/vitnode/src/lib/fetcher-client.ts | 32 --- packages/vitnode/src/lib/fetcher.ts | 157 ------------ packages/vitnode/src/lib/fetcher/index.ts | 134 +++++++++++ .../src/{test/elo.ts => lib/fetcher/types.ts} | 105 ++------ packages/vitnode/src/test/fetcher.ts | 66 ------ packages/vitnode/src/test/test.ts | 95 -------- packages/vitnode/src/test/testtest.ts | 64 ----- .../src/views/auth/sign-in/form/form.tsx | 6 +- .../auth/sign-in/form/hooks/mutation-api.ts | 28 ++- .../views/auth/sign-in/form/hooks/use-form.ts | 22 +- .../src/views/auth/sign-in/sign-in-view.tsx | 23 -- .../auth/sign-up/form/hooks/mutation-api.ts | 22 +- .../views/auth/sign-up/form/hooks/use-form.ts | 23 +- .../views/auth/sso/buttons/mutation-api.ts | 22 +- .../auth/sso/callback/client/mutation-api.ts | 28 ++- .../header/user/auth/log-out-mutation-api.ts | 20 +- plugins/blog/src/modules/categories/test.ts | 6 +- 28 files changed, 334 insertions(+), 821 deletions(-) delete mode 100644 packages/vitnode/src/lib/fetcher-client.ts delete mode 100644 packages/vitnode/src/lib/fetcher.ts create mode 100644 packages/vitnode/src/lib/fetcher/index.ts rename packages/vitnode/src/{test/elo.ts => lib/fetcher/types.ts} (75%) delete mode 100644 packages/vitnode/src/test/fetcher.ts delete mode 100644 packages/vitnode/src/test/test.ts delete mode 100644 packages/vitnode/src/test/testtest.ts diff --git a/apps/docs/content/docs/dev/fetcher.mdx b/apps/docs/content/docs/dev/fetcher.mdx index 749435a3a..5b6975b09 100644 --- a/apps/docs/content/docs/dev/fetcher.mdx +++ b/apps/docs/content/docs/dev/fetcher.mdx @@ -1,45 +1,52 @@ --- title: Fetcher -description: Fetch data from the server. +description: Fetch data with type-safe API --- -## Usage +Our fetcher has RPC (Remote Procedure Call) style API. It allows you to call any API endpoint with type-safe API. The `fetcher()` function is only server-side. You cannot use it on the client-side. -import { Step, Steps } from 'fumadocs-ui/components/steps'; - - - - - ### Initial client +## Usage -`fetcher()` is a function to create client. Pass generic type with the response type and pass the `plugin` and `module` as arguments. +To use the `fetcher()` function, you need to import it from the `vitnode/lib/fetcher` module. You also need to import the module you want to use. -As an example, we will pass `UsersTypes` as a generic type. +More about modules can be found in the [Modules](/docs/dev/modules) section. ```ts import { fetcher } from 'vitnode/lib/fetcher'; -import { UsersTypes } from 'vitnode/api/modules/users/users.module'; +import { usersModule } from 'vitnode/api/modules/users/users.module'; ``` -```tsx -const client = await fetcher({ - plugin: 'core', +```ts +const res = await fetcher(usersModule, { + path: '/session', + method: 'get', module: 'users', }); ``` -#### Options +The response from `fetcher()` is compatible with the standard `fetch` Response API. Here are common way to work with the response: + +```ts +// Basic response handling +if (res.ok) { + const data = await res.json(); + console.log(data); +} +``` + +### Options -You can pass the `options` object to modify the `fetch` function. For example we can pass `cache` option to enable the cache. +You can pass the `options` object to modify the `fetch` function. For example we can pass `cache` option to enable the cache from `next`: -```tsx -const client = await fetcher({ - plugin: 'core', +```ts +const res = await fetcher(usersModule, { + path: '/session', + method: 'get', module: 'users', // [!code ++] options: { @@ -50,167 +57,28 @@ const client = await fetcher({ }); ``` - - - - -### Fetch data - -Call `client.{path}.{method}` with the data you want to send to the server as an argument. - -```tsx -const data = await client.sign_in.$post(input); -``` - - - - -## Server Functions - -Methods like `POST`, `PUT` and `DELETE` require to use [Server Functions](https://react.dev/reference/rsc/server-functions). You can create `mutation-api.ts` file and use it to call the `fetcher()` function with `FetcherInput` type. - -```ts title="mutation-api.ts" -'use server'; - -import { UsersTypes } from 'vitnode/api/modules/users/users.module'; -import { fetcher, FetcherInput } from 'vitnode/lib/fetcher'; - -export const mutationApi = async ( - input: FetcherInput, -) => { - const res = await fetcher({ - plugin: 'core', - module: 'users', - }); - - await res.sign_in.$post(input); -}; -``` - -Now you can call the `mutationApi()` function on the server-side. - -```ts title="useForm.ts" -export const useForm = () => { - const onSubmit = async (values: z.infer) => { - // [!code ++] - await mutationApi({ - // [!code ++] - json: values, - // [!code ++] - }); - }; - - return { - onSubmit, - }; -}; -``` - -### Handling errors - -You can handle errors by checking the `status` property of the response. - -```ts title="mutation-api.ts" -export const mutationApi = async ( - input: FetcherInput, -) => { - const res = await fetcher({ - plugin: 'core', - module: 'users', - }); - - // [!code --] - await res.sign_in.$post(input); - // [!code ++] - const data = await res.sign_in.$post(input); - // [!code ++] - - // [!code ++] - if (data.status !== 200) { - // [!code ++] - return { message: await data.text() }; - // [!code ++] - } -}; -``` - -```ts title="useForm.ts" -// [!code ++] -import { useTranslations } from 'next-intl'; -// [!code ++] -import { toast } from 'sonner'; - -export const useForm = () => { - // [!code ++] - const t = useTranslations('core.global.errors'); - - const onSubmit = async (values: z.infer) => { - const mutation = await mutationApi({ - json: values, - }); - - // [!code ++] - if (!mutation?.message) return; - // [!code ++] - - // [!code ++] - toast.error(t('title'), { - // [!code ++] - description: t('internal_server_error'), - // [!code ++] - }); - }; - - return { - onSubmit, - }; -}; -``` - -### Handling set-cookies +### Handle set-cookies -React Server Components cannot handle `set-cookies` headers. You need to handle them by using the `handleCookiesFetcher()` function. +React Server Components cannot handle `set-cookies` headers from the server. To handle +this, you need to pass the `allowSaveCookies` param to the `fetcher()` function. This will allow the cookies to be saved in the response. -```ts title="mutation-api.ts" -'use server'; + + The `allowSaveCookies` param works only when your request has method different + from `get` and response status has 2xx. + -import { UsersTypes } from 'vitnode/api/modules/users/users.module'; -import { - fetcher, - FetcherInput, - // [!code ++] - handleSetCookiesFetcher, -} from 'vitnode/lib/fetcher'; - -export const mutationApi = async ( - input: FetcherInput, -) => { - const res = await fetcher({ - plugin: 'core', - module: 'users', - }); - - // [!code --] - await res.sign_in.$post(input); - // [!code ++] - const data = await res.sign_in.$post(input); +```ts +const res = await fetcher(usersModule, { + path: '/sign_in', + method: 'post', + module: 'users', // [!code ++] - await handleSetCookiesFetcher(data); -}; -``` - -## Client-side - -If you want to use the `fetcher()` on the client-side, you need to use the `fetcherClient()` function. - -```tsx - + allowSaveCookies: true, + args: { + body: { + email: '', + password: '', + }, + }, +}); ``` - -## Custom fetcher - -If you want you can create your own `fetch` function, but you need to remember to pass headers like: - -- `x-forwarded-for` header - client IP address, -- `Cookie` header - client cookies, -- `user-agent` header - client user agent. diff --git a/apps/web/src/plugins/core/langs/en.json b/apps/web/src/plugins/core/langs/en.json index 62287bca5..8e2d42545 100644 --- a/apps/web/src/plugins/core/langs/en.json +++ b/apps/web/src/plugins/core/langs/en.json @@ -96,7 +96,10 @@ "label": "Email", "invalid": "Invalid email address." }, - "password": "Password", + "password": { + "label": "Password", + "required": "Password is required." + }, "errors": { "access_denied": { "title": "Invalid credentials", diff --git a/packages/vitnode/src/api/lib/module.ts b/packages/vitnode/src/api/lib/module.ts index 7bc640d50..d24d855b9 100644 --- a/packages/vitnode/src/api/lib/module.ts +++ b/packages/vitnode/src/api/lib/module.ts @@ -22,8 +22,8 @@ export interface BaseBuildModuleReturn< export interface BuildModuleReturn< P extends string, M extends string, - Routes extends Route[] = [], - Modules extends BaseBuildModuleReturn

[] = [], + Routes extends Route[] = Route[], + Modules extends BaseBuildModuleReturn

[] = BaseBuildModuleReturn

[], > extends BaseBuildModuleReturn { modules?: Modules; } diff --git a/packages/vitnode/src/api/lib/plugin.ts b/packages/vitnode/src/api/lib/plugin.ts index 709a37a56..d288060c6 100644 --- a/packages/vitnode/src/api/lib/plugin.ts +++ b/packages/vitnode/src/api/lib/plugin.ts @@ -11,7 +11,7 @@ export function buildPlugin

({ name, modules = [], }: { - modules?: BuildModuleReturn

[]; + modules?: BuildModuleReturn[]; name: P; }): BuildPluginReturn { const hono = new OpenAPIHono(); diff --git a/packages/vitnode/src/api/modules/admin/admin.module.ts b/packages/vitnode/src/api/modules/admin/admin.module.ts index ddc365ca4..8f46e09ef 100644 --- a/packages/vitnode/src/api/modules/admin/admin.module.ts +++ b/packages/vitnode/src/api/modules/admin/admin.module.ts @@ -7,5 +7,3 @@ export const adminModule = buildModule({ plugin: 'core', routes: [sessionAdminRoute], }); - -export type AdminTypes = typeof adminModule; diff --git a/packages/vitnode/src/api/modules/middleware/middleware.module.ts b/packages/vitnode/src/api/modules/middleware/middleware.module.ts index cb1a71f08..1d12c1bbd 100644 --- a/packages/vitnode/src/api/modules/middleware/middleware.module.ts +++ b/packages/vitnode/src/api/modules/middleware/middleware.module.ts @@ -2,12 +2,8 @@ import { buildModule } from '@/api/lib/module'; import { routeMiddleware } from './route'; -export type MiddlewareTypes = typeof middlewareModule; - export const middlewareModule = buildModule({ plugin: 'core', name: 'middleware', routes: [routeMiddleware], }); - -export type BuildMiddlewareTypes = typeof middlewareModule; diff --git a/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts b/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts index 4761fb0aa..3cafe6474 100644 --- a/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/sign-in.route.ts @@ -30,6 +30,9 @@ export const signInRoute = buildRoute({ }, }, responses: { + 403: { + description: 'Access Denied', + }, 201: { content: { 'application/json': { @@ -41,15 +44,6 @@ export const signInRoute = buildRoute({ }, description: 'User signed in', }, - 403: { - description: 'Access Denied', - 'application/json': { - schema: z.object({ - id: z.string(), - token: z.string(), - }), - }, - }, }, }, handler: async c => { @@ -61,10 +55,10 @@ export const signInRoute = buildRoute({ data.id, ); - return c.json({ id: data.id, token }); + return c.json({ id: data.id, token }, 201); } const { token } = await new SessionModel(c).createSessionByUserId(data.id); - return c.json({ id: data.id, token }); + return c.json({ id: data.id, token }, 201); }, }); diff --git a/packages/vitnode/src/api/modules/users/users.module.ts b/packages/vitnode/src/api/modules/users/users.module.ts index b53322560..f4a718915 100644 --- a/packages/vitnode/src/api/modules/users/users.module.ts +++ b/packages/vitnode/src/api/modules/users/users.module.ts @@ -13,5 +13,3 @@ export const usersModule = buildModule({ routes: [sessionRoute, signInRoute, signOutRoute, signUpRoute, testRoute], modules: [ssoUserModule], }); - -export type UsersTypes = typeof usersModule; diff --git a/packages/vitnode/src/lib/api/get-middleware-api.ts b/packages/vitnode/src/lib/api/get-middleware-api.ts index 7b430da7c..821db5568 100644 --- a/packages/vitnode/src/lib/api/get-middleware-api.ts +++ b/packages/vitnode/src/lib/api/get-middleware-api.ts @@ -1,17 +1,12 @@ -import { MiddlewareTypes } from '@/api/modules/middleware/middleware.module'; - -import { fetcher } from '../fetcher'; +import { middlewareModule } from '@/api/modules/middleware/middleware.module'; +import { fetcher } from '@/lib/fetcher'; export const getMiddlewareApi = async () => { - const client = await fetcher({ - plugin: 'core', + const res = await fetcher(middlewareModule, { + path: '/', + method: 'get', module: 'middleware', - options: { - cache: 'force-cache', - }, }); - const res = await client.index.$get(); - return await res.json(); }; diff --git a/packages/vitnode/src/lib/api/get-session-admin-api.ts b/packages/vitnode/src/lib/api/get-session-admin-api.ts index efe3f554e..4496571aa 100644 --- a/packages/vitnode/src/lib/api/get-session-admin-api.ts +++ b/packages/vitnode/src/lib/api/get-session-admin-api.ts @@ -1,18 +1,15 @@ -import { AdminTypes } from '@/api/modules/admin/admin.module'; +import { adminModule } from '@/api/modules/admin/admin.module'; +import { fetcher } from '@/lib/fetcher'; -import { fetcher } from '../fetcher'; import { redirect } from '../navigation'; export const getSessionAdminApi = async () => { - const client = await fetcher({ - plugin: 'core', + const res = await fetcher(adminModule, { + path: '/session', + method: 'get', module: 'admin', - options: { - cache: 'force-cache', - }, }); - const res = await client.session.$get(); if (res.status !== 200) { await redirect('/admin'); diff --git a/packages/vitnode/src/lib/api/get-session-api.ts b/packages/vitnode/src/lib/api/get-session-api.ts index 3d7a19a8c..27b04b182 100644 --- a/packages/vitnode/src/lib/api/get-session-api.ts +++ b/packages/vitnode/src/lib/api/get-session-api.ts @@ -1,18 +1,13 @@ -import { UsersTypes } from '@/api/modules/users/users.module'; - -import { fetcher } from '../fetcher'; +import { usersModule } from '@/api/modules/users/users.module'; +import { fetcher } from '@/lib/fetcher'; export const getSessionApi = async () => { - const client = await fetcher({ - plugin: 'core', + const res = await fetcher(usersModule, { + path: '/session', + method: 'get', module: 'users', - options: { - cache: 'force-cache', - }, }); - const res = await client.session.$get(); - return await res.json(); }; diff --git a/packages/vitnode/src/lib/fetcher-client.ts b/packages/vitnode/src/lib/fetcher-client.ts deleted file mode 100644 index 487b9aa51..000000000 --- a/packages/vitnode/src/lib/fetcher-client.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ModuleApi } from '@/api/lib/module'; -import { Env, Schema } from 'hono'; -import { hc } from 'hono/client'; -import { UnionToIntersection } from 'hono/utils/types'; - -import { CONFIG } from './config'; -import { Client } from './fetcher'; - -export function fetcherClient< - T extends ModuleApi, ->({ - plugin, - module, - options, -}: { - module: T['name']; - options?: Omit; - plugin: T['plugin']; -}): UnionToIntersection> { - const url = new URL(`/api/${plugin}/${module}`, CONFIG.backend.origin); - - const client = hc(url.href, { - fetch: async (input, requestInit) => { - return fetch(input, { - ...requestInit, - ...options, - }); - }, - }); - - return client as unknown as UnionToIntersection>; -} diff --git a/packages/vitnode/src/lib/fetcher.ts b/packages/vitnode/src/lib/fetcher.ts deleted file mode 100644 index da2eb1625..000000000 --- a/packages/vitnode/src/lib/fetcher.ts +++ /dev/null @@ -1,157 +0,0 @@ -// --- VitNode Fetcher Types & Utilities --- -// These types are optimized for TypeScript performance and readability. -// Avoid deep recursion and keep type-level logic as flat as possible. - -import { ModuleApi } from '@/api/lib/module'; -import { ClientRequest, ClientResponse, hc } from 'hono/client'; -import { HonoBase } from 'hono/hono-base'; -import { Env, ResponseFormat, Schema } from 'hono/types'; -import { StatusCode } from 'hono/utils/http-status'; -import { UnionToIntersection } from 'hono/utils/types'; -import { cookies, headers } from 'next/headers'; - -import { CONFIG } from './config'; -import { cookieFromStringToObject } from './cookie-from-string-to-object'; - -// --- Type Utilities --- - -/** - * Maps an API path string to a nested object structure for type-safe client usage. - * Example: '/foo/bar' -> { foo: { bar: ... } } - * This is intentionally shallow to avoid deep recursion for TS perf. - */ -type PathToChain< - Path extends string, - E extends Schema, - Orig extends string = Path, -> = Path extends `/${infer P}` - ? PathToChain - : Path extends `${infer P}/${infer R}` - ? { [K in P]: PathToChain } - : Record< - Path extends '' ? 'index' : Path, - ClientRequest ? E[Orig] : never> - >; - -/** - * Type-safe client for a Hono API schema. - */ -export type Client = - T extends HonoBase - ? S extends Record - ? K extends string - ? PathToChain - : never - : never - : never; - -/** - * Type alias for extracting the schema from a ModuleApi. - */ -type SchemaOf> = - T extends ModuleApi ? S : never; - -/** - * Extracts available HTTP methods for a given endpoint path. - */ -type MethodsForEndpoint< - E extends Env, - T extends ModuleApi, - P extends keyof SchemaOf, -> = { - [K in Extract[P], `$${string}`>]: K extends `$${infer U}` - ? Lowercase - : never; -}[Extract[P], `$${string}`>]; - -/** - * Type-safe input for a fetcher endpoint method. - */ -export type FetcherInput< - T extends ModuleApi, - P extends keyof SchemaOf, - M extends MethodsForEndpoint, - E extends Env = Env, -> = { - [K in Extract[P], `$${string}`>]: Lowercase< - K extends `$${infer U}` ? U : never - > extends M - ? SchemaOf[P][K] extends { input: infer I } - ? I - : never - : never; -}[Extract[P], `$${string}`>]; - -// --- Fetcher Implementation --- - -/** - * Create a type-safe client for a VitNode API module. - * @param plugin - The plugin name (e.g. 'core') - * @param module - The module name (e.g. 'users') - * @param options - Optional fetch options - */ -export async function fetcher< - T extends ModuleApi, ->({ - plugin, - module, - options, -}: { - module: T['name']; - options?: Omit; - plugin: T['plugin']; -}): Promise>> { - const url = new URL(`/api/${plugin}/${module}`, CONFIG.backend.origin); - const [nextInternalHeaders, cookie] = await Promise.all([ - headers(), - cookies(), - ]); - - const client = hc(url.href, { - fetch: async (input, requestInit) => { - const headers = new Headers({ - 'Content-Type': 'application/json', - Cookie: cookie.toString(), - ['user-agent']: nextInternalHeaders.get('user-agent') ?? 'node', - ['x-forwarded-for']: - nextInternalHeaders.get('x-forwarded-for') ?? '0.0.0.0', - ...options?.headers, - }); - - return await fetch(input, { - ...requestInit, - ...options, - headers, - }); - }, - }); - - return client as unknown as UnionToIntersection>; -} - -/** - * Handles setting cookies from a Hono client response in Next.js server context. - */ -export async function handleSetCookiesFetcher< - T, - U extends number = StatusCode, - F extends ResponseFormat = string, ->(res: ClientResponse) { - await Promise.all( - cookieFromStringToObject(res.headers.getSetCookie()).map(async cookie => { - const key = Object.keys(cookie)[0]; - const value = Object.values(cookie)[0]; - - if (typeof value !== 'string' || typeof key !== 'string') return; - - (await cookies()).set(key, value, { - domain: cookie.Domain, - path: cookie.Path, - expires: new Date(cookie.Expires), - secure: cookie.Secure, - httpOnly: cookie.HttpOnly, - sameSite: cookie.SameSite, - }); - }), - ); -} diff --git a/packages/vitnode/src/lib/fetcher/index.ts b/packages/vitnode/src/lib/fetcher/index.ts new file mode 100644 index 000000000..361a808a4 --- /dev/null +++ b/packages/vitnode/src/lib/fetcher/index.ts @@ -0,0 +1,134 @@ +import { BaseBuildModuleReturn, BuildModuleReturn } from '@/api/lib/module'; +import { Route } from '@/api/lib/route'; +import { cookies, headers } from 'next/headers'; + +import { CONFIG } from '../config'; +import { cookieFromStringToObject } from '../cookie-from-string-to-object'; +import { + FetcherParams, + GetModulePaths, + GetValidPathsForModule, + InferResponseType, +} from '../fetcher/types'; + +const handleSetCookiesFetcher = async (res: Response) => { + await Promise.all( + cookieFromStringToObject(res.headers.getSetCookie()).map(async cookie => { + const key = Object.keys(cookie)[0]; + const value = Object.values(cookie)[0]; + + if (typeof value !== 'string' || typeof key !== 'string') return; + + (await cookies()).set(key, value, { + domain: cookie.Domain, + path: cookie.Path, + expires: new Date(cookie.Expires), + secure: cookie.Secure, + httpOnly: cookie.HttpOnly, + sameSite: cookie.SameSite, + }); + }), + ); +}; + +const buildSearchParams = (query: Record) => { + const searchParams = new URLSearchParams(); + + for (const [k, v] of Object.entries(query)) { + if (v === undefined) { + continue; + } + + if (Array.isArray(v)) { + for (const v2 of v) { + searchParams.append(k, v2); + } + } else { + searchParams.set(k, v); + } + } + + return searchParams; +}; + +export async function fetcher< + M extends string, + Routes extends Route[], + Modules extends BaseBuildModuleReturn[], + ModuleName extends GetModulePaths, + SelectedPath extends GetValidPathsForModule, +>( + { plugin }: BuildModuleReturn, + { + path, + method, + module, + args, + allowSaveCookies = false, + }: FetcherParams & { + allowSaveCookies?: boolean; + options?: Omit; + }, +): Promise> { + let currentPath: string = path; + + // Replace path parameters + if (args && 'params' in args && args.params) { + for (const [key, value] of Object.entries(args.params)) { + currentPath = currentPath.replaceAll(`{${key}}`, String(value)); + } + } + + // Ensure path starts with a slash + const formattedPath = currentPath.startsWith('/') + ? currentPath + : `/${currentPath}`; + + // Construct the base URL + const url = new URL( + `/api/${plugin}/${module}${formattedPath}`, + CONFIG.backend.origin, + ); + + // Add query parameters if they exist + if (args && 'query' in args && args.query) { + const searchParams = buildSearchParams( + args.query as Record, + ); + url.search = searchParams.toString(); + } + + const [nextInternalHeaders, cookie] = await Promise.all([ + headers(), + cookies(), + ]); + + const response = await fetch(url, { + method: method.toUpperCase(), + headers: new Headers({ + 'Content-Type': 'application/json', + Cookie: cookie.toString(), + ['user-agent']: nextInternalHeaders.get('user-agent') ?? 'node', + ['x-forwarded-for']: + nextInternalHeaders.get('x-forwarded-for') ?? '0.0.0.0', + }), + body: args && 'body' in args ? JSON.stringify(args.body) : undefined, + }); + + if ( + response.status >= 200 && + response.status < 300 && + allowSaveCookies && + method !== 'get' + ) { + await handleSetCookiesFetcher(response); + } + + return response as InferResponseType< + M, + Routes, + Modules, + ModuleName, + SelectedPath + >; +} diff --git a/packages/vitnode/src/test/elo.ts b/packages/vitnode/src/lib/fetcher/types.ts similarity index 75% rename from packages/vitnode/src/test/elo.ts rename to packages/vitnode/src/lib/fetcher/types.ts index a928d92c5..7bd6d6bbf 100644 --- a/packages/vitnode/src/test/elo.ts +++ b/packages/vitnode/src/lib/fetcher/types.ts @@ -1,6 +1,5 @@ -import { BaseBuildModuleReturn, BuildModuleReturn } from '@/api/lib/module'; +import { BaseBuildModuleReturn } from '@/api/lib/module'; import { Route } from '@/api/lib/route'; -import { usersModule } from '@/api/modules/users/users.module'; import { RouteConfig } from '@hono/zod-openapi'; import { ResponseFormat } from 'hono/types'; import { StatusCode, SuccessStatusCode } from 'hono/utils/http-status'; @@ -71,7 +70,7 @@ type FindModuleNested< : never : M; -type GetModulePaths< +export type GetModulePaths< MainModule extends string, Modules extends readonly ModuleSpec[], > = @@ -148,7 +147,7 @@ type BuildArgsType = { : K]: InferInputType; }; -type GetValidPathsForModule< +export type GetValidPathsForModule< ModulePath extends string, MainModuleName extends string, MainRoutes extends readonly RouteShape[], @@ -185,7 +184,7 @@ interface BaseFetcherParams< path: SelectedPath; } -type FetcherParams< +export type FetcherParams< M extends string, Routes extends Route[], Modules extends BaseBuildModuleReturn[], @@ -204,7 +203,13 @@ type FetcherParams< > = BaseFetcherParams & (keyof ArgsType extends never ? { args?: undefined } : { args: ArgsType }); -type InferResponseType< +type InferStatusCode = K extends `${infer N extends number}` + ? N + : K extends number + ? K + : never; + +export type InferResponseType< M extends string, Routes extends Route[], Modules extends BaseBuildModuleReturn[], @@ -221,84 +226,16 @@ type InferResponseType< >, > = RouteConfig extends { responses: infer S } ? { - [K in keyof S]: S[K] extends { content: infer C } - ? { - [Fmt in keyof C]: ClientResponse< - C[Fmt] extends { schema: infer S } ? ExtractZodType : never, - K extends `${infer N extends number}` - ? N - : K extends number - ? K - : never, - Fmt extends string ? Fmt : string - >; - }[keyof C] + [K in keyof S]: S[K] extends infer Response + ? Response extends { content: infer C } + ? { + [Fmt in keyof C]: ClientResponse< + C[Fmt] extends { schema: infer S } ? ExtractZodType : never, + InferStatusCode, + Fmt extends string ? Fmt : string + >; + }[keyof C] + : ClientResponse> : never; }[keyof S] : never; - -export async function fetcher< - M extends string, - Routes extends Route[], - Modules extends BaseBuildModuleReturn[], - ModuleName extends GetModulePaths, - SelectedPath extends GetValidPathsForModule, ->( - _moduleInput: BuildModuleReturn, - params: FetcherParams, -): Promise> { - void params; - - await fetch(''); - - return {} as InferResponseType; -} - -// Test cases -void (async () => { - const test = await fetcher(usersModule, { - path: '/sign_in', - method: 'post', - module: 'users', - args: { - body: { - email: 'string', - password: 'string', - }, - }, - }); - - const tes123t = await test.json(); - - const test2 = await fetcher(usersModule, { - path: '/{providerId}', - method: 'post', - module: 'users/sso', - args: { - params: { - providerId: 'github', - }, - }, - }); - - const test3 = await fetcher(usersModule, { - path: '/{providerId}/callback', - method: 'get', - module: 'users/sso', - args: { - params: { - providerId: 'github', - }, - query: { - code: 'some-code', - state: 'some-state', - }, - }, - }); - - const test4 = await fetcher(usersModule, { - path: '/test', - method: 'post', - module: 'users/sso/test', - }); -})(); diff --git a/packages/vitnode/src/test/fetcher.ts b/packages/vitnode/src/test/fetcher.ts deleted file mode 100644 index 32744b95b..000000000 --- a/packages/vitnode/src/test/fetcher.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { BuildModuleReturn } from '@/api/lib/module'; -import { Route } from '@/api/lib/route'; -import { CONFIG } from '@/lib/config'; -import { cookies, headers } from 'next/headers'; - -type FetcherParams< - T extends { name: string; plugin: string; routes: Route[] }, - R extends T['routes'][number], -> = R extends T['routes'][number] - ? Pick & { - input?: string; - module: T['name']; - plugin: T['plugin']; - } - : never; - -export async function fetcher< - T extends BuildModuleReturn, - P extends string = T['plugin'], - M extends string = T['name'], ->({ - path, - method, - plugin, - module, - input, -}: FetcherParams): Promise<{ data: never }> { - const formattedPath = path.startsWith('/') ? path : `/${path}`; - const url = new URL( - `/api/${plugin}/${module}${formattedPath}`, - CONFIG.backend.origin, - ); - const [nextInternalHeaders, cookie] = await Promise.all([ - headers(), - cookies(), - ]); - - const response = await fetch(url, { - method: method.toUpperCase(), - headers: new Headers({ - 'Content-Type': 'application/json', - Cookie: cookie.toString(), - ['user-agent']: nextInternalHeaders.get('user-agent') ?? 'node', - ['x-forwarded-for']: - nextInternalHeaders.get('x-forwarded-for') ?? '0.0.0.0', - }), - }); - - const returnValue = { - clone: response.clone, - }; - - // JSON response - const contentType = response.headers.get('Content-Type') ?? ''; - if (contentType.includes('application/json')) { - return { - data: '', - format: 'json', - ...returnValue, - }; - } - - // const data = await res.json(); - - return { data: '', format: 'text', ...returnValue }; -} diff --git a/packages/vitnode/src/test/test.ts b/packages/vitnode/src/test/test.ts deleted file mode 100644 index a2ff2691a..000000000 --- a/packages/vitnode/src/test/test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { createRoute, OpenAPIHono, z } from '@hono/zod-openapi'; -import { hc } from 'hono/client'; - -import { fetcher } from './testtest'; - -const test1 = new OpenAPIHono().openapi( - createRoute({ - path: '/test123/:test', - method: 'get', - request: { - params: z.object({ - test: z.string(), - }), - }, - responses: { - 201: { - description: 'test', - content: { - 'text/plain': { - schema: z.string(), - }, - }, - }, - 403: { - description: 'test', - content: { - 'text/plain': { - schema: z.string(), - }, - }, - }, - }, - }), - c => { - return c.text('123'); - }, -); - -export const test = new OpenAPIHono() - .openapi( - createRoute({ - path: '/test', - method: 'get', - request: { - query: z.object({ - test: z.string(), - }), - }, - responses: { - 201: { - description: 'test', - content: { - 'application/json': { - schema: z.object({ - test: z.string(), - }), - }, - }, - }, - 403: { - description: 'test', - content: { - 'application/json': { - schema: z.object({ - test: z.string(), - }), - }, - }, - }, - }, - }), - c => { - return c.json({ test: 'test' }); - }, - ) - .route('/something', test1); - -const client = hc('http://localhost:3000/api/core/test'); - -const test12 = await client.test.$get({ - query: { - test: '123', - }, -}); - -const elo = await test12.json(); - -// eslint-disable-next-line no-console -console.log(elo.test); - -const test124 = await client.something.test123[':test'].$get({ - param: { - test: '123', - }, -}); diff --git a/packages/vitnode/src/test/testtest.ts b/packages/vitnode/src/test/testtest.ts deleted file mode 100644 index 0aca8b77d..000000000 --- a/packages/vitnode/src/test/testtest.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable no-console */ -import { BuildModuleReturn } from '@/api/lib/module'; -import { OpenAPIHono } from '@hono/zod-openapi'; -import { UnionToIntersection } from 'hono/utils/types'; - -import type { Client } from './client/types'; - -const createProxy = ( - callback: (opts: { args: unknown[]; path: string[] }) => unknown, - path: string[], -) => { - const proxy = new Proxy(() => {}, { - get(_obj, key) { - if (typeof key !== 'string' || key === 'then') { - return undefined; - } - - return createProxy(callback, [...path, key]); - }, - apply(_1, _2, args) { - return callback({ - path, - args, - }); - }, - }); - - return proxy; -}; - -type UnionFromArrays = T[number] extends (infer U)[] - ? U - : T[number]; - -export function fetcher() { - return createProxy(async function proxyCallback(args) { - const paths = args.path; - - let method = ''; - const lastPartAt0 = paths.at(-1); - if (lastPartAt0 && /^\$/.test(lastPartAt0)) { - const last = paths.pop(); - if (last) { - method = last.replace(/^\$/, ''); - } - } - - const path = paths.join('/'); - - const test = await fetch('http://localhost:3000/' + path); - - if (method === 'ws') { - // TODO: implement ws - } - - console.log('args', args); - console.log('paths', paths); - console.log('method', method); - console.log('path', path); - - return ''; - // }, []) as UnionToIntersection>; - }, []) as UnionToIntersection; -} diff --git a/packages/vitnode/src/views/auth/sign-in/form/form.tsx b/packages/vitnode/src/views/auth/sign-in/form/form.tsx index f7333761e..05703928f 100644 --- a/packages/vitnode/src/views/auth/sign-in/form/form.tsx +++ b/packages/vitnode/src/views/auth/sign-in/form/form.tsx @@ -33,7 +33,11 @@ export const FormSignIn = ({ isAdmin }: { isAdmin?: boolean }) => { { id: 'password', component: props => ( - + ), }, ]} diff --git a/packages/vitnode/src/views/auth/sign-in/form/hooks/mutation-api.ts b/packages/vitnode/src/views/auth/sign-in/form/hooks/mutation-api.ts index b61235b4f..090c24e11 100644 --- a/packages/vitnode/src/views/auth/sign-in/form/hooks/mutation-api.ts +++ b/packages/vitnode/src/views/auth/sign-in/form/hooks/mutation-api.ts @@ -1,29 +1,37 @@ 'use server'; -import { UsersTypes } from '@/api/modules/users/users.module'; -import { fetcher, FetcherInput, handleSetCookiesFetcher } from '@/lib/fetcher'; +import { usersModule } from '@/api/modules/users/users.module'; +import { fetcher } from '@/lib/fetcher'; import { redirect } from '@/lib/navigation'; import { revalidatePath } from 'next/cache'; +import { z } from 'zod'; + +import { createSignInFormSchema } from './use-form'; export const mutationApi = async ( - input: FetcherInput, + input: z.infer> & { + isAdmin?: boolean; + }, ) => { - const res = await fetcher({ - plugin: 'core', + const res = await fetcher(usersModule, { + path: '/sign_in', + method: 'post', module: 'users', + allowSaveCookies: true, + args: { + body: input, + }, }); - const data = await res.sign_in.$post(input); - if (data.status === 403) { + if (res.status === 403) { return { message: 'access_denied' } as const; } - if (data.status !== 200) { + if (res.status !== 201) { return { message: 'Internal Server Error' } as const; } - await handleSetCookiesFetcher(data); - if (input.json.isAdmin) { + if (input.isAdmin) { revalidatePath('/[locale]/admin', 'layout'); await redirect('/admin/core'); diff --git a/packages/vitnode/src/views/auth/sign-in/form/hooks/use-form.ts b/packages/vitnode/src/views/auth/sign-in/form/hooks/use-form.ts index 7fbeea385..3a819b480 100644 --- a/packages/vitnode/src/views/auth/sign-in/form/hooks/use-form.ts +++ b/packages/vitnode/src/views/auth/sign-in/form/hooks/use-form.ts @@ -5,23 +5,27 @@ import { z } from 'zod'; import { mutationApi } from './mutation-api'; -export const useFormSignIn = ({ isAdmin }: { isAdmin?: boolean }) => { - const [error, setError] = React.useState<'' | 'access_denied'>(''); - const t = useTranslations('core.auth.sign_in'); - const tErrors = useTranslations('core.global.errors'); - const formSchema = z.object({ +export const createSignInFormSchema = (t: ReturnType) => + z.object({ email: z .string() .email({ message: t('email.invalid') }) .default(''), - password: z.string().min(1).default(''), + password: z + .string() + .min(1, { message: t('password.required') }) + .default(''), }); +export const useFormSignIn = ({ isAdmin }: { isAdmin?: boolean }) => { + const [error, setError] = React.useState<'' | 'access_denied'>(''); + const t = useTranslations<'core.auth.sign_in'>('core.auth.sign_in'); + const tErrors = useTranslations('core.global.errors'); + const formSchema = createSignInFormSchema(t); + const onSubmit = async (values: z.infer) => { setError(''); - const mutation = await mutationApi({ - json: { ...values, isAdmin }, - }); + const mutation = await mutationApi({ ...values, isAdmin }); if (!mutation?.message) return; if (mutation?.message !== 'Internal Server Error') { diff --git a/packages/vitnode/src/views/auth/sign-in/sign-in-view.tsx b/packages/vitnode/src/views/auth/sign-in/sign-in-view.tsx index 8a791020d..64f7d125b 100644 --- a/packages/vitnode/src/views/auth/sign-in/sign-in-view.tsx +++ b/packages/vitnode/src/views/auth/sign-in/sign-in-view.tsx @@ -1,9 +1,5 @@ -import { UsersTypes } from '@/api/modules/users/users.module'; import { Card, CardDescription } from '@/components/ui/card'; import { Link } from '@/lib/navigation'; -import { fetcher as fetcherTest } from '@/test/fetcher'; -import { test } from '@/test/test'; -import { fetcher } from '@/test/testtest'; import { getTranslations } from 'next-intl/server'; import { Metadata } from 'next/dist/types'; import React from 'react'; @@ -11,24 +7,6 @@ import React from 'react'; import { SSOButtons, SSOButtonsSkeleton } from '../sso/buttons/sso-buttons'; import { FormSignIn } from './form/form'; -const getData = async () => { - const test123 = fetcher(); - const test12312 = await fetcherTest({ - path: '/session', - method: 'get', - plugin: 'core', - module: 'users', - }); - - const data = await test123.something.test123[':test'].$get({ - param: { - test: 'test', - }, - }); - - console.log('data', data); -}; - export const generateMetadataSignInView = async ( locale: string, ): Promise => { @@ -42,7 +20,6 @@ export const generateMetadataSignInView = async ( export const SignInView = async () => { const t = await getTranslations('core.auth.sign_in'); const tGlobal = await getTranslations('core.global'); - await getData(); return (

diff --git a/packages/vitnode/src/views/auth/sign-up/form/hooks/mutation-api.ts b/packages/vitnode/src/views/auth/sign-up/form/hooks/mutation-api.ts index ddf6ba028..52ae0ba2b 100644 --- a/packages/vitnode/src/views/auth/sign-up/form/hooks/mutation-api.ts +++ b/packages/vitnode/src/views/auth/sign-up/form/hooks/mutation-api.ts @@ -1,18 +1,24 @@ 'use server'; -import { UsersTypes } from '@/api/modules/users/users.module'; -import { fetcher, FetcherInput } from '@/lib/fetcher'; +import { usersModule } from '@/api/modules/users/users.module'; +import { fetcher } from '@/lib/fetcher'; +import { z } from 'zod'; + +import { buildSignUpFormSchema } from './use-form'; export const mutationApi = async ( - input: FetcherInput, + input: z.infer>, ) => { - const res = await fetcher({ - plugin: 'core', + const res = await fetcher(usersModule, { + path: '/sign_up', + method: 'post', module: 'users', + args: { + body: input, + }, }); - const data = await res.sign_up.$post(input); - if (data.status !== 200) { - return { message: await data.text() }; + if (res.status !== 200) { + return { message: await res.text() }; } }; diff --git a/packages/vitnode/src/views/auth/sign-up/form/hooks/use-form.ts b/packages/vitnode/src/views/auth/sign-up/form/hooks/use-form.ts index 5c5cc8536..cf540397d 100644 --- a/packages/vitnode/src/views/auth/sign-up/form/hooks/use-form.ts +++ b/packages/vitnode/src/views/auth/sign-up/form/hooks/use-form.ts @@ -5,11 +5,16 @@ import { z } from 'zod'; import { mutationApi } from './mutation-api'; -export const useFormSignUp = () => { - const t = useTranslations('core.auth.sign_up'); - const tError = useTranslations('core.global.errors'); +export const buildSignUpFormSchema = ({ + t, + tError, +}: { + t: ReturnType>; + tError: ReturnType>; +}) => { const invalidPassword = t('password.invalid'); - const formSchema = z.object({ + + return z.object({ name: z .string({ message: tError('field_required'), @@ -33,14 +38,18 @@ export const useFormSignUp = () => { terms: z.boolean().refine(value => value, t('terms.required')), newsletter: z.boolean().optional(), }); +}; + +export const useFormSignUp = () => { + const t = useTranslations('core.auth.sign_up'); + const tError = useTranslations('core.global.errors'); + const formSchema = buildSignUpFormSchema({ tError, t }); const onSubmit = async ( values: z.infer, form: UseFormReturn>, ) => { - const mutation = await mutationApi({ - json: values, - }); + const mutation = await mutationApi(values); if (!mutation?.message) { toast('Event has been created.'); diff --git a/packages/vitnode/src/views/auth/sso/buttons/mutation-api.ts b/packages/vitnode/src/views/auth/sso/buttons/mutation-api.ts index 3ecf3e367..8543b2c50 100644 --- a/packages/vitnode/src/views/auth/sso/buttons/mutation-api.ts +++ b/packages/vitnode/src/views/auth/sso/buttons/mutation-api.ts @@ -1,20 +1,22 @@ 'use server'; -import { UsersTypes } from '@/api/modules/users/users.module'; -import { fetcher, handleSetCookiesFetcher } from '@/lib/fetcher'; +import { usersModule } from '@/api/modules/users/users.module'; +import { fetcher } from '@/lib/fetcher'; import { redirect } from '@/lib/navigation'; export const mutationApi = async (providerId: string) => { - const client = await fetcher({ - plugin: 'core', - module: 'users', + const res = await fetcher(usersModule, { + path: '/{providerId}', + method: 'post', + module: 'users/sso', + args: { + params: { + providerId, + }, + }, + allowSaveCookies: true, }); - const res = await client.sso[':providerId'].$post({ - param: { providerId }, - }); - await handleSetCookiesFetcher(res); - if (res.status !== 200) { return { message: 'Something is wrong' }; } diff --git a/packages/vitnode/src/views/auth/sso/callback/client/mutation-api.ts b/packages/vitnode/src/views/auth/sso/callback/client/mutation-api.ts index b3c8db8c9..f23c1aa84 100644 --- a/packages/vitnode/src/views/auth/sso/callback/client/mutation-api.ts +++ b/packages/vitnode/src/views/auth/sso/callback/client/mutation-api.ts @@ -1,7 +1,7 @@ 'use server'; -import { UsersTypes } from '@/api/modules/users/users.module'; -import { fetcher, handleSetCookiesFetcher } from '@/lib/fetcher'; +import { usersModule } from '@/api/modules/users/users.module'; +import { fetcher } from '@/lib/fetcher'; import { revalidatePath } from 'next/cache'; export const mutationApi = async ({ @@ -13,19 +13,21 @@ export const mutationApi = async ({ providerId: string; state: string; }) => { - const client = await fetcher({ - plugin: 'core', - module: 'users', - }); - - const res = await client.sso[':providerId'].callback.$get({ - param: { providerId }, - query: { - code, - state, + const res = await fetcher(usersModule, { + path: '/{providerId}/callback', + method: 'get', + module: 'users/sso', + allowSaveCookies: true, + args: { + params: { + providerId, + }, + query: { + code, + state, + }, }, }); - await handleSetCookiesFetcher(res); if (res.status !== 200) { return { error: 'Something went wrong' }; diff --git a/packages/vitnode/src/views/layouts/theme/header/user/auth/log-out-mutation-api.ts b/packages/vitnode/src/views/layouts/theme/header/user/auth/log-out-mutation-api.ts index f5f4dbf69..e31e1af94 100644 --- a/packages/vitnode/src/views/layouts/theme/header/user/auth/log-out-mutation-api.ts +++ b/packages/vitnode/src/views/layouts/theme/header/user/auth/log-out-mutation-api.ts @@ -1,7 +1,7 @@ 'use server'; -import { UsersTypes } from '@/api/modules/users/users.module'; -import { fetcher, handleSetCookiesFetcher } from '@/lib/fetcher'; +import { usersModule } from '@/api/modules/users/users.module'; +import { fetcher } from '@/lib/fetcher'; import { redirect } from '@/lib/navigation'; import { revalidatePath } from 'next/cache'; @@ -10,17 +10,17 @@ export const logOutMutationApi = async ({ }: { isAdmin?: boolean; }) => { - const res = await fetcher({ - plugin: 'core', + const res = await fetcher(usersModule, { + path: '/sign_out', + method: 'delete', + allowSaveCookies: true, module: 'users', + args: { + body: { isAdmin }, + }, }); - const data = await res.sign_out.$delete({ - json: { isAdmin }, - }); - if (data.status === 200) { - await handleSetCookiesFetcher(data); - + if (res.status === 200) { if (isAdmin) { revalidatePath('/admin/(main)', 'layout'); await redirect('/admin'); diff --git a/plugins/blog/src/modules/categories/test.ts b/plugins/blog/src/modules/categories/test.ts index e0687404c..0be3c861a 100644 --- a/plugins/blog/src/modules/categories/test.ts +++ b/plugins/blog/src/modules/categories/test.ts @@ -1,9 +1,9 @@ -import { fetcher } from 'vitnode/test/elo'; +import { fetcher } from 'vitnode/lib/fetcher'; import { categoriesModule } from './categories.module'; -export const test = () => { - fetcher(categoriesModule, { +export const test = async () => { + await fetcher(categoriesModule, { module: 'categories', path: '/', method: 'get', From 2a957b01ce904127802e1b35c26b9758369a4f09 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Mon, 28 Apr 2025 20:21:58 +0200 Subject: [PATCH 11/11] chore: Clean up --- packages/vitnode/src/api/config.ts | 2 +- .../src/api/modules/users/sso/sso.module.ts | 2 -- .../users/sso/test/routes/test.route.ts | 34 ------------------- .../api/modules/users/sso/test/test.module.ts | 9 ----- packages/vitnode/src/api/plugin.ts | 2 +- packages/vitnode/src/{api => }/lib/plugin.ts | 2 +- packages/vitnode/src/vitnode.config.ts | 2 +- plugins/blog/src/modules/categories/test.ts | 16 --------- plugins/blog/src/plugin.config.ts | 10 +++--- plugins/blog/src/test.ts | 0 10 files changed, 10 insertions(+), 69 deletions(-) delete mode 100644 packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts delete mode 100644 packages/vitnode/src/api/modules/users/sso/test/test.module.ts rename packages/vitnode/src/{api => }/lib/plugin.ts (88%) delete mode 100644 plugins/blog/src/modules/categories/test.ts delete mode 100644 plugins/blog/src/test.ts diff --git a/packages/vitnode/src/api/config.ts b/packages/vitnode/src/api/config.ts index 3aa306427..b72ab08db 100644 --- a/packages/vitnode/src/api/config.ts +++ b/packages/vitnode/src/api/config.ts @@ -6,7 +6,7 @@ import { cors } from 'hono/cors'; import { csrf } from 'hono/csrf'; import { HTTPException } from 'hono/http-exception'; -import { BuildPluginReturn } from './lib/plugin'; +import { BuildPluginReturn } from '../lib/plugin'; import { globalMiddleware } from './middlewares/global/global'; interface CORSOptions { diff --git a/packages/vitnode/src/api/modules/users/sso/sso.module.ts b/packages/vitnode/src/api/modules/users/sso/sso.module.ts index 51d407331..f80c2f59a 100644 --- a/packages/vitnode/src/api/modules/users/sso/sso.module.ts +++ b/packages/vitnode/src/api/modules/users/sso/sso.module.ts @@ -2,11 +2,9 @@ import { buildModule } from '@/api/lib/module'; import { callbackRoute } from './routes/callback.route'; import { createUrlRoute } from './routes/create-url.route'; -import { testModule } from './test/test.module'; export const ssoUserModule = buildModule({ name: 'sso', plugin: 'core', routes: [callbackRoute, createUrlRoute], - modules: [testModule], }); diff --git a/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts b/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts deleted file mode 100644 index e5ad531b8..000000000 --- a/packages/vitnode/src/api/modules/users/sso/test/routes/test.route.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { buildRoute } from '@/api/lib/route'; -import { z } from 'zod'; - -export const testRoute = buildRoute({ - route: { - method: 'post', - description: 'Test route', - path: '/test', - responses: { - 301: { - description: 'Redirect', - }, - 200: { - content: { - 'text/plain': { - schema: z.string(), - }, - }, - description: 'User', - }, - 201: { - content: { - 'text/plain': { - schema: z.string(), - }, - }, - description: 'User', - }, - }, - }, - handler: c => { - return c.redirect('/', 301); - }, -}); diff --git a/packages/vitnode/src/api/modules/users/sso/test/test.module.ts b/packages/vitnode/src/api/modules/users/sso/test/test.module.ts deleted file mode 100644 index 4e6c8517a..000000000 --- a/packages/vitnode/src/api/modules/users/sso/test/test.module.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { buildModule } from '@/api/lib/module'; - -import { testRoute } from './routes/test.route'; - -export const testModule = buildModule({ - name: 'test', - plugin: 'core', - routes: [testRoute], -}); diff --git a/packages/vitnode/src/api/plugin.ts b/packages/vitnode/src/api/plugin.ts index 3462a181b..7e4fc30b8 100644 --- a/packages/vitnode/src/api/plugin.ts +++ b/packages/vitnode/src/api/plugin.ts @@ -1,4 +1,4 @@ -import { buildPlugin } from './lib/plugin'; +import { buildPlugin } from '../lib/plugin'; import { adminModule } from './modules/admin/admin.module'; import { middlewareModule } from './modules/middleware/middleware.module'; import { usersModule } from './modules/users/users.module'; diff --git a/packages/vitnode/src/api/lib/plugin.ts b/packages/vitnode/src/lib/plugin.ts similarity index 88% rename from packages/vitnode/src/api/lib/plugin.ts rename to packages/vitnode/src/lib/plugin.ts index d288060c6..5c6b4d1e3 100644 --- a/packages/vitnode/src/api/lib/plugin.ts +++ b/packages/vitnode/src/lib/plugin.ts @@ -1,6 +1,6 @@ import { OpenAPIHono } from '@hono/zod-openapi'; -import { BuildModuleReturn } from './module'; +import { BuildModuleReturn } from '../api/lib/module'; export interface BuildPluginReturn { hono: OpenAPIHono; diff --git a/packages/vitnode/src/vitnode.config.ts b/packages/vitnode/src/vitnode.config.ts index 5b3bbd3b0..9f08d3858 100644 --- a/packages/vitnode/src/vitnode.config.ts +++ b/packages/vitnode/src/vitnode.config.ts @@ -1,4 +1,4 @@ -import { BuildPluginReturn } from './api/lib/plugin'; +import { BuildPluginReturn } from './lib/plugin'; export interface VitNodeConfig { debug?: boolean; diff --git a/plugins/blog/src/modules/categories/test.ts b/plugins/blog/src/modules/categories/test.ts deleted file mode 100644 index 0be3c861a..000000000 --- a/plugins/blog/src/modules/categories/test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { fetcher } from 'vitnode/lib/fetcher'; - -import { categoriesModule } from './categories.module'; - -export const test = async () => { - await fetcher(categoriesModule, { - module: 'categories', - path: '/', - method: 'get', - args: { - query: { - test: 'test', - }, - }, - }); -}; diff --git a/plugins/blog/src/plugin.config.ts b/plugins/blog/src/plugin.config.ts index 9145ad005..9dab5187c 100644 --- a/plugins/blog/src/plugin.config.ts +++ b/plugins/blog/src/plugin.config.ts @@ -1,8 +1,10 @@ -import { buildPluginConfig } from 'vitnode/plugin.config'; +import { buildPlugin } from 'vitnode/lib/plugin'; + +import { categoriesModule } from './modules/categories/categories.module'; export const blogPlugin = () => { - return buildPluginConfig({ - id: 'blog', - routes: [], + return buildPlugin({ + name: 'blog', + modules: [categoriesModule], }); }; diff --git a/plugins/blog/src/test.ts b/plugins/blog/src/test.ts deleted file mode 100644 index e69de29bb..000000000