UNPKG

convex

Version:

Client for the Convex Cloud

143 lines (136 loc) 4.84 kB
import { convexToJson, jsonToConvex } from "../../values/index.js"; import { GenericAPI } from "../../api/index.js"; import { GenericDataModel } from "../data_model.js"; import { ActionCtx, MutationCtx, PublicMutation, PublicAction, PublicQuery, QueryCtx, } from "../registration.js"; import { setupAuth, setupActionAuth } from "./authentication_impl.js"; import { setupReader, setupWriter } from "./database_impl.js"; import { setupActionDatabaseClient } from "./actions_impl.js"; async function invokeMutation< F extends (ctx: MutationCtx<GenericDataModel>, ...args: any) => any >(func: F, argsStr: string) { const args = jsonToConvex(JSON.parse(argsStr)); const mutationCtx = { db: setupWriter(), auth: setupAuth(), }; const result = await Promise.resolve(func(mutationCtx, ...(args as any))); return JSON.stringify(convexToJson(result === undefined ? null : result)); } /** * Define a mutation in this Convex app's public API. * * This function will be allowed to modify your Convex database and will be accessible from the client. * * If you're using code generation, use the `mutation` function in * `convex/_generated/server.d.ts` which is typed for your data model. * * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. * * @public */ export const mutationGeneric = < DataModel extends GenericDataModel, Args extends any[], Output >( func: (ctx: MutationCtx<DataModel>, ...args: Args) => Output ): PublicMutation<DataModel, Args, Output> => { const m = func as unknown as PublicMutation<DataModel, Args, Output>; // Helpful runtime check that functions are only be registered once if (m.isRegistered) { throw new Error("Function registered twice " + func); } m.isRegistered = true; m.isMutation = true; m.invokeMutation = argsStr => invokeMutation(func as any, argsStr); return m; }; async function invokeQuery< F extends (ctx: QueryCtx<GenericDataModel>, ...args: any) => any >(func: F, argsStr: string) { const args = jsonToConvex(JSON.parse(argsStr)); const queryCtx = { db: setupReader(), auth: setupAuth(), }; const result = await Promise.resolve(func(queryCtx, ...(args as any))); return JSON.stringify(convexToJson(result === undefined ? null : result)); } /** * Define a query in this Convex app's public API. * * This function will be allowed to read your Convex database and will be accessible from the client. * * If you're using code generation, use the `query` function in * `convex/_generated/server.d.ts` which is typed for your data model. * * @param func - The query function. It receives a {@link QueryCtx} as its first argument. * @returns The wrapped query. Include this as an `export` to name it and make it accessible. * * @public */ export const queryGeneric = < DataModel extends GenericDataModel, Args extends any[], Output >( func: (ctx: QueryCtx<DataModel>, ...args: Args) => Output ): PublicQuery<DataModel, Args, Output> => { const q = func as unknown as PublicQuery<DataModel, Args, Output>; // Helpful runtime check that functions are only be registered once if (q.isRegistered) { throw new Error("Function registered twice " + func); } q.isRegistered = true; q.isQuery = true; q.invokeQuery = argsStr => invokeQuery(func as any, argsStr); return q; }; async function invokeAction< API extends GenericAPI, F extends (ctx: ActionCtx<API>, ...args: any) => any >(func: F, requestId: string, argsStr: string) { const args = jsonToConvex(JSON.parse(argsStr)); const databaseClient = setupActionDatabaseClient(requestId); const ctx = { query: databaseClient.query, mutation: databaseClient.mutation, auth: setupActionAuth(requestId), }; const result = await Promise.resolve(func(ctx, ...(args as any))); return JSON.stringify(convexToJson(result === undefined ? null : result)); } /** * Define function in this Convex app's public API. * * @param func - The function. It receives a {@link ActionCtx} as its first argument. * @returns The wrapped function. Include this as an `export` to name it and make it accessible. * * @public */ export const actionGeneric = < API extends GenericAPI, Args extends any[], Output >( func: (ctx: ActionCtx<API>, ...args: Args) => Output ): PublicAction<API, Args, Output> => { const q = func as unknown as PublicAction<API, Args, Output>; // Helpful runtime check that functions are only be registered once if (q.isRegistered) { throw new Error("Function registered twice " + func); } q.isRegistered = true; q.isAction = true; q.invokeAction = (requestId, argsStr) => invokeAction(func as any, requestId, argsStr); return q; };