From cda0523628c2a4e07db57db96abe5b50f8b9396e Mon Sep 17 00:00:00 2001 From: Hernan Alvarado Date: Fri, 1 May 2026 20:27:05 +0000 Subject: [PATCH 1/3] feat(core): add experimental Valibot schema validation --- packages/core/package.json | 1 + packages/core/src/@types/config.ts | 20 +- packages/core/src/@types/session.ts | 8 +- packages/core/src/@types/utility.ts | 29 +- .../actions/updateSession/updateSession.ts | 2 +- packages/core/src/createAuth.ts | 11 +- packages/core/src/router/context.ts | 8 +- packages/core/src/session/strategy.ts | 9 +- packages/core/src/shared/identity.ts | 20 +- packages/core/src/shared/logger.ts | 5 +- packages/core/test/types.test-d.ts | 17 +- pnpm-lock.yaml | 269 ++++++++++++++++-- 12 files changed, 332 insertions(+), 67 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 8a63fee..441a059 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -87,6 +87,7 @@ "dependencies": { "@aura-stack/jose": "workspace:*", "@aura-stack/router": "^0.6.0", + "valibot": "^1.3.1", "zod": "catalog:zod-v4" }, "devDependencies": { diff --git a/packages/core/src/@types/config.ts b/packages/core/src/@types/config.ts index 9194497..e76872d 100644 --- a/packages/core/src/@types/config.ts +++ b/packages/core/src/@types/config.ts @@ -1,19 +1,19 @@ import { createJoseInstance } from "@/jose.ts" import { createAuthAPI } from "@/api/createApi.ts" import { createLogEntry } from "@/shared/logger.ts" -import { UserIdentity } from "@/shared/identity.ts" +import { Identities, UserIdentity } from "@/shared/identity.ts" import type { ZodObject } from "zod/v4" import type { BuiltInOAuthProvider } from "@/oauth/index.ts" import type { SerializeOptions } from "@aura-stack/router/cookie" -import type { EditableShape, Prettify, ZodShapeToObject } from "@/@types/utility.ts" +import type { ConfigSchema, FromShapeToObject, Prettify } from "@/@types/utility.ts" import type { OAuthProviderCredentials, OAuthProviderRecord } from "@/@types/oauth.ts" -import type { JWTKey, SessionConfig, SessionStrategy, User, UserShape } from "@/@types/session.ts" +import type { JWTKey, SessionConfig, SessionStrategy, User } from "@/@types/session.ts" /** * Main configuration interface for Aura Auth. * This is the user-facing configuration object passed to `createAuth()`. */ -export interface AuthConfig = EditableShape> { +export interface AuthConfig { /** * OAuth providers available in the authentication and authorization flows. It provides a type-inference * for the OAuth providers that are supported by Aura Stack Auth; alternatively, you can provide a custom @@ -45,7 +45,7 @@ export interface AuthConfig = Editable * ``` */ // @todo: add type inference for built-in providers - oauth: (BuiltInOAuthProvider | OAuthProviderCredentials>)[] + oauth: (BuiltInOAuthProvider | OAuthProviderCredentials>)[] /** * Cookie options defines the configuration for cookies used in Aura Auth. * It includes a prefix for cookie names and flag options to determine @@ -167,7 +167,7 @@ export interface AuthConfig = Editable */ identity?: Partial<{ skipValidation: boolean - schema: ZodObject + schema: ConfigSchema unknownKeys: "passthrough" | "strict" | "strip" }> /** @@ -317,7 +317,7 @@ export interface CredentialsProviderContext { /** * Interface for the credentials provider. */ -export interface CredentialsProvider = EditableShape> { +export interface CredentialsProvider { hash?: (password: string, salt?: string, iterations?: number) => Promise verify?: (password: string, hashedPassword: string) => Promise /** @@ -326,7 +326,7 @@ export interface CredentialsProvider = */ authorize: ( ctx: CredentialsProviderContext - ) => Promise | null> | ZodShapeToObject | null + ) => Promise | null> | FromShapeToObject | null } /** @@ -375,9 +375,7 @@ export interface AuthInstance { /** * Extended context used inside the library with both secure and standard cookie materializations. */ -export type InternalContext> = RouterGlobalContext< - ZodShapeToObject & User -> & { +export type InternalContext = RouterGlobalContext & User> & { cookieConfig: { secure: CookieStoreConfig standard: CookieStoreConfig diff --git a/packages/core/src/@types/session.ts b/packages/core/src/@types/session.ts index cd5e27e..97f95ea 100644 --- a/packages/core/src/@types/session.ts +++ b/packages/core/src/@types/session.ts @@ -1,7 +1,7 @@ import type { infer as Infer } from "zod/v4/core" import type { TypedJWTPayload } from "@aura-stack/jose" -import type { UserIdentity, UserShape } from "@/shared/identity.ts" -import type { DeepPartial, EditableShape, Prettify, ZodShapeToObject } from "@/@types/utility.ts" +import type { Identities, UserIdentity } from "@/shared/identity.ts" +import type { DeepPartial, FromShapeToObject, Prettify } from "@/@types/utility.ts" import type { CookieStoreConfig, IdentityConfig, InternalLogger, JoseInstance } from "@/@types/config.ts" import type { JWK } from "@aura-stack/jose/jose" @@ -226,9 +226,9 @@ export interface SessionStrategy { } /** Inputs for constructing a session strategy implementation for a given identity schema. */ -export interface CreateSessionStrategyOptions> { +export interface CreateSessionStrategyOptions { config?: SessionConfig - jose: JoseInstance & User> + jose: JoseInstance & User> cookies: () => CookieStoreConfig logger?: InternalLogger identity: IdentityConfig diff --git a/packages/core/src/@types/utility.ts b/packages/core/src/@types/utility.ts index f2a9380..0ca765a 100644 --- a/packages/core/src/@types/utility.ts +++ b/packages/core/src/@types/utility.ts @@ -1,6 +1,8 @@ import type { AuthInstance } from "@/@types/config.ts" -import type { Session, User } from "@/@types/session.ts" +import type { Session, User, UserShape } from "@/@types/session.ts" import type { ZodObject, ZodRawShape, ZodTypeAny, infer as Infer } from "zod/v4" +import type { ObjectSchema, BaseSchema, AnySchema as AnyValibotSchema, ObjectEntries, InferOutput } from "valibot" +import { UserShapeValibot } from "@/shared/identity.ts" /** Expands intersection types into a single flat object type for readable editor hints. */ export type Prettify = { [K in keyof T]: T[K] } @@ -18,6 +20,25 @@ export type EditableShape = { [K in keyof T]: T[K] extends ZodObject ? ZodObject> : ZodTypeAny } +export type EditableShapeZod = EditableShape + +type AnyShape = Record + +export type EditableShapeValibot = { + [K in keyof T]: T[K] extends ObjectSchema + ? ObjectSchema, undefined> + : BaseSchema +} + +export type ConfigSchema | EditableShapeValibot> = + T extends EditableShape + ? ZodObject + : T extends EditableShapeValibot + ? ObjectSchema + : never + +export type ValibotShapeToObject = Merge>, User> + /** Merges type `B` over `A`, replacing overlapping keys with `B`. */ export type Merge = Omit & B @@ -27,6 +48,12 @@ export type Merge = Omit & B */ export type ZodShapeToObject = Merge>, User> +export type FromShapeToObject = S extends ZodRawShape + ? ZodShapeToObject + : S extends ObjectEntries + ? ValibotShapeToObject + : never + /** Recursively makes every property required. */ export type DeepRequired = { [K in keyof T]-?: T[K] extends object ? DeepRequired : T[K] diff --git a/packages/core/src/actions/updateSession/updateSession.ts b/packages/core/src/actions/updateSession/updateSession.ts index 850a840..3848274 100644 --- a/packages/core/src/actions/updateSession/updateSession.ts +++ b/packages/core/src/actions/updateSession/updateSession.ts @@ -24,7 +24,7 @@ export const updateSessionAction = (identity: IdentityConfig) => { ctx: ctx.context, headers: ctx.request.headers, session: { - user: ctx.body.user as User, + user: ctx.body?.user as User, expires: ctx.body.expires?.toISOString(), }, }) diff --git a/packages/core/src/createAuth.ts b/packages/core/src/createAuth.ts index 15f43ac..0d91b9c 100644 --- a/packages/core/src/createAuth.ts +++ b/packages/core/src/createAuth.ts @@ -12,9 +12,10 @@ import { csrfTokenAction, updateSessionAction, } from "@/actions/index.ts" -import type { AuthConfig, AuthInstance, EditableShape, ZodShapeToObject, UserShape } from "@/@types/index.ts" +import { Identities } from "@/shared/identity.ts" +import type { AuthConfig, AuthInstance, FromShapeToObject } from "@/@types/index.ts" -const createInternalConfig = >(config?: AuthConfig): RouterConfig => { +const createInternalConfig = (config?: AuthConfig): RouterConfig => { const context = createContext(config) return { basePath: config?.basePath ?? "/auth", @@ -30,7 +31,7 @@ const createInternalConfig = >(config? } } -export const createAuthInstance = >(authConfig: AuthConfig) => { +export const createAuthInstance = (authConfig: AuthConfig) => { const config = createInternalConfig(authConfig) const router = createRouter( [ @@ -75,8 +76,8 @@ export const createAuthInstance = >(au * }] * }) */ -export const createAuth = >(config: AuthConfig) => { - const authInstance = createAuthInstance(config) as unknown as AuthInstance> +export const createAuth = (config: AuthConfig) => { + const authInstance = createAuthInstance(config) as unknown as AuthInstance> authInstance.handlers.ALL = async (request: Request) => { const method = request.method.toUpperCase() const methodHandlers = { diff --git a/packages/core/src/router/context.ts b/packages/core/src/router/context.ts index 8814bb4..6b5d184 100644 --- a/packages/core/src/router/context.ts +++ b/packages/core/src/router/context.ts @@ -1,13 +1,13 @@ import { createJoseInstance } from "@/jose.ts" import { createCookieStore } from "@/cookie.ts" -import { UserIdentity } from "@/shared/identity.ts" +import { Identities, UserIdentity } from "@/shared/identity.ts" import { createProxyLogger } from "@/shared/logger.ts" import { createSessionStrategy } from "@/session/strategy.ts" import { createBuiltInOAuthProviders } from "@/oauth/index.ts" import { getEnv, getEnvArray, getEnvBoolean } from "@/shared/env.ts" -import type { AuthConfig, EditableShape, InternalContext, ZodShapeToObject, UserShape } from "@/@types/index.ts" +import type { AuthConfig, InternalContext, FromShapeToObject } from "@/@types/index.ts" -export const createContext = >(config?: AuthConfig) => { +export const createContext = (config?: AuthConfig) => { const trustedProxyHeadersEnv = getEnv("TRUSTED_PROXY_HEADERS") const useProxyHeaders = trustedProxyHeadersEnv === undefined ? (config?.trustedProxyHeaders ?? false) : getEnvBoolean("TRUSTED_PROXY_HEADERS") @@ -16,7 +16,7 @@ export const createContext = >(config? const cookieOverrides = config?.cookies?.overrides ?? {} const secureCookieStore = createCookieStore(true, cookiePrefix, cookieOverrides, logger) const standardCookieStore = createCookieStore(false, cookiePrefix, cookieOverrides, logger) - const jose = createJoseInstance>(config?.secret, config?.session) + const jose = createJoseInstance>(config?.secret, config?.session) const ctx = { oauth: createBuiltInOAuthProviders(config?.oauth), diff --git a/packages/core/src/session/strategy.ts b/packages/core/src/session/strategy.ts index 0bffb60..6e20061 100644 --- a/packages/core/src/session/strategy.ts +++ b/packages/core/src/session/strategy.ts @@ -1,15 +1,16 @@ import { AuthInvalidConfigurationError } from "@/shared/errors.ts" import { createStatelessStrategy } from "@/session/stateless.ts" -import type { CreateSessionStrategyOptions, SessionStrategy, User, UserShape } from "@/@types/session.ts" -import { EditableShape, ZodShapeToObject } from "@/@types/utility.ts" +import type { CreateSessionStrategyOptions, SessionStrategy, User } from "@/@types/session.ts" +import type { FromShapeToObject } from "@/@types/utility.ts" +import type { Identities } from "@/shared/identity.ts" -export const createSessionStrategy = >({ +export const createSessionStrategy = ({ config, jose, cookies, logger, identity, -}: CreateSessionStrategyOptions): SessionStrategy & User> => { +}: CreateSessionStrategyOptions): SessionStrategy & User> => { const strategy = config?.strategy ?? "jwt" switch (strategy) { diff --git a/packages/core/src/shared/identity.ts b/packages/core/src/shared/identity.ts index 838f366..77ac943 100644 --- a/packages/core/src/shared/identity.ts +++ b/packages/core/src/shared/identity.ts @@ -1,5 +1,6 @@ import { email, string, z } from "zod/v4" -import type { EditableShape } from "@/@types/utility.ts" +import type { EditableShape, EditableShapeValibot } from "@/@types/utility.ts" +import * as valibot from "valibot" export type { InferUser, @@ -18,6 +19,21 @@ export const UserIdentity = z.object({ email: email().nullable().optional(), }) +export const UserIdentityValibot = valibot.object({ + sub: valibot.string(), + name: valibot.optional(valibot.nullable(valibot.string())), + image: valibot.optional(valibot.nullable(valibot.string())), + email: valibot.optional(valibot.nullable(valibot.pipe(valibot.string(), valibot.email()))), +}) + export type UserShape = (typeof UserIdentity)["shape"] +export type UserShapeValibot = typeof UserIdentityValibot.entries + +export type Identities = EditableShape | EditableShapeValibot -export const createIdentity = >(shape: S) => z.object(shape) +export const createIdentity = | EditableShapeValibot>(shape: S) => { + if (typeof shape === "object" && shape !== null && Symbol.for("valibot") in shape) { + return shape + } + return z.object(shape) +} diff --git a/packages/core/src/shared/logger.ts b/packages/core/src/shared/logger.ts index 9b05281..d506764 100644 --- a/packages/core/src/shared/logger.ts +++ b/packages/core/src/shared/logger.ts @@ -1,5 +1,6 @@ import { getEnv, getEnvBoolean } from "@/shared/env.ts" -import type { AuthConfig, EditableShape, InternalLogger, Logger, LogLevel, SyslogOptions, UserShape } from "@/@types/index.ts" +import type { AuthConfig, InternalLogger, Logger, LogLevel, SyslogOptions } from "@/@types/index.ts" +import { Identities } from "./identity.ts" /** * Log message definitions organized by category. @@ -388,7 +389,7 @@ export const createLogger = (logger?: Required): InternalLogger | undefi * Creates the logger instance based on the provided configuration and environment variables. * Priority: config.logger, LOG_LEVEL env, DEBUG env and defaults to undefined if logging is not enabled. */ -export const createProxyLogger = >(config?: AuthConfig) => { +export const createProxyLogger = (config?: AuthConfig) => { const level = getEnv("LOG_LEVEL") const debug = getEnvBoolean("DEBUG") if (typeof config?.logger === "object") { diff --git a/packages/core/test/types.test-d.ts b/packages/core/test/types.test-d.ts index 9c7137e..dc3af98 100644 --- a/packages/core/test/types.test-d.ts +++ b/packages/core/test/types.test-d.ts @@ -1,7 +1,7 @@ import { describe, expectTypeOf } from "vitest" import { z, ZodOptional, ZodString } from "zod/v4" import { createAuth } from "@/createAuth.ts" -import { UserIdentity } from "@/shared/identity.ts" +import { Identities, UserIdentity, UserShapeValibot } from "@/shared/identity.ts" import { github, type GitHubProfile } from "@/oauth/github.ts" import type { GetSessionAPIOptions, @@ -13,25 +13,27 @@ import type { } from "@/@types/index.ts" import type { AuthConfig, AuthInstance, User } from "@/index.ts" import type { OAuthProviderCredentials } from "@/@types/oauth.ts" -import type { EditableShape, InferSession, InferUser, ZodShapeToObject } from "@/@types/utility.ts" +import type { FromShapeToObject, InferSession, InferUser, ValibotShapeToObject, ZodShapeToObject } from "@/@types/utility.ts" import type { JWTHeaderParameters, JWTVerifyOptions, Prettify, TypedJWTPayload } from "@aura-stack/jose" +type Shapes = ZodShapeToObject | ValibotShapeToObject + describe("createAuth", () => { expectTypeOf(createAuth).toEqualTypeOf< - >(config: AuthConfig) => AuthInstance> + (config: AuthConfig) => AuthInstance> >() expectTypeOf(createAuth({ oauth: [] }).api.getSession).toEqualTypeOf< - (options: GetSessionAPIOptions) => Promise>> + (options: GetSessionAPIOptions) => Promise> >() expectTypeOf(createAuth({ oauth: [] }).api.updateSession).toEqualTypeOf< - (options: UpdateSessionAPIOptions) => Promise>> + (options: UpdateSessionAPIOptions) => Promise> >() expectTypeOf(createAuth({ oauth: [] }).jose.signJWS).toEqualTypeOf< - (payload: TypedJWTPayload>, options?: JWTHeaderParameters) => Promise + (payload: TypedJWTPayload>, options?: JWTHeaderParameters) => Promise >() expectTypeOf(createAuth({ oauth: [] }).jose.verifyJWS).toEqualTypeOf< - (token: string, options?: JWTVerifyOptions) => Promise>> + (token: string, options?: JWTVerifyOptions) => Promise> >() expectTypeOf( @@ -76,7 +78,6 @@ describe("createAuth", () => { ) => Promise>> >() expectTypeOf>>().toEqualTypeOf() - expectTypeOf>>().toEqualTypeOf>() expectTypeOf }>>>>().toEqualTypeOf< Prettify >() diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb5313e..d7047dd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -358,7 +358,7 @@ importers: version: 0.563.0(vue@3.5.30(typescript@5.9.3)) nuxt: specifier: ^4.4.2 - version: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2) + version: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2) reka-ui: specifier: ^2.7.0 version: 2.9.2(vue@3.5.30(typescript@5.9.3)) @@ -495,7 +495,7 @@ importers: version: 0.561.0(react@19.2.4) nitro: specifier: npm:nitro-nightly@latest - version: nitro-nightly@3.0.1-20260415-080922-45e20aaa(chokidar@5.0.0)(dotenv@17.3.1)(giget@3.1.2)(ioredis@5.10.0)(jiti@2.6.1)(lru-cache@11.2.7)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)) + version: nitro-nightly@3.0.1-20260501-155839-674070e0(chokidar@5.0.0)(dotenv@17.3.1)(giget@3.1.2)(ioredis@5.10.0)(jiti@2.6.1)(lru-cache@11.2.7)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)) react: specifier: catalog:react version: 19.2.4 @@ -586,7 +586,7 @@ importers: version: 1.2.4(@types/react@19.2.14)(react@19.2.4) '@vercel/analytics': specifier: ^2.0.1 - version: 2.0.1(next@16.1.7(@babel/core@7.29.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(react@19.2.4)(vue-router@4.6.4(vue@3.5.30(typescript@5.9.3)))(vue@3.5.30(typescript@5.9.3)) + version: 2.0.1(next@16.1.7(@babel/core@7.29.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(react@19.2.4)(vue-router@4.6.4(vue@3.5.30(typescript@5.9.3)))(vue@3.5.30(typescript@5.9.3)) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -663,6 +663,9 @@ importers: '@aura-stack/router': specifier: ^0.6.0 version: 0.6.0 + valibot: + specifier: ^1.3.1 + version: 1.3.1(typescript@5.9.3) zod: specifier: catalog:zod-v4 version: 4.3.5 @@ -1309,12 +1312,18 @@ packages: '@emmetio/stream-reader@2.2.0': resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==} + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + '@emnapi/core@1.9.0': resolution: {integrity: sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==} '@emnapi/core@1.9.2': resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + '@emnapi/runtime@1.9.0': resolution: {integrity: sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==} @@ -1953,6 +1962,12 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 + '@napi-rs/wasm-runtime@1.1.4': + resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@next/env@16.1.7': resolution: {integrity: sha512-rJJbIdJB/RQr2F1nylZr/PJzamvNNhfr3brdKP6s/GW850jbtR70QlSfFselvIBbcPUOlQwBakexjFzqLzF6pg==} @@ -2367,6 +2382,9 @@ packages: '@oxc-project/types@0.124.0': resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==} + '@oxc-project/types@0.128.0': + resolution: {integrity: sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==} + '@oxc-transform/binding-android-arm-eabi@0.117.0': resolution: {integrity: sha512-17giX7h5VR9Eodru4OoSCFdgwLFIaUxeEn8JWe0vMZrAuRbT9NiDTy5dXdbGQBoO8aXPkbGS38FGlvbi31aujw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3279,89 +3297,178 @@ packages: cpu: [arm64] os: [android] + '@rolldown/binding-android-arm64@1.0.0-rc.18': + resolution: {integrity: sha512-lIDyUAfD7U3+BWKzdxMbJcsYHuqXqmGz40aeRqvuAm3y5TkJSYTBW2RDrn65DJFPQqVjUAUqq5uz8urzQ8aBdQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@rolldown/binding-darwin-arm64@1.0.0-rc.15': resolution: {integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@rolldown/binding-darwin-arm64@1.0.0-rc.18': + resolution: {integrity: sha512-apJq2ktnGp27nSInMR5Vcj8kY6xJzDAvfdIFlpDcAK/w4cDO58qVoi1YQsES/SKiFNge/6e4CUzgjfHduYqWpQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-rc.15': resolution: {integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-rc.18': + resolution: {integrity: sha512-5Ofot8xbs+pxRHJqm9/9N/4sTQOvdrwEsmPE9pdLEEoAbdZtG6F2LMDfO1sp6ZAtXJuJV/21ew2srq3W8NXB5g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@rolldown/binding-freebsd-x64@1.0.0-rc.15': resolution: {integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@rolldown/binding-freebsd-x64@1.0.0-rc.18': + resolution: {integrity: sha512-7h8eeOTT1eyqJyx64BFCnWZpNm486hGWt2sqeLLgDxA0xI1oGZ9H7gK1S85uNGmBhkdPwa/6reTxfFFKvIsebw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': resolution: {integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.18': + resolution: {integrity: sha512-eRcm/HVt9U/JFu5RKAEKwGQYtDCKWLiaH6wOnsSEp6NMBb/3Os8LgHZlNyzMpFVNmiiMFlfb2zEnebfzJrHFmg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': resolution: {integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.18': + resolution: {integrity: sha512-SOrT/cT4ukTmgnrEz/Hg3m7LBnuCLW9psDeMKrimRWY4I8DmnO7Lco8W2vtqPmMkbVu8iJ+g4GFLVLLOVjJ9DQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': resolution: {integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.18': + resolution: {integrity: sha512-QWjdxN1HJCpBTAcZ5N5F7wju3gVPzRzSpmGzx7na0c/1qpN9CFil+xt+l9lV/1M6/gqHSNXCiqPfwhVJPeLnug==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': resolution: {integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.18': + resolution: {integrity: sha512-ugCOyj7a4d9h3q9B+wXmf6g3a68UsjGh6dob5DHevHGMwDUbhsYNbSPxJsENcIttJZ9jv7qGM2UesLw5jqIhdg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': resolution: {integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.18': + resolution: {integrity: sha512-kKWRhbsotpXkGbcd5dllUWg5gEXcDAa8u5YnP9AV5DYNbvJHGzzuwv7dpmhc8NqKMJldl0a+x76IHbspEpEmdA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': resolution: {integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.18': + resolution: {integrity: sha512-uCo8ElcCIAMyYAZyuIZ81oFkhTSIllNvUCHCAlbhlN4ji3uC28h7IIdlXyIvGO7HsuqnV9p3rD/bpH7XhIyhRw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': resolution: {integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + '@rolldown/binding-linux-x64-musl@1.0.0-rc.18': + resolution: {integrity: sha512-XNOQZtuE6yUIvx4rwGemwh8kpL1xvU41FXy/s9K7T/3JVcqGzo3NfKM2HrbrGgfPYGFW42f07Wk++aOC6B9NWA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': resolution: {integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@rolldown/binding-openharmony-arm64@1.0.0-rc.18': + resolution: {integrity: sha512-tSn/kzrfa7tNOXr7sEacDBN4YsIqTyLqh45IO0nHDwtpKIDNDJr+VFojt+4klSpChxB29JLyduSsE0MKEwa65A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': resolution: {integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==} engines: {node: '>=14.0.0'} cpu: [wasm32] + '@rolldown/binding-wasm32-wasi@1.0.0-rc.18': + resolution: {integrity: sha512-+J9YGmc+czgqlhYmwun3S3O0FIZhsH8ep2456xwjAdIOmuJxM7xz4P4PtrxU+Bz17a/5bqPA8o3HAAoX0teUdg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': resolution: {integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.18': + resolution: {integrity: sha512-zsu47DgU0FQzSwi6sU9dZoEdUv7pc1AptSEz/Z8HBg54sV0Pbs3N0+CrIbTsgiu6EyoaNN9CHboqbLaz9lhOyQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': resolution: {integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.18': + resolution: {integrity: sha512-7H+3yqGgmnlDTRRhw/xpYY9J1kf4GC681nVc4GqKhExZTDrVVrV2tsOR9kso0fvgBdcTCcQShx4SLLoHgaLwhg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/pluginutils@1.0.0-beta.40': resolution: {integrity: sha512-s3GeJKSQOwBlzdUrj4ISjJj5SfSh+aqn0wjOar4Bx95iV1ETI7F6S/5hLcfAxZ9kXDcyrAkxPlqmd1ZITttf+w==} @@ -3371,6 +3478,9 @@ packages: '@rolldown/pluginutils@1.0.0-rc.15': resolution: {integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==} + '@rolldown/pluginutils@1.0.0-rc.18': + resolution: {integrity: sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==} + '@rolldown/pluginutils@1.0.0-rc.2': resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} @@ -7023,16 +7133,16 @@ packages: nf3@0.3.16: resolution: {integrity: sha512-Gs0xRPpUm2nDkqbi40NJ9g7qDIcjcJzgExiydnq6LAyqhI2jfno8wG3NKTL+IiJsx799UHOb1CnSd4Wg4SG4Pw==} - nitro-nightly@3.0.1-20260415-080922-45e20aaa: - resolution: {integrity: sha512-vsJ1gh15OfW48KArEye63r+NBrG6nIF0Br9qd6OAxf8RODA+fFnyZnsIxPj1p0ecwPLVDQXSETdnbDWWty0pMw==} + nitro-nightly@3.0.1-20260501-155839-674070e0: + resolution: {integrity: sha512-V+zm26pSCrMAaAnv3o7we3dJbnT/XNKMTBJvEaNg7c0tXtne5+0nx9l0X61l3JwDVpRxBCYEb1SuGz3XlHTinw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@vercel/queue': ^0.1.4 + '@vercel/queue': ^0.1.6 dotenv: '*' giget: '*' jiti: ^2.6.1 - rollup: ^4.60.1 + rollup: ^4.60.2 vite: ^7 || ^8 xml2js: ^0.6.2 zephyr-agent: ^0.2.0 @@ -7888,6 +7998,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rolldown@1.0.0-rc.18: + resolution: {integrity: sha512-phmyKBpuBdRYDf4hgyynGAYn/rDDe+iZXKVJ7WX5b1zQzpLkP5oJRPGsfJuHdzPMlyyEO/4sPW6yfSx2gf7lVg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rollup-plugin-visualizer@6.0.11: resolution: {integrity: sha512-TBwVHVY7buHjIKVLqr9scTVFwqZqMXINcCphPwIWKPDCOBIa+jCQfafvbjRJDZgXdq/A996Dy6yGJ/+/NtAXDQ==} engines: {node: '>=18'} @@ -8779,6 +8894,14 @@ packages: typescript: optional: true + valibot@1.3.1: + resolution: {integrity: sha512-sfdRir/QFM0JaF22hqTroPc5xy4DimuGQVKFrzF1YfGwaS1nJot3Y8VqMdLO2Lg27fMzat2yD3pY5PbAYO39Gg==} + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -9879,6 +10002,12 @@ snapshots: '@emmetio/stream-reader@2.2.0': {} + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + '@emnapi/core@1.9.0': dependencies: '@emnapi/wasi-threads': 1.2.0 @@ -9891,6 +10020,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.9.0': dependencies: tslib: 2.8.1 @@ -10400,6 +10534,13 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.1 + optional: true + '@next/env@16.1.7': {} '@next/swc-darwin-arm64@16.1.7': @@ -10565,7 +10706,7 @@ snapshots: transitivePeerDependencies: - magicast - '@nuxt/nitro-server@4.4.2(@babel/core@7.29.0)(db0@0.3.4)(ioredis@5.10.0)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(rolldown@1.0.0-rc.15)(typescript@5.9.3)': + '@nuxt/nitro-server@4.4.2(@babel/core@7.29.0)(db0@0.3.4)(ioredis@5.10.0)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(rolldown@1.0.0-rc.18)(typescript@5.9.3)': dependencies: '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) '@nuxt/devalue': 2.0.2 @@ -10583,8 +10724,8 @@ snapshots: impound: 1.1.5 klona: 2.0.6 mocked-exports: 0.1.1 - nitropack: 2.13.1(rolldown@1.0.0-rc.15) - nuxt: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2) + nitropack: 2.13.1(rolldown@1.0.0-rc.18) + nuxt: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2) nypm: 0.6.5 ohash: 2.0.11 pathe: 2.0.3 @@ -10651,7 +10792,7 @@ snapshots: rc9: 3.0.0 std-env: 3.10.0 - '@nuxt/vite-builder@4.4.2(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@types/node@24.12.0)(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.30(typescript@5.9.3))(yaml@2.8.2)': + '@nuxt/vite-builder@4.4.2(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@types/node@24.12.0)(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.30(typescript@5.9.3))(yaml@2.8.2)': dependencies: '@nuxt/kit': 4.4.2(magicast@0.5.2) '@rollup/plugin-replace': 6.0.3(rollup@4.59.0) @@ -10669,7 +10810,7 @@ snapshots: magic-string: 0.30.21 mlly: 1.8.1 mocked-exports: 0.1.1 - nuxt: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2) + nuxt: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2) nypm: 0.6.5 pathe: 2.0.3 pkg-types: 2.3.0 @@ -10685,8 +10826,8 @@ snapshots: vue-bundle-renderer: 2.2.0 optionalDependencies: '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) - rolldown: 1.0.0-rc.15 - rollup-plugin-visualizer: 6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0) + rolldown: 1.0.0-rc.18 + rollup-plugin-visualizer: 6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0) transitivePeerDependencies: - '@biomejs/biome' - '@types/node' @@ -10861,6 +11002,8 @@ snapshots: '@oxc-project/types@0.124.0': {} + '@oxc-project/types@0.128.0': {} + '@oxc-transform/binding-android-arm-eabi@0.117.0': optional: true @@ -11593,39 +11736,75 @@ snapshots: '@rolldown/binding-android-arm64@1.0.0-rc.15': optional: true + '@rolldown/binding-android-arm64@1.0.0-rc.18': + optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.15': optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.18': + optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.15': optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.18': + optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.15': optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.18': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.18': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.18': + optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.18': + optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.18': + optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.18': + optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.18': + optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.18': + optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.18': + optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': dependencies: '@emnapi/core': 1.9.2 @@ -11633,18 +11812,33 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-rc.18': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.18': + optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.18': + optional: true + '@rolldown/pluginutils@1.0.0-beta.40': {} '@rolldown/pluginutils@1.0.0-rc.10': {} '@rolldown/pluginutils@1.0.0-rc.15': {} + '@rolldown/pluginutils@1.0.0-rc.18': {} + '@rolldown/pluginutils@1.0.0-rc.2': {} '@rolldown/pluginutils@1.0.0-rc.3': {} @@ -12604,10 +12798,10 @@ snapshots: d3-selection: 3.0.0 d3-transition: 3.0.1(d3-selection@3.0.0) - '@vercel/analytics@2.0.1(next@16.1.7(@babel/core@7.29.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(react@19.2.4)(vue-router@4.6.4(vue@3.5.30(typescript@5.9.3)))(vue@3.5.30(typescript@5.9.3))': + '@vercel/analytics@2.0.1(next@16.1.7(@babel/core@7.29.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(react@19.2.4)(vue-router@4.6.4(vue@3.5.30(typescript@5.9.3)))(vue@3.5.30(typescript@5.9.3))': optionalDependencies: next: 16.1.7(@babel/core@7.29.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - nuxt: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2) + nuxt: 4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2) react: 19.2.4 vue: 3.5.30(typescript@5.9.3) vue-router: 4.6.4(vue@3.5.30(typescript@5.9.3)) @@ -15963,7 +16157,7 @@ snapshots: nf3@0.3.16: {} - nitro-nightly@3.0.1-20260415-080922-45e20aaa(chokidar@5.0.0)(dotenv@17.3.1)(giget@3.1.2)(ioredis@5.10.0)(jiti@2.6.1)(lru-cache@11.2.7)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)): + nitro-nightly@3.0.1-20260501-155839-674070e0(chokidar@5.0.0)(dotenv@17.3.1)(giget@3.1.2)(ioredis@5.10.0)(jiti@2.6.1)(lru-cache@11.2.7)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: consola: 3.4.2 crossws: 0.4.5(srvx@0.11.15) @@ -15975,7 +16169,7 @@ snapshots: ocache: 0.1.4 ofetch: 2.0.0-alpha.3 ohash: 2.0.11 - rolldown: 1.0.0-rc.15 + rolldown: 1.0.0-rc.18 srvx: 0.11.15 unenv: 2.0.0-rc.24 unstorage: 2.0.0-alpha.7(chokidar@5.0.0)(db0@0.3.4)(ioredis@5.10.0)(lru-cache@11.2.7)(ofetch@2.0.0-alpha.3) @@ -16015,7 +16209,7 @@ snapshots: - sqlite3 - uploadthing - nitropack@2.13.1(rolldown@1.0.0-rc.15): + nitropack@2.13.1(rolldown@1.0.0-rc.18): dependencies: '@cloudflare/kv-asset-handler': 0.4.2 '@rollup/plugin-alias': 6.0.0(rollup@4.59.0) @@ -16068,7 +16262,7 @@ snapshots: pretty-bytes: 7.1.0 radix3: 1.1.2 rollup: 4.59.0 - rollup-plugin-visualizer: 6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0) + rollup-plugin-visualizer: 6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0) scule: 1.3.0 semver: 7.7.4 serve-placeholder: 2.0.2 @@ -16169,16 +16363,16 @@ snapshots: dependencies: boolbase: 1.0.0 - nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2): + nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2): dependencies: '@dxup/nuxt': 0.4.0(magicast@0.5.2)(typescript@5.9.3) '@nuxt/cli': 3.34.0(@nuxt/schema@4.4.2)(cac@6.7.14)(magicast@0.5.2) '@nuxt/devtools': 3.2.4(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.30(typescript@5.9.3)) '@nuxt/kit': 4.4.2(magicast@0.5.2) - '@nuxt/nitro-server': 4.4.2(@babel/core@7.29.0)(db0@0.3.4)(ioredis@5.10.0)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(rolldown@1.0.0-rc.15)(typescript@5.9.3) + '@nuxt/nitro-server': 4.4.2(@babel/core@7.29.0)(db0@0.3.4)(ioredis@5.10.0)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(rolldown@1.0.0-rc.18)(typescript@5.9.3) '@nuxt/schema': 4.4.2 '@nuxt/telemetry': 2.7.0(@nuxt/kit@4.4.2(magicast@0.5.2)) - '@nuxt/vite-builder': 4.4.2(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@types/node@24.12.0)(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.30(typescript@5.9.3))(yaml@2.8.2) + '@nuxt/vite-builder': 4.4.2(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@types/node@24.12.0)(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(magicast@0.5.2)(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.30)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.4(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(optionator@0.9.4)(oxlint@1.56.0)(rolldown@1.0.0-rc.18)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.30(typescript@5.9.3))(yaml@2.8.2) '@unhead/vue': 2.1.12(vue@3.5.30(typescript@5.9.3)) '@vue/shared': 3.5.30 c12: 3.3.3(magicast@0.5.2) @@ -17202,14 +17396,35 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.15 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.15 - rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0): + rolldown@1.0.0-rc.18: + dependencies: + '@oxc-project/types': 0.128.0 + '@rolldown/pluginutils': 1.0.0-rc.18 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.18 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.18 + '@rolldown/binding-darwin-x64': 1.0.0-rc.18 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.18 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.18 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.18 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.18 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.18 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.18 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.18 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.18 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.18 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.18 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.18 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.18 + + rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.18)(rollup@4.59.0): dependencies: open: 8.4.2 picomatch: 4.0.3 source-map: 0.7.6 yargs: 17.7.2 optionalDependencies: - rolldown: 1.0.0-rc.15 + rolldown: 1.0.0-rc.18 rollup: 4.59.0 rollup@4.59.0: @@ -18088,6 +18303,10 @@ snapshots: optionalDependencies: typescript: 5.9.3 + valibot@1.3.1(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 + vary@1.1.2: {} vfile-location@5.0.3: From a9cb3ccd31b6bb6774e20f2bb2a27317c79041d9 Mon Sep 17 00:00:00 2001 From: Hernan Alvarado Date: Sat, 2 May 2026 23:19:31 +0000 Subject: [PATCH 2/3] feat(core): add valibot to schema registry --- packages/core/CHANGELOG.md | 2 + packages/core/src/@types/config.ts | 3 +- .../actions/updateSession/updateSession.ts | 8 +- packages/core/src/createAuth.ts | 4 +- packages/core/src/schema-registry.ts | 61 ++-- packages/core/src/shared/assert.ts | 24 ++ packages/core/src/shared/identity.ts | 20 +- packages/core/test/identity.test.ts | 274 ++++++++++++++++++ packages/core/test/types.test-d.ts | 92 +++++- 9 files changed, 459 insertions(+), 29 deletions(-) create mode 100644 packages/core/test/identity.test.ts diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 3a024da..d28abc5 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Added +- Added experimental support for `Valibot` schema validation in `createAuth`; it now supports both Zod and Valibot schemas to extend the default User fields. [#160](https://github.com/aura-stack-ts/auth/pull/160) + - Extended asymmetric cryptography support to accept JWK (JSON Web Key) format keys in addition to `CryptoKeyPair` across JOSE functions exposed by `createAuth.jose`, including the dedicated `signJWS`, `verifyJWS`, `encryptJWE`, `decryptJWE`, `encodeJWT`, and `decodeJWT` functions. [#159](https://github.com/aura-stack-ts/auth/pull/159) - Added support for asymmetric cryptography using `public/private` key pairs via `CryptoKeyPair` across JOSE functions exposed by `createAuth.jose`, including the dedicated `signJWS`, `verifyJWS`, `encryptJWE`, `decryptJWE`, `encodeJWT`, and `decodeJWT` functions. [#157](https://github.com/aura-stack-ts/auth/pull/157) diff --git a/packages/core/src/@types/config.ts b/packages/core/src/@types/config.ts index e76872d..600a485 100644 --- a/packages/core/src/@types/config.ts +++ b/packages/core/src/@types/config.ts @@ -8,6 +8,7 @@ import type { SerializeOptions } from "@aura-stack/router/cookie" import type { ConfigSchema, FromShapeToObject, Prettify } from "@/@types/utility.ts" import type { OAuthProviderCredentials, OAuthProviderRecord } from "@/@types/oauth.ts" import type { JWTKey, SessionConfig, SessionStrategy, User } from "@/@types/session.ts" +import { ObjectSchema } from "valibot" /** * Main configuration interface for Aura Auth. @@ -283,7 +284,7 @@ export interface InternalLogger { * Identity validation settings used when building session strategy and OAuth profile mapping. * Controls the Zod schema and how unknown keys are handled on user objects. */ -export interface IdentityConfig = typeof UserIdentity> { +export interface IdentityConfig | ObjectSchema = typeof UserIdentity> { schema?: Schema skipValidation?: boolean unknownKeys?: "passthrough" | "strict" | "strip" diff --git a/packages/core/src/actions/updateSession/updateSession.ts b/packages/core/src/actions/updateSession/updateSession.ts index 3848274..676c162 100644 --- a/packages/core/src/actions/updateSession/updateSession.ts +++ b/packages/core/src/actions/updateSession/updateSession.ts @@ -3,12 +3,16 @@ import { createEndpoint, createEndpointConfig } from "@aura-stack/router" import { updateSession } from "@/api/updateSession.ts" import type { User } from "@/@types/session.ts" import type { IdentityConfig } from "@/@types/config.ts" +import { UserIdentity } from "@/shared/identity.ts" export const config = (identity: IdentityConfig) => { return createEndpointConfig({ schemas: { body: z.object({ - user: identity.schema?.partial().optional(), + /** + * @todo add support for valibot schemas in the body as well, currently only Zod is supported + */ + user: UserIdentity.partial().optional(), expires: z.coerce.date().optional(), }), }, @@ -25,7 +29,7 @@ export const updateSessionAction = (identity: IdentityConfig) => { headers: ctx.request.headers, session: { user: ctx.body?.user as User, - expires: ctx.body.expires?.toISOString(), + expires: ctx.body?.expires?.toISOString(), }, }) return toResponse() diff --git a/packages/core/src/createAuth.ts b/packages/core/src/createAuth.ts index 0d91b9c..f03183a 100644 --- a/packages/core/src/createAuth.ts +++ b/packages/core/src/createAuth.ts @@ -13,7 +13,7 @@ import { updateSessionAction, } from "@/actions/index.ts" import { Identities } from "@/shared/identity.ts" -import type { AuthConfig, AuthInstance, FromShapeToObject } from "@/@types/index.ts" +import type { AuthConfig, AuthInstance, EditableShape, FromShapeToObject, UserShape } from "@/@types/index.ts" const createInternalConfig = (config?: AuthConfig): RouterConfig => { const context = createContext(config) @@ -76,7 +76,7 @@ export const createAuthInstance = (authConfig: Auth * }] * }) */ -export const createAuth = (config: AuthConfig) => { +export const createAuth = >(config: AuthConfig) => { const authInstance = createAuthInstance(config) as unknown as AuthInstance> authInstance.handlers.ALL = async (request: Request) => { const method = request.method.toUpperCase() diff --git a/packages/core/src/schema-registry.ts b/packages/core/src/schema-registry.ts index 1600598..1f407b2 100644 --- a/packages/core/src/schema-registry.ts +++ b/packages/core/src/schema-registry.ts @@ -1,44 +1,71 @@ +import { isZodSchema } from "@/shared/assert.ts" import { formatZodError } from "@/shared/utils.ts" import { UserIdentity } from "@/shared/identity.ts" -import { infer as Infer, type ZodObject } from "zod/v4" import { AuthValidationError } from "@/shared/errors.ts" +import { strictObject, objectWithRest, transform, pipe, unknown, safeParseAsync, partial, type ObjectSchema } from "valibot" +import type { ZodObject } from "zod/v4" import type { IdentityConfig } from "@/@types/config.ts" -export const stripUnknownKeys = >(schema: T, unknownKeys: "strip" | "passthrough" | "strict") => { +export const stripUnknownKeys = | ObjectSchema>( + schema: T, + unknownKeys: "strip" | "passthrough" | "strict" +): any => { switch (unknownKeys) { case "strip": - return schema.strip() + return isZodSchema(schema) + ? schema.strip() + : pipe( + objectWithRest((schema as ObjectSchema).entries, unknown()), + transform((input) => { + const result: any = {} + for (const key in (schema as ObjectSchema).entries) { + if (key in input) result[key] = input[key] + } + return result + }) + ) case "passthrough": - return schema.loose() + return isZodSchema(schema) + ? schema.loose() + : objectWithRest((schema as ObjectSchema).entries, unknown()) case "strict": - return schema.strict() + return isZodSchema(schema) ? schema.strict() : strictObject((schema as ObjectSchema).entries) + default: + throw new AuthValidationError( + "INVALID_IDENTITY_VALIDATION_FAILED", + `Invalid unknownKeys configuration: ${unknownKeys}. Valid options are: "strip", "passthrough", "strict".` + ) } } -export const createSchemaRegistry = >(config: IdentityConfig) => { +export const createSchemaRegistry = | ObjectSchema>( + config: IdentityConfig +) => { const schema = stripUnknownKeys(config.schema ?? UserIdentity, config.unknownKeys ?? "strip") - const partialSchema = schema.partial() + const partialSchema = isZodSchema(schema) ? schema.partial() : partial(schema) - const parse = async >(data: unknown = {}) => { - const parsed = await schema.safeParseAsync(data) + const parse = async (data: unknown = {}) => { + const isZod = isZodSchema(schema) + const parsed: any = isZod ? await schema.safeParseAsync(data) : await safeParseAsync(schema as any, data) if (!parsed.success) { - const details = JSON.stringify(formatZodError(parsed.error), null, 2) + const details = JSON.stringify(isZod ? formatZodError(parsed.error) : {}, null, 2) throw new AuthValidationError("INVALID_IDENTITY_VALIDATION_FAILED", details, { - cause: parsed.error, + cause: isZod ? parsed.error : undefined, }) } - return parsed.data as T + return isZod ? parsed.data : parsed.output } - const parseAsPartial = async >>(data: unknown = {}) => { - const parsed = await partialSchema.safeParseAsync(data) + const parseAsPartial = async (data: unknown = {}) => { + const isZod = isZodSchema(partialSchema) + const parsed: any = isZod ? await partialSchema.safeParseAsync(data) : await safeParseAsync(partialSchema as any, data) if (!parsed.success) { - const details = JSON.stringify(formatZodError(parsed.error), null, 2) + const details = JSON.stringify(isZod ? formatZodError(parsed.error) : {}, null, 2) throw new AuthValidationError("INVALID_IDENTITY_VALIDATION_FAILED", details, { - cause: parsed.error, + cause: isZod ? parsed.error : undefined, }) } - return parsed.data as T + return isZod ? parsed.data : parsed.output } return { parse, parseAsPartial } diff --git a/packages/core/src/shared/assert.ts b/packages/core/src/shared/assert.ts index c1bbbd4..92e1d19 100644 --- a/packages/core/src/shared/assert.ts +++ b/packages/core/src/shared/assert.ts @@ -9,6 +9,8 @@ import type { SessionConfig, } from "@/@types/index.ts" import type { JWK } from "@aura-stack/jose/jose" +import { BaseSchema } from "valibot" +import { ZodObject, ZodTypeAny } from "zod" export const isFalsy = (value: unknown): boolean => { return value === false || value === 0 || value === "" || value === null || value === undefined || Number.isNaN(value) @@ -173,3 +175,25 @@ export const isJWTPEMFormattedKeyPair = ( export const isJWKFormattedKey = (value: unknown): value is JWK => { return typeof value === "object" && value !== null && "kty" in value && typeof (value as any).kty === "string" } + +export const isValibotSchema = (value: unknown): value is BaseSchema => { + return typeof value === "object" && value !== null && "~run" in value && typeof (value as any)["~run"] === "function" +} + +export const isValibotEntries = (value: unknown): value is Record> => { + return ( + typeof value === "object" && + value !== null && + !Array.isArray(value) && + Object.values(value).length > 0 && // optional but useful + Object.values(value).every(isValibotSchema) + ) +} + +export const isZodSchema = (value: unknown): value is ZodObject => { + return typeof value === "object" && value !== null && "_def" in value +} + +export const isZodEntries = (value: unknown): value is Record => { + return typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every(isZodSchema) +} diff --git a/packages/core/src/shared/identity.ts b/packages/core/src/shared/identity.ts index 77ac943..3a2efea 100644 --- a/packages/core/src/shared/identity.ts +++ b/packages/core/src/shared/identity.ts @@ -1,6 +1,7 @@ -import { email, string, z } from "zod/v4" +import { email, string, z, ZodObject } from "zod/v4" import type { EditableShape, EditableShapeValibot } from "@/@types/utility.ts" import * as valibot from "valibot" +import { isValibotEntries, isValibotSchema } from "./assert.ts" export type { InferUser, @@ -31,9 +32,18 @@ export type UserShapeValibot = typeof UserIdentityValibot.entries export type Identities = EditableShape | EditableShapeValibot -export const createIdentity = | EditableShapeValibot>(shape: S) => { - if (typeof shape === "object" && shape !== null && Symbol.for("valibot") in shape) { - return shape +type ReturnShapeType = + S extends EditableShape + ? z.ZodObject + : S extends EditableShapeValibot + ? valibot.ObjectSchema + : never + +export const createIdentity = | EditableShapeValibot>( + shape: S +): ReturnShapeType => { + if (isValibotEntries(shape)) { + return valibot.object(shape) as unknown as ReturnShapeType } - return z.object(shape) + return z.object(shape) as unknown as ReturnShapeType } diff --git a/packages/core/test/identity.test.ts b/packages/core/test/identity.test.ts new file mode 100644 index 0000000..ee4e998 --- /dev/null +++ b/packages/core/test/identity.test.ts @@ -0,0 +1,274 @@ +import { describe, test, expect, expectTypeOf } from "vitest" +import { createIdentity, InferUser } from "@/shared/identity.ts" +import { z } from "zod/v4" +import * as valibot from "valibot" +import { createAuth } from "@/createAuth.ts" +import { createSchemaRegistry, stripUnknownKeys } from "@/schema-registry.ts" + +describe("createIdentity", () => { + test("should create a Zod schema when passed a Zod shape", () => { + const schema = createIdentity({ + sub: z.string(), + name: z.string().nullable().optional(), + email: z.string().nullable().optional(), + image: z.string().nullable().optional(), + role: z.string(), + }) + + const out = schema.parse({ + sub: "user123", + name: "John Doe", + role: "admin", + }) + + expect(out).toEqual({ + sub: "user123", + name: "John Doe", + role: "admin", + }) + }) + + test("auth instance with Zod schema", () => { + const schema = createIdentity({ + sub: z.string(), + name: z.string().nullable().optional(), + email: z.string().nullable().optional(), + image: z.string().nullable().optional(), + role: z.string(), + }) + + const auth = createAuth({ + oauth: [], + identity: { + schema, + }, + }) + type ExpectedIdentity = z.infer + expectTypeOf().toEqualTypeOf>() + }) + + test("should create a Valibot schema when passed a Valibot shape", () => { + const schema = createIdentity({ + sub: valibot.string(), + name: valibot.optional(valibot.nullable(valibot.string())), + email: valibot.optional(valibot.nullable(valibot.pipe(valibot.string(), valibot.email()))), + image: valibot.optional(valibot.nullable(valibot.string())), + role: valibot.string(), + }) + + const out = valibot.parse(schema, { + sub: "user123", + name: "John Doe", + role: "admin", + }) + + expect(out).toEqual({ + sub: "user123", + name: "John Doe", + role: "admin", + }) + }) + + test("auth instance with Valibot schema", () => { + const schema = createIdentity({ + sub: valibot.string(), + name: valibot.optional(valibot.nullable(valibot.string())), + email: valibot.optional(valibot.nullable(valibot.pipe(valibot.string(), valibot.email()))), + image: valibot.optional(valibot.nullable(valibot.string())), + role: valibot.string(), + }) + + const auth = createAuth({ + oauth: [], + identity: { + schema, + }, + }) + type ExpectedIdentity = valibot.InferOutput + expectTypeOf().toEqualTypeOf>() + }) +}) + +describe("stripUnknownKeys", () => { + const zodSchema = z.object({ + sub: z.string(), + name: z.string().nullable().optional(), + email: z.string().nullable().optional(), + image: z.string().nullable().optional(), + role: z.string(), + }) + + const valibotSchema = valibot.object({ + sub: valibot.string(), + name: valibot.optional(valibot.nullable(valibot.string())), + email: valibot.optional(valibot.nullable(valibot.pipe(valibot.string(), valibot.email()))), + image: valibot.optional(valibot.nullable(valibot.string())), + role: valibot.string(), + }) + + const payload = { + sub: "user123", + name: "John Doe", + role: "admin", + extraKey: "should be stripped", + } + + test("zod schema with 'strip' unknownKeys", () => { + const schema = stripUnknownKeys(zodSchema, "strip") + expect(schema.safeParse(payload)).toMatchObject({ + success: true, + data: { + sub: "user123", + name: "John Doe", + role: "admin", + }, + }) + }) + + test("zod schema with 'passthrough' unknownKeys", () => { + const schema = stripUnknownKeys(zodSchema, "passthrough") + expect(schema.safeParse(payload)).toMatchObject({ + success: true, + data: { + sub: "user123", + name: "John Doe", + role: "admin", + extraKey: "should be stripped", + }, + }) + }) + + test("zod schema with 'strict' unknownKeys", () => { + const schema = stripUnknownKeys(zodSchema, "strict") + expect(schema.safeParse(payload)).toMatchObject({ + success: false, + }) + }) + + test("valibot schema with 'strip' unknownKeys", () => { + const schema = stripUnknownKeys(valibotSchema, "strip") + expect(valibot.safeParse(schema, payload)).toMatchObject({ + success: true, + output: { + sub: "user123", + name: "John Doe", + role: "admin", + }, + }) + }) + + test("valibot schema with 'passthrough' unknownKeys", () => { + const schema = stripUnknownKeys(valibotSchema, "passthrough") + expect(valibot.safeParse(schema, payload)).toMatchObject({ + success: true, + output: { + sub: "user123", + name: "John Doe", + role: "admin", + extraKey: "should be stripped", + }, + }) + }) + + test("valibot schema with 'strict' unknownKeys", () => { + const schema = stripUnknownKeys(valibotSchema, "strict") + expect(valibot.safeParse(schema, payload)).toMatchObject({ + success: false, + }) + }) +}) + +describe("createSchemaRegistry", () => { + const zodSchema = z.object({ + sub: z.string(), + name: z.string().nullable().optional(), + email: z.string().nullable().optional(), + image: z.string().nullable().optional(), + role: z.string(), + }) + + const valibotSchema = valibot.object({ + sub: valibot.string(), + name: valibot.optional(valibot.nullable(valibot.string())), + email: valibot.optional(valibot.nullable(valibot.pipe(valibot.string(), valibot.email()))), + image: valibot.optional(valibot.nullable(valibot.string())), + role: valibot.string(), + }) + + const payload = { + sub: "user123", + name: "John Doe", + role: "admin", + extraKey: "should be stripped", + } + + test("zod schema with 'strip' unknownKeys", async () => { + const { parse } = createSchemaRegistry({ + schema: zodSchema, + unknownKeys: "strip", + }) + const out = await parse(payload) + expect(out).toEqual({ + sub: "user123", + name: "John Doe", + role: "admin", + }) + }) + + test("zod schema with 'passthrough' unknownKeys", async () => { + const { parse } = createSchemaRegistry({ + schema: zodSchema, + unknownKeys: "passthrough", + }) + const out = await parse(payload) + expect(out).toEqual({ + sub: "user123", + name: "John Doe", + role: "admin", + extraKey: "should be stripped", + }) + }) + + test("zod schema with 'strict' unknownKeys", async () => { + const { parse } = createSchemaRegistry({ + schema: zodSchema, + unknownKeys: "strict", + }) + await expect(parse(payload)).rejects.toThrow() + }) + + test("valibot schema with 'strip' unknownKeys", async () => { + const { parse } = createSchemaRegistry({ + schema: valibotSchema, + unknownKeys: "strip", + }) + const out = await parse(payload) + expect(out).toEqual({ + sub: "user123", + name: "John Doe", + role: "admin", + }) + }) + + test("valibot schema with 'passthrough' unknownKeys", async () => { + const { parse } = createSchemaRegistry({ + schema: valibotSchema, + unknownKeys: "passthrough", + }) + const out = await parse(payload) + expect(out).toEqual({ + sub: "user123", + name: "John Doe", + role: "admin", + extraKey: "should be stripped", + }) + }) + + test("valibot schema with 'strict' unknownKeys", async () => { + const { parse } = createSchemaRegistry({ + schema: valibotSchema, + unknownKeys: "strict", + }) + await expect(parse(payload)).rejects.toThrow() + }) +}) diff --git a/packages/core/test/types.test-d.ts b/packages/core/test/types.test-d.ts index dc3af98..42cad22 100644 --- a/packages/core/test/types.test-d.ts +++ b/packages/core/test/types.test-d.ts @@ -1,7 +1,8 @@ import { describe, expectTypeOf } from "vitest" -import { z, ZodOptional, ZodString } from "zod/v4" +import * as valibot from "valibot" import { createAuth } from "@/createAuth.ts" -import { Identities, UserIdentity, UserShapeValibot } from "@/shared/identity.ts" +import { z, ZodOptional, ZodString } from "zod/v4" +import { Identities, UserIdentity, UserIdentityValibot, UserShapeValibot } from "@/shared/identity.ts" import { github, type GitHubProfile } from "@/oauth/github.ts" import type { GetSessionAPIOptions, @@ -59,17 +60,78 @@ describe("createAuth", () => { options?: JWTHeaderParameters ) => Promise >() + expectTypeOf( + createAuth({ + oauth: [], + identity: { schema: valibot.object({ ...UserIdentityValibot.entries, role: valibot.string() }) }, + }).jose.signJWS + ).toEqualTypeOf< + ( + payload: TypedJWTPayload< + Partial< + { + sub: string + role: string + name?: string | null | undefined + image?: string | null | undefined + email?: string | null | undefined + } & { + sub: string + name?: string | null | undefined + image?: string | null | undefined + email?: string | null | undefined + } + > + >, + options?: JWTHeaderParameters + ) => Promise + >() expectTypeOf( createAuth({ oauth: [], identity: { schema: UserIdentity.extend({ role: z.string() }) } }).jose.verifyJWS ).toEqualTypeOf< (token: string, options?: JWTVerifyOptions) => Promise>> >() + expectTypeOf( + createAuth({ + oauth: [], + identity: { schema: valibot.object({ ...UserIdentityValibot.entries, role: valibot.string() }) }, + }).jose.verifyJWS + ).toEqualTypeOf< + ( + token: string, + options?: JWTVerifyOptions + ) => Promise }>>> + >() + expectTypeOf(createAuth({ oauth: [], identity: { schema: UserIdentityValibot } })).toEqualTypeOf< + AuthInstance> + >() + expectTypeOf( + createAuth({ + oauth: [], + identity: { + schema: valibot.object({ + ...UserIdentityValibot.entries, + role: valibot.string(), + }), + }, + }) + ).toEqualTypeOf>() expectTypeOf( createAuth({ oauth: [], identity: { schema: UserIdentity.extend({ role: z.string() }) } }).api.getSession ).toEqualTypeOf< (options: GetSessionAPIOptions) => Promise>> >() + expectTypeOf( + createAuth({ + oauth: [], + identity: { schema: valibot.object({ ...UserIdentityValibot.entries, role: valibot.string() }) }, + }).api.getSession + ).toEqualTypeOf< + ( + options: GetSessionAPIOptions + ) => Promise }>>> + >() expectTypeOf( createAuth({ oauth: [], identity: { schema: UserIdentity.extend({ role: z.string() }) } }).api.updateSession ).toEqualTypeOf< @@ -77,13 +139,39 @@ describe("createAuth", () => { options: UpdateSessionAPIOptions> ) => Promise>> >() + expectTypeOf( + createAuth({ + oauth: [], + identity: { schema: valibot.object({ ...UserIdentityValibot.entries, role: valibot.string() }) }, + }).api.updateSession + ).toEqualTypeOf< + ( + options: UpdateSessionAPIOptions }>> + ) => Promise }>>> + >() + expectTypeOf>>().toEqualTypeOf() expectTypeOf }>>>>().toEqualTypeOf< Prettify >() + expectTypeOf< + InferUser< + ReturnType< + typeof createAuth, undefined> }> + > + > + >().toEqualTypeOf>() + expectTypeOf }>>>>().toEqualTypeOf< Session> >() + expectTypeOf< + InferSession< + ReturnType< + typeof createAuth, undefined> }> + > + > + >().toEqualTypeOf>>() }) describe("OAuth providers", () => { From 054ffcdf787c1e07dc9cb9e30cb9372fbb9033c6 Mon Sep 17 00:00:00 2001 From: Hernan Alvarado Date: Sat, 2 May 2026 23:36:18 +0000 Subject: [PATCH 3/3] chore: apply coderabbit's suggestions --- packages/core/src/actions/signIn/authorization.ts | 3 ++- .../src/actions/updateSession/updateSession.ts | 2 +- packages/core/src/session/stateless.ts | 6 +++--- packages/core/src/shared/assert.ts | 2 +- packages/core/src/shared/identity.ts | 12 ++++++------ packages/core/test/types.test-d.ts | 14 ++++++-------- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/packages/core/src/actions/signIn/authorization.ts b/packages/core/src/actions/signIn/authorization.ts index 57da3fe..dbb7b74 100644 --- a/packages/core/src/actions/signIn/authorization.ts +++ b/packages/core/src/actions/signIn/authorization.ts @@ -4,11 +4,12 @@ import { equals, extractPath, patternToRegex } from "@/shared/utils.ts" import { isRelativeURL, isSameOrigin, isValidURL, isTrustedOrigin } from "@/shared/assert.ts" import type { AuthConfig } from "@/@types/index.ts" import type { GlobalContext } from "@aura-stack/router" +import { Identities } from "@/shared/identity.ts" /** * Resolves trusted origins from config (array or function). */ -export const getTrustedOrigins = async (request: Request, trustedOrigins: AuthConfig["trustedOrigins"]): Promise => { +export const getTrustedOrigins = async (request: Request, trustedOrigins: AuthConfig["trustedOrigins"]): Promise => { if (!trustedOrigins) return [] const raw = typeof trustedOrigins === "function" ? await trustedOrigins(request) : trustedOrigins return Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : [] diff --git a/packages/core/src/actions/updateSession/updateSession.ts b/packages/core/src/actions/updateSession/updateSession.ts index 676c162..c9d2779 100644 --- a/packages/core/src/actions/updateSession/updateSession.ts +++ b/packages/core/src/actions/updateSession/updateSession.ts @@ -5,7 +5,7 @@ import type { User } from "@/@types/session.ts" import type { IdentityConfig } from "@/@types/config.ts" import { UserIdentity } from "@/shared/identity.ts" -export const config = (identity: IdentityConfig) => { +export const config = (_identity: IdentityConfig) => { return createEndpointConfig({ schemas: { body: z.object({ diff --git a/packages/core/src/session/stateless.ts b/packages/core/src/session/stateless.ts index 906db48..467e9f6 100644 --- a/packages/core/src/session/stateless.ts +++ b/packages/core/src/session/stateless.ts @@ -135,13 +135,13 @@ export const createStatelessStrategy = ({ if (!expiresAt) { const userSession = identity.skipValidation ? session.user - : await schema.parse>(session.user) + : await schema.parse(session.user) return { session: { expires: session.expires, user: userSession }, headers } } const newSessionPayload = identity.skipValidation ? session.user - : await schema.parse>(session.user) + : await schema.parse(session.user) const newSession = { user: newSessionPayload, expires: expiresAt.toISOString() } const issuedAt = strategy === "absolute" ? _iat : Math.floor(Date.now() / 1000) @@ -170,7 +170,7 @@ export const createStatelessStrategy = ({ }, }) } - const payload = identity.skipValidation ? session : await schema.parse>(session) + const payload = identity.skipValidation ? session : await schema.parse(session) return jwt.createToken(payload) } diff --git a/packages/core/src/shared/assert.ts b/packages/core/src/shared/assert.ts index 92e1d19..8ee42cd 100644 --- a/packages/core/src/shared/assert.ts +++ b/packages/core/src/shared/assert.ts @@ -190,7 +190,7 @@ export const isValibotEntries = (value: unknown): value is Record { +export const isZodSchema = (value: unknown): value is ZodObject => { return typeof value === "object" && value !== null && "_def" in value } diff --git a/packages/core/src/shared/identity.ts b/packages/core/src/shared/identity.ts index 3a2efea..c5ae770 100644 --- a/packages/core/src/shared/identity.ts +++ b/packages/core/src/shared/identity.ts @@ -1,7 +1,7 @@ -import { email, string, z, ZodObject } from "zod/v4" +import { z } from "zod/v4" import type { EditableShape, EditableShapeValibot } from "@/@types/utility.ts" import * as valibot from "valibot" -import { isValibotEntries, isValibotSchema } from "./assert.ts" +import { isValibotEntries } from "./assert.ts" export type { InferUser, @@ -14,10 +14,10 @@ export type { } from "@/@types/utility.ts" export const UserIdentity = z.object({ - sub: string(), - name: string().nullable().optional(), - image: string().nullable().optional(), - email: email().nullable().optional(), + sub: z.string(), + name: z.string().nullable().optional(), + image: z.string().nullable().optional(), + email: z.string().email().nullable().optional(), }) export const UserIdentityValibot = valibot.object({ diff --git a/packages/core/test/types.test-d.ts b/packages/core/test/types.test-d.ts index 42cad22..c712077 100644 --- a/packages/core/test/types.test-d.ts +++ b/packages/core/test/types.test-d.ts @@ -14,27 +14,25 @@ import type { } from "@/@types/index.ts" import type { AuthConfig, AuthInstance, User } from "@/index.ts" import type { OAuthProviderCredentials } from "@/@types/oauth.ts" -import type { FromShapeToObject, InferSession, InferUser, ValibotShapeToObject, ZodShapeToObject } from "@/@types/utility.ts" +import type { EditableShape, FromShapeToObject, InferSession, InferUser, ValibotShapeToObject, ZodShapeToObject } from "@/@types/utility.ts" import type { JWTHeaderParameters, JWTVerifyOptions, Prettify, TypedJWTPayload } from "@aura-stack/jose" -type Shapes = ZodShapeToObject | ValibotShapeToObject - describe("createAuth", () => { expectTypeOf(createAuth).toEqualTypeOf< - (config: AuthConfig) => AuthInstance> + >(config: AuthConfig) => AuthInstance> >() expectTypeOf(createAuth({ oauth: [] }).api.getSession).toEqualTypeOf< - (options: GetSessionAPIOptions) => Promise> + (options: GetSessionAPIOptions) => Promise>> >() expectTypeOf(createAuth({ oauth: [] }).api.updateSession).toEqualTypeOf< - (options: UpdateSessionAPIOptions) => Promise> + (options: UpdateSessionAPIOptions) => Promise>> >() expectTypeOf(createAuth({ oauth: [] }).jose.signJWS).toEqualTypeOf< - (payload: TypedJWTPayload>, options?: JWTHeaderParameters) => Promise + (payload: TypedJWTPayload>>, options?: JWTHeaderParameters) => Promise >() expectTypeOf(createAuth({ oauth: [] }).jose.verifyJWS).toEqualTypeOf< - (token: string, options?: JWTVerifyOptions) => Promise> + (token: string, options?: JWTVerifyOptions) => Promise>> >() expectTypeOf(