UNPKG

convex-helpers

Version:

A collection of useful code to complement the official convex package.

106 lines (105 loc) 4.37 kB
/** * Allows you to persist state server-side, associated with a sessionId stored * on the client (in localStorage, e.g.). * * You can define your function to take in a sessionId parameter of type * SessionId, which is just a branded string to help avoid errors. * The validator is vSessionId, or you can spread the argument in for your * function like this: * ```ts * const myMutation = mutation({ * args: { * arg1: v.number(), // whatever other args you want * ...SessionIdArg, * }, * handler: async (ctx, args) => { * // args.sessionId is a SessionId * }) * }); * ``` * * Then, on the client side, you can use {@link useSessionMutation} to call * your function with the sessionId automatically passed in, like: * ```ts * const myMutation = useSessionMutation(api.myModule.myMutation); * ... * await myMutation({ arg1: 123 }); * ``` * * To codify the sessionId parameter, you can use the customFunction module to * create a custom mutation or query, like: * ```ts * export const sessionMutation = customMutation(mutation, { * args: { ...SessionIdArg }, * input: (ctx, { sessionId }) => { * const anonUser = await getAnonymousUser(ctx, sessionId); * return { ctx: { anonUser }, args: {} }; * }, * }); * ``` * * Then you can define functions like: * ```ts * export const myMutation = sessionMutation({ * args: { arg1: v.number() }, // whatever other args you want * handler: async (ctx, args) => { * // ctx.anonUser exists and has a type from getAnonymousUser. * // args is { arg1: number } * }) * }); * ``` * * See the associated [Stack post](https://stack.convex.dev/track-sessions-without-cookies) * for more information. */ import { FunctionArgs, FunctionReference, FunctionReturnType, GenericActionCtx, GenericDataModel } from "convex/server"; import { Validator } from "convex/values"; import { BetterOmit, EmptyObject } from ".."; export type SessionId = string & { __SessionId: true; }; export declare const vSessionId: Validator<SessionId, false, never>; export declare const SessionIdArg: { sessionId: Validator<SessionId, false, never>; }; type SessionFunction<T extends "query" | "mutation" | "action", Args extends any = any> = FunctionReference<T, "public" | "internal", { sessionId: SessionId; } & Args, any>; type SessionArgsArray<Fn extends SessionFunction<"query" | "mutation" | "action", any>> = keyof FunctionArgs<Fn> extends "sessionId" ? [args?: EmptyObject] : [args: BetterOmit<FunctionArgs<Fn>, "sessionId">]; export interface RunSessionFunctions { /** * Run the Convex query with the given name and arguments. * * Consider using an {@link internalQuery} to prevent users from calling the * query directly. * * @param query - A {@link FunctionReference} for the query to run. * @param args - The arguments to the query function. * @returns A promise of the query's result. */ runSessionQuery<Query extends SessionFunction<"query">>(query: Query, ...args: SessionArgsArray<Query>): Promise<FunctionReturnType<Query>>; /** * Run the Convex mutation with the given name and arguments. * * Consider using an {@link internalMutation} to prevent users from calling * the mutation directly. * * @param mutation - A {@link FunctionReference} for the mutation to run. * @param args - The arguments to the mutation function. * @returns A promise of the mutation's result. */ runSessionMutation<Mutation extends SessionFunction<"mutation">>(mutation: Mutation, ...args: SessionArgsArray<Mutation>): Promise<FunctionReturnType<Mutation>>; /** * Run the Convex action with the given name and arguments. * * Consider using an {@link internalAction} to prevent users from calling the * action directly. * * @param action - A {@link FunctionReference} for the action to run. * @param args - The arguments to the action function. * @returns A promise of the action's result. */ runSessionAction<Action extends SessionFunction<"action">>(action: Action, ...args: SessionArgsArray<Action>): Promise<FunctionReturnType<Action>>; } export declare function runSessionFunctions<DataModel extends GenericDataModel>(ctx: GenericActionCtx<DataModel>, sessionId: SessionId): RunSessionFunctions; export {};