UNPKG

kitcn

Version:

kitcn - React Query integration and CLI tools for Convex

986 lines (985 loc) 71.2 kB
import { AuthConfig, FunctionArgs, FunctionReference, FunctionReturnType } from "convex/server"; import * as solid_js0 from "solid-js"; import { JSX, ParentProps } from "solid-js"; import { DefaultError, QueryCache, QueryClient, QueryFilters, QueryFunction, QueryFunctionContext, QueryKey, SkipToken, SolidMutationOptions, SolidQueryOptions } from "@tanstack/solid-query"; import { AuthTokenFetcher, ConvexClient, ConvexHttpClient } from "convex/browser"; import { z } from "zod"; import * as better_auth0 from "better-auth"; import { BetterAuthClientPlugin, Session, User } from "better-auth"; import { createAuthClient } from "better-auth/solid"; import * as better_auth_api0 from "better-auth/api"; import * as better_auth_plugins_oidc_provider0 from "better-auth/plugins/oidc-provider"; import * as jose from "jose"; import { BetterAuthOptions } from "better-auth/minimal"; //#region src/crpc/types.d.ts /** Symbol key for attaching FunctionReference to options (non-serializable) */ declare const FUNC_REF_SYMBOL: unique symbol; /** Options controlled by convexQuery/convexAction factories */ type ReservedQueryOptions$2 = 'queryKey' | 'queryFn' | 'staleTime'; /** Options controlled by mutation factories */ type ReservedMutationOptions$2 = 'mutationFn'; /** Reserved options controlled by infinite query factories */ type ReservedInfiniteQueryOptions = 'queryKey' | 'queryFn' | 'staleTime' | 'refetchInterval' | 'refetchOnMount' | 'refetchOnReconnect' | 'refetchOnWindowFocus' | 'persister' | 'placeholderData'; /** Metadata for a single Convex function */ type FnMeta$1 = { auth?: 'required' | 'optional'; role?: string; ratelimit?: string; type?: 'query' | 'mutation' | 'action'; limit?: number; [key: string]: unknown; }; /** Metadata for paginated functions (limit is required) */ type PaginatedFnMeta = Omit<FnMeta$1, 'limit'> & { limit: number; }; /** Metadata for all Convex functions by namespace.fnName, with _http for HTTP routes */ type Meta = Record<string, Record<string, FnMeta$1>> & { _http?: Record<string, { path: string; method: string; }>; }; /** Query key structure for Convex queries */ type ConvexQueryKey<T extends FunctionReference<'query'>> = readonly ['convexQuery', string, FunctionArgs<T>]; /** Query key structure for Convex actions */ type ConvexActionKey<T extends FunctionReference<'action'>> = readonly ['convexAction', string, FunctionArgs<T>]; /** Mutation key structure for Convex mutations/actions */ type ConvexMutationKey = ['convexMutation', string]; /** * Meta passed to TanStack Query for auth and subscription control. * Set by convexQuery, read by ConvexQueryClient.queryFn() and subscribeInner(). */ type ConvexQueryMeta = { /** Auth type from generated Convex metadata via getMeta() */authType?: 'required' | 'optional'; /** Skip query silently when unauthenticated (returns null) */ skipUnauth?: boolean; /** Whether to create WebSocket subscription (default: true) */ subscribe?: boolean; }; /** Hook options for Convex queries */ type ConvexQueryHookOptions = { /** Skip query silently when unauthenticated (default: false, calls onQueryUnauthorized) */skipUnauth?: boolean; /** Set to false to fetch once without subscribing (default: true) */ subscribe?: boolean; }; /** Extract input args without cursor/limit (user's filter args only) */ type InfiniteQueryInput<TInput> = Omit<TInput, 'cursor' | 'limit'>; /** Extract item type from PaginationResult<T> */ type ExtractPaginatedItem<TOutput> = TOutput extends { page: (infer T)[]; } ? T : never; /** Metadata for infinite query (extends ConvexQueryMeta) */ type ConvexInfiniteQueryMeta = ConvexQueryMeta & { /** The query function name (serializable for RSC) */queryName: string; /** Query args without cursor/limit (user's filter args only) */ args: Record<string, unknown>; /** Items per page (optional - server uses .paginated() default) */ limit?: number; }; type EmptyObject = Record<string, never>; /** Static query options parameter type (non-hook, for event handlers) */ type StaticQueryOptsParam = { skipUnauth?: boolean; }; /** Check if a type has cursor key (pagination detection) */ type IsPaginated<T> = 'cursor' extends keyof T ? true : false; /** Mutation variables type - undefined when no args required (allows mutateAsync() without args) */ type MutationVariables<T extends FunctionReference<'mutation' | 'action'>> = keyof FunctionArgs<T> extends never ? void : EmptyObject extends FunctionArgs<T> ? FunctionArgs<T> | undefined : FunctionArgs<T>; /** Vanilla mutation - direct .mutate() call without TanStack Query */ type VanillaMutation<T extends FunctionReference<'mutation'>> = { mutate: keyof FunctionArgs<T> extends never ? (args?: EmptyObject) => Promise<FunctionReturnType<T>> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T>) => Promise<FunctionReturnType<T>> : (args: FunctionArgs<T>) => Promise<FunctionReturnType<T>>; }; /** Vanilla action - both .query() and .mutate() for direct calls */ type VanillaAction<T extends FunctionReference<'action'>> = { query: keyof FunctionArgs<T> extends never ? (args?: EmptyObject) => Promise<FunctionReturnType<T>> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T>) => Promise<FunctionReturnType<T>> : (args: FunctionArgs<T>) => Promise<FunctionReturnType<T>>; mutate: keyof FunctionArgs<T> extends never ? (args?: EmptyObject) => Promise<FunctionReturnType<T>> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T>) => Promise<FunctionReturnType<T>> : (args: FunctionArgs<T>) => Promise<FunctionReturnType<T>>; }; //#endregion //#region src/solid/auth.d.ts declare const MetaContext: solid_js0.Context<Meta | undefined>; /** * Hook to access the meta object from context. * Returns undefined if meta was not provided. */ declare function useMeta(): Meta | undefined; /** * Hook to get function metadata from the meta index. */ declare function useFnMeta(): (namespace: string, fnName: string) => FnMeta$1 | undefined; type AuthType = 'required' | 'optional' | undefined; /** Get auth type from meta for a function */ declare function getAuthType(meta: Meta | undefined, funcName: string): AuthType; /** Hook to compute auth-based skip logic for queries */ declare function useAuthSkip(funcRef: FunctionReference<'query' | 'mutation' | 'action'>, opts?: { skipUnauth?: boolean; enabled?: boolean; }): { authType: AuthType; readonly isAuthLoading: boolean; readonly isAuthenticated: boolean; readonly shouldSkip: boolean; }; //#endregion //#region src/crpc/auth-error.d.ts /** * Auth Mutation Error * * Framework-agnostic error class for Better Auth mutations. */ /** * Error thrown when a Better Auth mutation fails. * Contains the original error details from Better Auth. */ declare class AuthMutationError extends Error { /** Error code from Better Auth (e.g., 'INVALID_PASSWORD', 'EMAIL_ALREADY_REGISTERED') */ code?: string; /** HTTP status code */ status: number; /** HTTP status text */ statusText: string; constructor(authError: { message?: string; status: number; statusText: string; code?: string; }); } /** * Type guard to check if an error is an AuthMutationError. */ declare function isAuthMutationError(error: unknown): error is AuthMutationError; //#endregion //#region src/solid/auth-mutations.d.ts type MutationOptionsHook<TData, TVariables = void> = (options?: Omit<SolidMutationOptions<TData, DefaultError, TVariables>, 'mutationFn'>) => SolidMutationOptions<TData, DefaultError, TVariables>; type AnyFn = (...args: any[]) => Promise<any>; type AuthClient = { signOut: AnyFn; signIn: { social: AnyFn; email: AnyFn; }; signUp: { email: AnyFn; }; }; type AuthMutationsResult<T extends AuthClient> = { useSignOutMutationOptions: MutationOptionsHook<Awaited<ReturnType<T['signOut']>>, Parameters<T['signOut']>[0] | void>; useSignInSocialMutationOptions: MutationOptionsHook<Awaited<ReturnType<T['signIn']['social']>>, Parameters<T['signIn']['social']>[0]>; useSignInMutationOptions: MutationOptionsHook<Awaited<ReturnType<T['signIn']['email']>>, Parameters<T['signIn']['email']>[0]>; useSignUpMutationOptions: MutationOptionsHook<Awaited<ReturnType<T['signUp']['email']>>, Parameters<T['signUp']['email']>[0]>; }; /** * Create mutation option hooks from a better-auth client. * * @example * ```tsx * // lib/auth-client.ts * import { createAuthMutations } from 'kitcn/solid'; * * export const authClient = createAuthClient({...}); * * export const { * useSignOutMutationOptions, * useSignInSocialMutationOptions, * useSignInMutationOptions, * useSignUpMutationOptions, * } = createAuthMutations(authClient); * * // components/header.tsx * const signOutMutation = createMutation(() => useSignOutMutationOptions({ * onSuccess: () => navigate('/login'), * })); * ``` */ declare function createAuthMutations<T extends AuthClient>(authClient: T): AuthMutationsResult<T>; //#endregion //#region src/solid/auth-store.d.ts type FetchAccessTokenFn = (args: { forceRefreshToken: boolean; }) => Promise<string | null>; declare const FetchAccessTokenContext: solid_js0.Context<FetchAccessTokenFn | null>; /** Get fetchAccessToken from context (available immediately, no race condition) */ declare const useFetchAccessToken: () => FetchAccessTokenFn | null; type ConvexAuthResult = { isAuthenticated: boolean; isLoading: boolean; }; /** Get auth from bridge context (null if no bridge configured) */ declare const useConvexAuthBridge: () => ConvexAuthResult | null; type AuthStoreState = { /** Callback when mutation/action called while unauthorized. Throws by default. */onMutationUnauthorized: () => void; /** Callback when query called while unauthorized. Noop by default. */ onQueryUnauthorized: (info: { queryName: string; }) => void; /** Custom function to detect UNAUTHORIZED errors. Default checks code or "auth" in message. */ isUnauthorized: (error: unknown) => boolean; /** Cached Convex JWT for HTTP requests */ token: string | null; /** JWT expiration timestamp (ms) */ expiresAt: number | null; /** Auth loading state (synced from useConvexAuth for class methods) */ isLoading: boolean; /** Auth state (synced from useConvexAuth for class methods) */ isAuthenticated: boolean; }; /** Decode JWT expiration (ms timestamp) from token */ declare function decodeJwtExp(token: string): number | null; type AuthStore = { get: <K extends keyof AuthStoreState>(key: K) => AuthStoreState[K]; set: <K extends keyof AuthStoreState>(key: K, value: AuthStoreState[K]) => void; store: AuthStoreState; }; declare function useAuthStore(): AuthStore; declare function useAuthValue<K extends keyof AuthStoreState>(key: K): AuthStoreState[K]; declare function AuthProvider(props: { children: JSX.Element; initialValues?: Partial<AuthStoreState>; isUnauthorized?: (error: unknown) => boolean; onMutationUnauthorized?: () => void; onQueryUnauthorized?: (info: { queryName: string; }) => void; }): JSX.Element; /** * Safe wrapper that doesn't throw when used outside auth provider. * Returns { isAuthenticated: false, isLoading: false } when no auth provider. * * Supports both: * - better-auth users (via AuthProvider) * - @convex-dev/auth users (via ConvexAuthBridge) */ declare function useSafeConvexAuth(): ConvexAuthResult; /** * Bridge component that provides auth state via context. * @internal */ declare function ConvexAuthBridge(props: ParentProps<{ isLoading: boolean; isAuthenticated: boolean; }>): JSX.Element; declare const useAuth: () => { readonly hasSession: boolean; readonly isAuthenticated: boolean; readonly isLoading: boolean; }; /** Check if user maybe has auth (optimistic, has token) */ declare const useMaybeAuth: () => () => boolean; /** Check if user is authenticated (server-verified) */ declare const useIsAuth: () => () => boolean; declare const useAuthGuard: () => (callback?: () => Promise<void> | void) => boolean | undefined; /** Render children only when maybe has auth (optimistic) */ declare function MaybeAuthenticated(props: { children: JSX.Element; }): JSX.Element; /** Render children only when authenticated (server-verified) */ declare function Authenticated(props: { children: JSX.Element; }): JSX.Element; /** Render children only when maybe not auth (optimistic) */ declare function MaybeUnauthenticated(props: { children: JSX.Element; }): JSX.Element; /** Render children only when not authenticated (server-verified) */ declare function Unauthenticated(props: { children: JSX.Element; }): JSX.Element; //#endregion //#region src/crpc/transformer.d.ts /** * Generic transformer contract (mirrors tRPC shape). */ interface DataTransformer { deserialize(object: any): any; serialize(object: any): any; } /** * Separate input/output transformers. */ interface CombinedDataTransformer { input: DataTransformer; output: DataTransformer; } /** * Transformer config accepted by cRPC. */ type DataTransformerOptions = CombinedDataTransformer | DataTransformer; //#endregion //#region src/solid/client.d.ts interface ConvexQueryClientOptions { /** Auth store for checking auth state in queryFn */ authStore?: AuthStore; /** * Opt out of consistent SSR queries for faster performance. * Trade-off: queries may return results from different timestamps. */ dangerouslyUseInconsistentQueriesDuringSSR?: boolean; /** TanStack QueryClient. Can also be set later via .connect(queryClient) */ queryClient?: QueryClient; /** Custom fetch for SSR. Avoid bundling on client. */ serverFetch?: typeof globalThis.fetch; /** Optional payload transformer (always composed with built-in Date support). */ transformer?: DataTransformerOptions; /** * Delay in ms before unsubscribing when a query has no observers. * Prevents wasteful unsubscribe/subscribe cycles from component * mount/unmount cycles and quick back/forward navigation. * Set to 0 to unsubscribe immediately. * @default 3000 */ unsubscribeDelay?: number; } /** * Bridges TanStack Query with Convex real-time subscriptions (SolidJS). * * Uses `ConvexClient.onUpdate()` instead of `ConvexReactClient.watchQuery()`. */ declare class ConvexQueryClient { /** Convex client for WebSocket subscriptions (client) and one-shot queries */ convexClient: ConvexClient; /** * Active WebSocket subscriptions, keyed by TanStack query hash. * Each subscription has: * - getCurrentValue: getter for latest query result * - unsubscribe: cleanup function to remove the subscription * - queryKey: original query key for cache updates * - lastError: most recent error from onError callback */ subscriptions: Record<string, { getCurrentValue: () => unknown; unsubscribe: () => void; queryKey: ['convexQuery', string, Record<string, unknown>]; lastError: unknown; }>; /** Cleanup function for QueryCache subscription */ unsubscribe: (() => void) | undefined; /** * Pending unsubscribes with timeout IDs. * Used to debounce unsubscribe/subscribe cycles. */ private pendingUnsubscribes; /** HTTP client for SSR queries (no WebSocket on server) */ serverHttpClient?: ConvexHttpClient; /** TanStack QueryClient reference */ _queryClient: QueryClient | undefined; /** SSR query mode: 'consistent' guarantees same timestamp, 'inconsistent' is faster */ ssrQueryMode: 'consistent' | 'inconsistent'; /** Auth store for checking auth state */ private authStore?; /** Delay before unsubscribing when query has no observers */ private unsubscribeDelay; /** Payload transformer used across request/response boundaries. */ private transformer; /** Stored URL for creating HTTP client on server */ private convexUrl; /** Runtime-safe accessor for pending unsubscribe map (defensive for HMR edge cases) */ private getPendingUnsubscribesMap; /** Cancel a pending delayed unsubscribe for a query hash. */ private cancelPendingUnsubscribe; /** Unsubscribe a live Convex subscription (if present) and remove it from the subscription map. */ private unsubscribeQueryByHash; /** Update auth store (for HMR where store may reset) */ updateAuthStore(authStore?: AuthStore): void; /** Get current auth state from store */ private getAuthState; /** * Check if subscription should be skipped due to auth state. * Needed for useSuspenseQuery which ignores enabled: false. */ private shouldSkipSubscription; /** Get QueryClient, throwing if not connected */ get queryClient(): QueryClient; /** * Create a ConvexQueryClient. * * @param client - Convex URL string or existing ConvexClient * @param options - Configuration options */ constructor(client: ConvexClient | string, options?: ConvexQueryClientOptions); /** * Connect to TanStack QueryClient. * Starts listening to cache events for subscription management. */ connect(queryClient: QueryClient): void; /** * Clean up all subscriptions. * Call this when the client is no longer needed. */ destroy(): void; /** * Unsubscribe from all auth-required queries. * Call before logout to prevent UNAUTHORIZED errors during session invalidation. */ unsubscribeAuthQueries(): void; /** * Batch update all subscriptions. * Called internally when Convex client reconnects. */ onUpdate: () => void; /** * Handle Convex subscription update for a specific query. * Reads latest value from getCurrentValue and updates TanStack cache. * * @param queryHash - TanStack query hash identifying the query */ onUpdateQueryKeyHash(queryHash: string): void; /** * Subscribe to TanStack QueryCache events. * Creates/removes Convex WebSocket subscriptions as queries are added/removed. * * @param queryCache - TanStack QueryCache to subscribe to * @returns Cleanup function to unsubscribe */ subscribeInner(queryCache: QueryCache): () => void; /** * Create a WebSocket subscription via ConvexClient.onUpdate(). * Stores the subscription in the subscriptions map. */ private createSubscription; /** * Create default queryFn for TanStack QueryClient. * * Handles: * - Convex queries and actions * - Auth checking (throws CRPCClientError if unauthorized) * - SSR via HTTP client * - Client via WebSocket client * * @param otherFetch - Fallback queryFn for non-Convex queries * @returns QueryFunction compatible with TanStack Query */ queryFn(otherFetch?: QueryFunction<unknown, QueryKey>): <T extends FunctionReference<"query", "public">>(context: QueryFunctionContext<readonly unknown[]>) => Promise<FunctionReturnType<T>>; /** * Create hash function for TanStack QueryClient. * * Uses Convex-specific hashing for Convex queries to ensure * consistent cache keys across serialization. * * @param fallback - Fallback hash function for non-Convex queries * @returns Hash function compatible with TanStack Query */ hashFn(fallback?: (queryKey: readonly unknown[]) => string): (queryKey: readonly unknown[]) => string; } //#endregion //#region src/internal/types.d.ts /** * Simplify complex type intersections for better IDE display. * Pattern from Drizzle ORM: The & {} intersection "seals" the type to prevent * distributive conditional behavior that can cause union widening. * @see https://github.com/drizzle-team/drizzle-orm/blob/main/drizzle-orm/src/utils.ts#L144-L149 */ type Simplify<TType> = TType extends any[] | Date ? TType : { [K in keyof TType]: TType[K] } & {}; /** * Omit keys without removing a potential union. * Unlike standard Omit, this preserves union types. */ type DistributiveOmit<TObj, TKey extends keyof any> = TObj extends any ? Omit<TObj, TKey> : never; /** Makes the object recursively optional */ type DeepPartial<TObject> = TObject extends object ? { [P in keyof TObject]?: DeepPartial<TObject[P]> } : TObject; //#endregion //#region src/server/types.d.ts /** Marker for unset values - branded type to distinguish "not set" from actual types */ type UnsetMarker = { readonly __brand: 'UnsetMarker'; }; //#endregion //#region src/server/http-types.d.ts type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; interface HttpRouteDefinition<TMethod extends HttpMethod = HttpMethod> { method: TMethod; path: string; pathParamNames: string[]; usePathPrefix: boolean; } interface HttpActionHandler { isHttp: true; } interface HttpProcedure<TInput extends UnsetMarker | z.ZodTypeAny = any, TOutput extends UnsetMarker | z.ZodTypeAny = any, TParams extends UnsetMarker | z.ZodTypeAny = any, TQuery extends UnsetMarker | z.ZodTypeAny = any, TMethod extends HttpMethod = HttpMethod, TForm extends UnsetMarker | z.ZodTypeAny = any> extends HttpActionHandler { _crpcHttpRoute: HttpRouteDefinition<TMethod>; /** @internal Expose def for client-side type inference */ _def: { inputSchema?: TInput; outputSchema?: TOutput; paramsSchema?: TParams; querySchema?: TQuery; formSchema?: TForm; }; } //#endregion //#region src/server/http-router.d.ts /** * Recursive router record - can contain procedures or nested routers */ interface HttpRouterRecord { [key: string]: HttpProcedure | HttpRouterRecord | CRPCHttpRouter<any>; } /** * Router definition - stores both flat procedures and hierarchical record */ interface HttpRouterDef<TRecord extends HttpRouterRecord> { /** Flat map with dot-notation keys (e.g., "todos.get") for lookup */ procedures: Record<string, HttpProcedure>; /** Hierarchical structure for type inference */ record: TRecord; router: true; } /** * HTTP Router - like tRPC's BuiltRouter */ interface CRPCHttpRouter<TRecord extends HttpRouterRecord> { _def: HttpRouterDef<TRecord>; } //#endregion //#region src/crpc/http-types.d.ts /** Error codes that can be returned from HTTP endpoints */ type HttpErrorCode = 'BAD_REQUEST' | 'UNAUTHORIZED' | 'FORBIDDEN' | 'NOT_FOUND' | 'METHOD_NOT_SUPPORTED' | 'CONFLICT' | 'UNPROCESSABLE_CONTENT' | 'TOO_MANY_REQUESTS' | 'INTERNAL_SERVER_ERROR' | 'UNKNOWN'; /** HTTP client error */ declare class HttpClientError extends Error { readonly name = "HttpClientError"; readonly code: HttpErrorCode; readonly status: number; readonly procedureName: string; constructor(opts: { code: HttpErrorCode; status: number; procedureName: string; message?: string; }); } //#endregion //#region src/solid/crpc-types.d.ts /** Stops callbacks from running. Matches convex/browser Unsubscribe<T>. */ type Unsubscribe<T> = { /** Stop calling callback when query results change. */(): void; /** Stop calling callback when query results change. */ unsubscribe(): void; /** Get the last known value, possibly with local optimistic updates applied. */ getCurrentValue(): T | undefined; }; /** Options returned by `convexQuery` factory */ type ConvexQueryOptions<T extends FunctionReference<'query'>> = Pick<SolidQueryOptions<FunctionReturnType<T>, Error, FunctionReturnType<T>, ConvexQueryKey<T>>, 'queryKey' | 'staleTime' | 'enabled'>; /** Options returned by `convexAction` factory */ type ConvexActionOptions<T extends FunctionReference<'action'>> = Pick<SolidQueryOptions<FunctionReturnType<T>, Error, FunctionReturnType<T>, ConvexActionKey<T>>, 'queryKey' | 'staleTime' | 'enabled'>; /** Query options parameter type */ type QueryOptsParam<T extends FunctionReference<'query'>> = Simplify<ConvexQueryHookOptions & DistributiveOmit<SolidQueryOptions<FunctionReturnType<T>, DefaultError>, ReservedQueryOptions$2>>; /** Query options return type */ type QueryOptsReturn<T extends FunctionReference<'query'>> = ConvexQueryOptions<T> & { meta: ConvexQueryMeta; }; /** Action query options parameter type (actions don't support subscriptions) */ type ActionQueryOptsParam<T extends FunctionReference<'action'>> = DistributiveOmit<SolidQueryOptions<FunctionReturnType<T>, DefaultError>, ReservedQueryOptions$2>; /** Action query options return type */ type ActionQueryOptsReturn<T extends FunctionReference<'action'>> = ConvexActionOptions<T>; /** * Decorated query procedure with queryOptions, queryKey, and queryFilter methods. * Args are optional when the function has no required parameters. * Supports skipToken for type-safe conditional queries. */ type DecorateQuery<T extends FunctionReference<'query'>> = { queryOptions: keyof FunctionArgs<T> extends never ? (args?: EmptyObject | SkipToken, opts?: QueryOptsParam<T>) => QueryOptsReturn<T> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T> | SkipToken, opts?: QueryOptsParam<T>) => QueryOptsReturn<T> : (args: FunctionArgs<T> | SkipToken, opts?: QueryOptsParam<T>) => QueryOptsReturn<T>; /** Static (non-hook) query options for event handlers and prefetching */ staticQueryOptions: keyof FunctionArgs<T> extends never ? (args?: EmptyObject | SkipToken, opts?: StaticQueryOptsParam) => ConvexQueryOptions<T> & { meta: ConvexQueryMeta; } : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T> | SkipToken, opts?: StaticQueryOptsParam) => ConvexQueryOptions<T> & { meta: ConvexQueryMeta; } : (args: FunctionArgs<T> | SkipToken, opts?: StaticQueryOptsParam) => ConvexQueryOptions<T> & { meta: ConvexQueryMeta; }; /** Get query key for QueryClient methods (setQueryData, getQueryData, etc.) */ queryKey: (args?: DeepPartial<FunctionArgs<T>>) => ConvexQueryKey<T>; /** Get query filter for QueryClient methods (invalidateQueries, removeQueries, etc.) */ queryFilter: (args?: DeepPartial<FunctionArgs<T>>, filters?: DistributiveOmit<QueryFilters, 'queryKey'>) => QueryFilters; }; /** Options for infinite query - extends TanStack Query options */ type InfiniteQueryOptsParam<T extends FunctionReference<'query'> = FunctionReference<'query'>> = { /** Items per page. Optional - server uses .paginated() default if not provided. */limit?: number; /** Skip query silently when unauthenticated */ skipUnauth?: boolean; /** Placeholder data shown while loading (item array, not pagination result) */ placeholderData?: ExtractPaginatedItem<FunctionReturnType<T>>[]; } & DistributiveOmit<SolidQueryOptions<FunctionReturnType<T>, DefaultError>, ReservedInfiniteQueryOptions>; /** Return type of infiniteQueryOptions - compatible with TanStack prefetch */ type ConvexInfiniteQueryOptions<T extends FunctionReference<'query'>> = Pick<SolidQueryOptions<FunctionReturnType<T>, Error, FunctionReturnType<T>, ConvexQueryKey<T>>, 'queryKey' | 'staleTime' | 'enabled'> & { meta: ConvexInfiniteQueryMeta; refetchInterval: false; refetchOnMount: false; refetchOnReconnect: false; refetchOnWindowFocus: false; /** Placeholder data shown while loading (item array, not pagination result) */ placeholderData?: ExtractPaginatedItem<FunctionReturnType<T>>[]; } & DistributiveOmit<SolidQueryOptions<FunctionReturnType<T>, DefaultError>, ReservedInfiniteQueryOptions>; /** Infinite query options with attached function reference (client-only) */ type ConvexInfiniteQueryOptionsWithRef<T extends FunctionReference<'query'>> = ConvexInfiniteQueryOptions<T> & { [FUNC_REF_SYMBOL]: T; }; /** Infinite query options return type */ type InfiniteQueryOptsReturn<T extends FunctionReference<'query'>> = ConvexInfiniteQueryOptionsWithRef<T>; /** * Decorated infinite query procedure. * Only available on queries that have cursor/limit in their input (paginated). * Supports skipToken for conditional queries. * Args are optional when the function has no required parameters (besides cursor/limit). */ type DecorateInfiniteQuery<T extends FunctionReference<'query'>> = { /** Create infinite query options for useInfiniteQuery and prefetch */infiniteQueryOptions: keyof InfiniteQueryInput<FunctionArgs<T>> extends never ? (args?: EmptyObject | SkipToken, opts?: InfiniteQueryOptsParam<T>) => InfiniteQueryOptsReturn<T> : EmptyObject extends InfiniteQueryInput<FunctionArgs<T>> ? (args?: InfiniteQueryInput<FunctionArgs<T>> | SkipToken, opts?: InfiniteQueryOptsParam<T>) => InfiniteQueryOptsReturn<T> : (args: InfiniteQueryInput<FunctionArgs<T>> | SkipToken, opts?: InfiniteQueryOptsParam<T>) => InfiniteQueryOptsReturn<T>; /** Get query key for infinite query (QueryClient methods like setQueryData, getQueryData) */ infiniteQueryKey: (args?: DeepPartial<InfiniteQueryInput<FunctionArgs<T>>>) => ConvexQueryKey<T>; /** Function metadata from server (auth, limit, rateLimit, role, type) */ meta: PaginatedFnMeta; }; /** * Decorated mutation procedure with mutationOptions and mutationKey methods. */ type DecorateMutation<T extends FunctionReference<'mutation'>> = { mutationOptions: (opts?: DistributiveOmit<SolidMutationOptions<FunctionReturnType<T>, DefaultError, MutationVariables<T>>, ReservedMutationOptions$2>) => SolidMutationOptions<FunctionReturnType<T>, DefaultError, MutationVariables<T>>; /** Get mutation key for QueryClient methods */ mutationKey: () => ConvexMutationKey; }; /** * Decorated action procedure with queryOptions, mutationOptions, and key methods. * Actions can be used as one-shot queries (no subscription) or as mutations. * Supports skipToken for conditional queries. */ type DecorateAction<T extends FunctionReference<'action'>> = { /** Use action as a one-shot query (no WebSocket subscription) */queryOptions: keyof FunctionArgs<T> extends never ? (args?: EmptyObject | SkipToken, opts?: ActionQueryOptsParam<T>) => ActionQueryOptsReturn<T> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T> | SkipToken, opts?: ActionQueryOptsParam<T>) => ActionQueryOptsReturn<T> : (args: FunctionArgs<T> | SkipToken, opts?: ActionQueryOptsParam<T>) => ActionQueryOptsReturn<T>; /** Static (non-hook) action query options for event handlers and prefetching */ staticQueryOptions: keyof FunctionArgs<T> extends never ? (args?: EmptyObject | SkipToken, opts?: StaticQueryOptsParam) => ConvexActionOptions<T> & { meta: ConvexQueryMeta; } : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T> | SkipToken, opts?: StaticQueryOptsParam) => ConvexActionOptions<T> & { meta: ConvexQueryMeta; } : (args: FunctionArgs<T> | SkipToken, opts?: StaticQueryOptsParam) => ConvexActionOptions<T> & { meta: ConvexQueryMeta; }; /** Use action as a mutation */ mutationOptions: (opts?: DistributiveOmit<SolidMutationOptions<FunctionReturnType<T>, DefaultError, MutationVariables<T>>, ReservedMutationOptions$2>) => SolidMutationOptions<FunctionReturnType<T>, DefaultError, MutationVariables<T>>; /** Get mutation key for QueryClient methods */ mutationKey: () => ConvexMutationKey; /** Get query key for QueryClient methods */ queryKey: (args?: DeepPartial<FunctionArgs<T>>) => ConvexActionKey<T>; /** Get query filter for QueryClient methods */ queryFilter: (args?: DeepPartial<FunctionArgs<T>>, filters?: DistributiveOmit<QueryFilters, 'queryKey'>) => QueryFilters; }; /** Vanilla query - direct .query() and .onUpdate() calls without Solid Query */ type VanillaQuery<T extends FunctionReference<'query'>> = { query: keyof FunctionArgs<T> extends never ? (args?: EmptyObject) => Promise<FunctionReturnType<T>> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T>) => Promise<FunctionReturnType<T>> : (args: FunctionArgs<T>) => Promise<FunctionReturnType<T>>; onUpdate: keyof FunctionArgs<T> extends never ? (args?: EmptyObject, callback?: (result: FunctionReturnType<T>) => void, onError?: (e: Error) => void) => Unsubscribe<FunctionReturnType<T>> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T>, callback?: (result: FunctionReturnType<T>) => void, onError?: (e: Error) => void) => Unsubscribe<FunctionReturnType<T>> : (args: FunctionArgs<T>, callback: (result: FunctionReturnType<T>) => void, onError?: (e: Error) => void) => Unsubscribe<FunctionReturnType<T>>; }; /** * Recursively creates vanilla client type for direct procedural calls. */ type VanillaCRPCClient<TApi> = { [K in keyof TApi as K extends string ? K extends `_${string}` ? never : K : K]: TApi[K] extends FunctionReference<'query'> ? VanillaQuery<TApi[K]> : TApi[K] extends FunctionReference<'mutation'> ? VanillaMutation<TApi[K]> : TApi[K] extends FunctionReference<'action'> ? VanillaAction<TApi[K]> : TApi[K] extends Record<string, unknown> ? VanillaCRPCClient<TApi[K]> : never }; /** * Recursively decorates all procedures in a Convex API object. */ type CRPCClient<TApi> = { [K in keyof TApi as K extends string ? K extends `_${string}` ? never : K : K]: TApi[K] extends FunctionReference<'query'> ? IsPaginated<FunctionArgs<TApi[K]>> extends true ? DecorateQuery<TApi[K]> & DecorateInfiniteQuery<TApi[K]> : DecorateQuery<TApi[K]> : TApi[K] extends FunctionReference<'mutation'> ? DecorateMutation<TApi[K]> : TApi[K] extends FunctionReference<'action'> ? DecorateAction<TApi[K]> : TApi[K] extends Record<string, unknown> ? CRPCClient<TApi[K]> : never }; //#endregion //#region src/crpc/http-client.d.ts /** Form value types (matches Hono's FormValue) */ type HttpFormValue = string | Blob; /** * Hybrid input args: JSON body fields at root, explicit params/searchParams/form. * - JSON body: spread at root level (tRPC-style) * - Path params: { params: { id: '123' } } * - Query params: { searchParams: { limit: '10' } } * - Form data: { form: { file: blob } } - typed via .form() builder * - Client options: { headers, fetch, init } - for per-call customization */ type HttpInputArgs = { /** Path parameters (e.g., :id in /users/:id) */params?: Record<string, string>; /** Query string parameters */ searchParams?: Record<string, string | string[]>; /** Form data body (Content-Type: multipart/form-data) - typed via .form() builder */ form?: Record<string, HttpFormValue | HttpFormValue[]>; /** Custom fetch function (per-call override) */ fetch?: typeof fetch; /** Standard RequestInit (per-call override) */ init?: RequestInit; /** Additional headers (per-call override) */ headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>); /** Any other properties are JSON body fields */ [key: string]: unknown; }; /** * Client request options (matches Hono's ClientRequestOptions). * Standard RequestInit in `init` takes highest priority and can override * things that are set automatically like body, method, headers. */ type HttpClientOptions = { /** Custom fetch function */fetch?: typeof fetch; /** * Standard RequestInit - takes highest priority. * Can override body, method, headers if needed. */ init?: RequestInit; /** Additional headers (or async function returning headers) */ headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>); }; //#endregion //#region src/solid/http-proxy.d.ts type HttpRouteInfo = { path: string; method: string; }; type HttpRouteMap = Record<string, HttpRouteInfo>; /** Infer schema type or return empty object if UnsetMarker */ type InferSchemaOrEmpty<T> = T extends UnsetMarker ? object : T extends z.ZodTypeAny ? z.infer<T> : object; /** Infer merged input from HttpProcedure (flat - used internally) */ type InferHttpInput<T> = T extends HttpProcedure<infer TInput, infer _TOutput, infer TParams, infer TQuery> ? Simplify<InferSchemaOrEmpty<TParams> & InferSchemaOrEmpty<TQuery> & InferSchemaOrEmpty<TInput>> : object; /** * Extract string keys from a Zod object schema. * Used for param/query which are always strings in URLs. */ type ZodObjectKeys<T> = T extends z.ZodObject<infer Shape> ? { [K in keyof Shape]: string } : Record<string, string>; /** * Extract string or string[] keys from a Zod object schema. * Query params can have array values. */ type ZodQueryKeys<T> = T extends z.ZodObject<infer Shape> ? { [K in keyof Shape]?: string | string[] } : Record<string, string | string[]>; /** * Infer client-side args from HttpProcedure with proper nesting. * - params: only present if TParams is defined, always strings (URL path params) * - searchParams: only present if TQuery is defined, always strings (URL query params) * - form: only present if TForm is defined, typed from schema * - JSON body fields spread at root level (typed from schema) * - Client options (fetch, init, headers) always optional for per-call overrides */ type InferHttpClientArgs<T> = T extends HttpProcedure<infer TInput, infer _TOutput, infer TParams, infer TQuery, infer _TMethod, infer TForm> ? Simplify<(TParams extends UnsetMarker ? object : { params: ZodObjectKeys<TParams>; }) & (TQuery extends UnsetMarker ? object : { searchParams: ZodQueryKeys<TQuery>; }) & (TForm extends UnsetMarker ? object : TForm extends z.ZodTypeAny ? { form: z.infer<TForm>; } : object) & (TInput extends UnsetMarker ? object : TInput extends z.ZodTypeAny ? z.infer<TInput> : object) & { fetch?: typeof fetch; init?: RequestInit; headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>); }> : HttpInputArgs; /** Infer output type from HttpProcedure */ type InferHttpOutput<T> = T extends HttpProcedure<infer _TInput, infer TOutput, infer _TParams, infer _TQuery> ? TOutput extends UnsetMarker ? unknown : TOutput extends z.ZodTypeAny ? z.infer<TOutput> : unknown : unknown; /** Query key with args (3-element) or prefix key without args (2-element) for invalidation */ type HttpQueryKey = readonly ['httpQuery', string, unknown] | readonly ['httpQuery', string]; type HttpMutationKey = readonly ['httpMutation', string]; type ReservedQueryOptions$1 = 'queryKey' | 'queryFn'; type ReservedMutationOptions$1 = 'mutationFn'; /** Query options for GET HTTP endpoints - compatible with both createQuery and createSuspenseQuery */ type HttpQueryOptsReturn<T extends HttpProcedure> = Omit<SolidQueryOptions<InferHttpOutput<T>, Error, InferHttpOutput<T>, HttpQueryKey>, 'queryFn'> & { queryFn: () => Promise<InferHttpOutput<T>>; }; /** Mutation options for POST/PUT/PATCH/DELETE HTTP endpoints - typed variables */ type HttpMutationOptsReturn<T extends HttpProcedure> = SolidMutationOptions<InferHttpOutput<T>, DefaultError, InferHttpClientArgs<T>>; /** Query options (TanStack Query only - client opts go in args) */ type HttpQueryOptions<T extends HttpProcedure> = DistributiveOmit<HttpQueryOptsReturn<T>, ReservedQueryOptions$1>; /** Mutation options (TanStack Query only - client opts go in mutate args) */ type HttpMutationOptions<T extends HttpProcedure> = DistributiveOmit<HttpMutationOptsReturn<T>, ReservedMutationOptions$1>; /** * Decorated GET procedure with queryOptions and mutationOptions. * - queryOptions: For cached data fetching (createQuery/createSuspenseQuery) * - mutationOptions: For one-time actions like exports (createMutation) */ type DecorateHttpQuery<T extends HttpProcedure> = { queryOptions: keyof InferHttpInput<T> extends never ? (args?: InferHttpClientArgs<T>, opts?: HttpQueryOptions<T>) => HttpQueryOptsReturn<T> : object extends InferHttpInput<T> ? (args?: InferHttpClientArgs<T>, opts?: HttpQueryOptions<T>) => HttpQueryOptsReturn<T> : (args: InferHttpClientArgs<T>, opts?: HttpQueryOptions<T>) => HttpQueryOptsReturn<T>; /** Get query key for QueryClient methods (with args = exact match, without = prefix) */ queryKey: (args?: InferHttpClientArgs<T>) => HttpQueryKey; /** Get query filter for QueryClient methods (e.g., invalidateQueries) */ queryFilter: (args?: InferHttpClientArgs<T>, filters?: DistributiveOmit<QueryFilters, 'queryKey'>) => QueryFilters; /** Mutation options for GET endpoints (exports, downloads - no caching) */ mutationOptions: (opts?: HttpMutationOptions<T>) => HttpMutationOptsReturn<T>; /** Get mutation key for QueryClient methods */ mutationKey: () => HttpMutationKey; }; /** * Decorated POST/PUT/PATCH/DELETE procedure with mutationOptions. * The mutationFn receives typed args inferred from server schemas. */ type DecorateHttpMutation<T extends HttpProcedure> = { mutationOptions: (opts?: HttpMutationOptions<T>) => HttpMutationOptsReturn<T>; /** Get mutation key for QueryClient methods */ mutationKey: () => HttpMutationKey; }; /** Vanilla HTTP query - only direct call, no TanStack Query */ type VanillaHttpQuery<T extends HttpProcedure> = { query: keyof InferHttpInput<T> extends never ? (args?: InferHttpClientArgs<T>) => Promise<InferHttpOutput<T>> : object extends InferHttpInput<T> ? (args?: InferHttpClientArgs<T>) => Promise<InferHttpOutput<T>> : (args: InferHttpClientArgs<T>) => Promise<InferHttpOutput<T>>; }; /** Vanilla HTTP mutation - only direct call, no TanStack Query */ type VanillaHttpMutation<T extends HttpProcedure> = { mutate: keyof InferHttpInput<T> extends never ? (args?: InferHttpClientArgs<T>) => Promise<InferHttpOutput<T>> : object extends InferHttpInput<T> ? (args?: InferHttpClientArgs<T>) => Promise<InferHttpOutput<T>> : (args: InferHttpClientArgs<T>) => Promise<InferHttpOutput<T>>; }; /** Vanilla HTTP client type - only query/mutate methods */ type VanillaHttpCRPCClient<T extends HttpRouterRecord> = { [K in keyof T]: T[K] extends HttpProcedure<infer _TInput, infer _TOutput, infer _TParams, infer _TQuery, infer TMethod, infer _TForm> ? TMethod extends 'GET' ? VanillaHttpQuery<T[K]> : VanillaHttpMutation<T[K]> : T[K] extends CRPCHttpRouter<infer R> ? VanillaHttpCRPCClient<R> : T[K] extends HttpRouterRecord ? VanillaHttpCRPCClient<T[K]> : never }; /** Extract vanilla HTTP client from router */ type VanillaHttpCRPCClientFromRouter<T> = T extends CRPCHttpRouter<infer R> ? VanillaHttpCRPCClient<R> : never; /** * HTTP Client type from router record. * Maps each procedure to queryOptions (GET) or mutationOptions (POST/etc). * Uses infer to extract the method type literal for proper GET/non-GET distinction. */ type HttpCRPCClient<T extends HttpRouterRecord> = { [K in keyof T]: T[K] extends HttpProcedure<infer _TInput, infer _TOutput, infer _TParams, infer _TQuery, infer TMethod, infer _TForm> ? TMethod extends 'GET' ? DecorateHttpQuery<T[K]> : DecorateHttpMutation<T[K]> : T[K] extends CRPCHttpRouter<infer R> ? HttpCRPCClient<R> : T[K] extends HttpRouterRecord ? HttpCRPCClient<T[K]> : never }; /** * HTTP Client type from a CRPCHttpRouter. * Use this when your type is the router object (with _def). */ type HttpCRPCClientFromRouter<TRouter extends CRPCHttpRouter<any>> = HttpCRPCClient<TRouter['_def']['record']>; interface HttpProxyOptions<TRoutes extends HttpRouteMap> { /** Base URL for the Convex HTTP API (e.g., https://your-site.convex.site) */ convexSiteUrl: string; /** Custom fetch function (defaults to global fetch) */ fetch?: typeof fetch; /** Default headers or async function returning headers (for auth tokens) */ headers?: { [key: string]: string | undefined; } | (() => { [key: string]: string | undefined; } | Promise<{ [key: string]: string | undefined; }>); /** Error handler called on HTTP errors */ onError?: (error: HttpClientError) => void; /** Runtime route definitions (from codegen httpRoutes) */ routes: TRoutes; /** Optional payload transformer (always composed with built-in Date support). */ transformer?: DataTransformerOptions; } /** * Create an HTTP proxy with TanStack Query integration for SolidJS. * * Returns a proxy that provides: * - `queryOptions` for GET endpoints (no subscription) * - `mutationOptions` for POST/PUT/PATCH/DELETE endpoints * * @example * ```ts * const httpProxy = createHttpProxy<AppRouter>({ * convexSiteUrl: import.meta.env.VITE_CONVEX_SITE_URL, * routes: httpRoutes, * }); * * // GET endpoint * const opts = httpProxy.todos.get.queryOptions({ id: '123' }); * const query = createQuery(() => opts); * * // POST endpoint * const mutation = createMutation(() => httpProxy.todos.create.mutationOptions()); * await mutation.mutateAsync({ title: 'New todo' }); * ``` */ declare function createHttpProxy<TRouter extends CRPCHttpRouter<any>, TRoutes extends HttpRouteMap = HttpRouteMap>(opts: HttpProxyOptions<TRoutes>): HttpCRPCClientFromRouter<TRouter>; //#endregion //#region src/solid/context.d.ts /** Access ConvexQueryClient (e.g., for logout cleanup) */ declare const useConvexQueryClient: () => ConvexQueryClient | null; /** Headers record that allows empty objects and optional properties */ type HeadersInput = { [key: string]: string | undefined; }; type CRPCHttpOptions = { /** Base URL for the Convex HTTP API (e.g., https://your-site.convex.site) */convexSiteUrl: string; /** Default headers or async function returning headers (for auth tokens) */ headers?: HeadersInput | (() => HeadersInput | Promise<HeadersInput>); /** Custom fetch function (defaults to global fetch) */ fetch?: typeof fetch; /** Error handler called on HTTP errors */ onError?: (error: HttpClientError) => void; }; type CreateCRPCContextOptions<TApi> = { api: TApi; /** Optional payload transformer (always composed with built-in Date support). */ transformer?: DataTransformerOptions; } & Partial<CRPCHttpOptions>; /** * Extract HTTP router from TApi['http'] if present (optional). * Uses NonNullable to handle optional http property. */ type ExtractHttpRouter<TApi> = TApi extends { http?: infer R; } ? NonNullable<R> extends CRPCHttpRouter<HttpRouterRecord> ? NonNullable<R> : undefined : undefined; /** * Create CRPC context, provider, and hooks for a Convex API. * * @param options - Configuration object containing api and optional HTTP settings * @returns Object with CRPCProvider, useCRPC, and useCRPCClient * * @example * ```tsx * // lib/crpc.ts * import { api } from '@convex/api'; * import { createCRPCContext } from 'kitcn/solid'; * * // Works for both regular Convex functions and generated HTTP router types * export const { useCRPC } = createCRPCContext({ * api, * convexSiteUrl: import.meta.env.VITE_CONVEX_SITE_URL, * }); * * // components/user-profile.tsx * function UserProfile({ id }) { * const crpc = useCRPC(); * const { data } = createQuery(() => crpc.user.get.queryOptions({ id })); * * // HTTP endpoints (if configured) * const { data: httpData } = createQuery(() => crpc.http.todos.get.queryOptions({ id })); * } * ``` */ declare function createCRPCContext<TApi extends Record<string, unknown>>(options: CreateCRPCContextOptions<TApi>): { CRPCProvider: (props: { children: JSX.Element; convexClient: ConvexClient; convexQueryClient: ConvexQueryClient; }) => JSX.Element; useCRPC: () => ExtractHttpRouter<TApi> extends CRPCHttpRouter<HttpRouterRecord> ? CRPCClient<Omit<TApi, "http">> & { http: HttpCRPCClientFromRouter<ExtractHttpRouter<TApi>>; } : CRPCClient<TApi>; useCRPCClient: () => ExtractHttpRouter<TApi> extends CRPCHttpRouter<HttpRouterRecord> ? VanillaCRPCClient<Omit<TApi, "http">> & { http: VanillaHttpCRPCClientFromRouter<ExtractHttpRouter<TApi>>; } : VanillaCRPCClient<TApi>; }; //#endregion //#region src/auth/internal/convex-plugin.d.ts declare const convex$1: (opts: { authConfig: AuthConfig; jwks?: string; jwksRotateOnTokenGenerationError?: boolean; jwt?: { definePayload?: (session: { session: Session & Record<string, any>; user: User & Record<string, any>; }) => Promise<Record<string, any>> | Record<string, any> | undefined; expirationSeconds?: number; }; /** * @deprecated Use jwt.expirationSeconds instead. */ jwtExpirationSeconds?: number; options?: BetterAuthOptions; }) => { id: "convex"; init: (ctx: better_auth0.AuthContext) => void; hooks: { before: ({ matcher(context: better_auth0.HookEndpointContext): boolean; handler: (inputContext: better_auth0.MiddlewareInputContext<better_auth0.MiddlewareOptions>) => Promise<{ context: { headers: Headers; }; } | undefined>; } | { matcher: (ctx: better_auth0.HookEndpointContext) => boolean; handler: (inputContext: better_auth0.MiddlewareInputContext<better_auth0.MiddlewareOptions>) => Promise<{ context: better_auth0.MiddlewareContext<better_auth0.MiddlewareOptions, { returned?: unknown | undefined; responseHeaders?: Headers | undefined; } & better_auth0.PluginContext<BetterAuthOptions> & better_auth0.InfoContext & { options: BetterAuthOptions; trustedOrigins: string[]; trustedProviders: string[]; isTrustedOrigin: (url: string, settings?: { allowRelativePaths: boolean; }) => boolean; oauthConfig: { skipStateCookieCheck?: boolean | undefined; storeStateStrategy: "database" | "cookie"; }; newSession: { session: { id: string; createdAt: Date; updatedAt: Date; userId: string; expiresAt: Date; token: string; ipAddress?: string | null | undefined; userAgent?: string | null | undefined; } & Record<string, any>; user: { id: string; createdAt: Date; updatedAt: Date; email: string; emailVerified: boolean; name: string; image?: string | null | undefined; } & Record<string, any>; } | null; session: { session: { id: string; createdAt: Date; updatedAt: Date; userId: string; expiresAt: Date; token: string; ipAddress?: string | null | undefined; userAgent?: string | null | undefined; } & Record<string, any>; user: { id: string; createdAt: Date; updatedAt: Date; email: string; emailVerified: boolean; name: string; image?: string | null | undefined; } & Record<string, any>; } | null; setNewSession: (session: { session: { id: string; c