convex-helpers
Version:
A collection of useful code to complement the official convex package.
106 lines (105 loc) • 4.37 kB
TypeScript
/**
* 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 {};