import { actionGeneric, type DefaultFunctionArgs, type GenericActionCtx, type GenericMutationCtx, type GenericQueryCtx, internalActionGeneric, internalMutationGeneric, internalQueryGeneric, mutationGeneric, queryGeneric, type RegisteredAction, type RegisteredMutation, type RegisteredQuery, } from "convex/server"; import { Effect, pipe, Schema } from "effect"; import { ConfectActionCtx, ConfectMutationCtx, ConfectQueryCtx, makeConfectActionCtx, makeConfectMutationCtx, makeConfectQueryCtx, } from "~/src/server/ctx"; import type { DataModelFromConfectDataModel, GenericConfectDataModel, } from "~/src/server/data-model"; import { type DatabaseSchemasFromConfectDataModel, databaseSchemasFromConfectSchema, } from "~/src/server/database"; import type { ConfectDataModelFromConfectSchema, ConfectSchemaDefinition, GenericConfectSchema, } from "~/src/server/schema"; import { compileArgsSchema, compileReturnsSchema, } from "~/src/server/schema-to-validator"; export const makeFunctions = ( confectSchemaDefinition: ConfectSchemaDefinition, ) => { const databaseSchemas = databaseSchemasFromConfectSchema( confectSchemaDefinition.confectSchema, ); const query = < ConvexArgs extends DefaultFunctionArgs, ConfectArgs, ConvexReturns, ConfectReturns, E, >({ args, returns, handler, }: { args: Schema.Schema; returns: Schema.Schema; handler: ( a: ConfectArgs, ) => Effect.Effect< ConfectReturns, E, ConfectQueryCtx> >; }): RegisteredQuery<"public", ConvexArgs, Promise> => queryGeneric( confectQueryFunction({ databaseSchemas, args, returns, handler }), ); const internalQuery = < ConvexArgs extends DefaultFunctionArgs, ConfectArgs, ConvexReturns, ConfectReturns, E, >({ args, handler, returns, }: { args: Schema.Schema; returns: Schema.Schema; handler: ( a: ConfectArgs, ) => Effect.Effect< ConfectReturns, E, ConfectQueryCtx> >; }): RegisteredQuery<"internal", ConvexArgs, Promise> => internalQueryGeneric( confectQueryFunction({ databaseSchemas, args, returns, handler }), ); const mutation = < ConvexValue extends DefaultFunctionArgs, ConfectValue, ConvexReturns, ConfectReturns, E, >({ args, returns, handler, }: { args: Schema.Schema; returns: Schema.Schema; handler: ( a: ConfectValue, ) => Effect.Effect< ConfectReturns, E, | ConfectQueryCtx> | ConfectMutationCtx> >; }): RegisteredMutation<"public", ConvexValue, Promise> => mutationGeneric( confectMutationFunction({ databaseSchemas, args, returns, handler }), ); const internalMutation = < ConvexValue extends DefaultFunctionArgs, ConfectValue, ConvexReturns, ConfectReturns, E, >({ args, returns, handler, }: { args: Schema.Schema; returns: Schema.Schema; handler: ( a: ConfectValue, ) => Effect.Effect< ConfectReturns, E, | ConfectQueryCtx> | ConfectMutationCtx> >; }): RegisteredMutation<"internal", ConvexValue, Promise> => internalMutationGeneric( confectMutationFunction({ databaseSchemas, args, returns, handler }), ); const action = < ConvexValue extends DefaultFunctionArgs, ConfectValue, ConvexReturns, ConfectReturns, E, >({ args, returns, handler, }: { args: Schema.Schema; returns: Schema.Schema; handler: ( a: ConfectValue, ) => Effect.Effect< ConfectReturns, E, ConfectActionCtx> >; }): RegisteredAction<"public", ConvexValue, Promise> => actionGeneric(confectActionFunction({ args, returns, handler })); const internalAction = < ConvexValue extends DefaultFunctionArgs, ConfectValue, ConvexReturns, ConfectReturns, E, >({ args, returns, handler, }: { args: Schema.Schema; returns: Schema.Schema; handler: ( a: ConfectValue, ) => Effect.Effect< ConfectReturns, E, ConfectActionCtx> >; }): RegisteredAction<"internal", ConvexValue, Promise> => internalActionGeneric(confectActionFunction({ args, returns, handler })); return { query, internalQuery, mutation, internalMutation, action, internalAction, }; }; const confectQueryFunction = < ConfectDataModel extends GenericConfectDataModel, ConvexArgs extends DefaultFunctionArgs, ConfectArgs, ConvexReturns, ConfectReturns, E, >({ databaseSchemas, args, returns, handler, }: { databaseSchemas: DatabaseSchemasFromConfectDataModel; args: Schema.Schema; returns: Schema.Schema; handler: ( a: ConfectArgs, ) => Effect.Effect>; }) => ({ args: compileArgsSchema(args), returns: compileReturnsSchema(returns), handler: ( ctx: GenericQueryCtx>, actualArgs: ConvexArgs, ): Promise => pipe( actualArgs, Schema.decode(args), Effect.orDie, Effect.andThen((decodedArgs) => handler(decodedArgs).pipe( Effect.provideService( ConfectQueryCtx(), makeConfectQueryCtx(ctx, databaseSchemas), ), ), ), Effect.andThen((convexReturns) => Schema.encodeUnknown(returns)(convexReturns), ), Effect.runPromise, ), }); const confectMutationFunction = < ConfectDataModel extends GenericConfectDataModel, ConvexValue extends DefaultFunctionArgs, ConfectValue, ConvexReturns, ConfectReturns, E, >({ databaseSchemas, args, returns, handler, }: { databaseSchemas: DatabaseSchemasFromConfectDataModel; args: Schema.Schema; returns: Schema.Schema; handler: ( a: ConfectValue, ) => Effect.Effect< ConfectReturns, E, ConfectQueryCtx | ConfectMutationCtx >; }) => ({ args: compileArgsSchema(args), returns: compileReturnsSchema(returns), handler: ( ctx: GenericMutationCtx>, actualArgs: ConvexValue, ): Promise => pipe( actualArgs, Schema.decode(args), Effect.orDie, Effect.andThen((decodedArgs) => handler(decodedArgs).pipe( Effect.provideService( ConfectQueryCtx(), makeConfectQueryCtx(ctx, databaseSchemas), ), Effect.provideService( ConfectMutationCtx(), makeConfectMutationCtx(ctx, databaseSchemas), ), ), ), Effect.andThen((convexReturns) => Schema.encodeUnknown(returns)(convexReturns), ), Effect.runPromise, ), }); const confectActionFunction = < ConfectDataModel extends GenericConfectDataModel, ConvexValue extends DefaultFunctionArgs, ConfectValue, ConvexReturns, ConfectReturns, E, >({ args, returns, handler, }: { args: Schema.Schema; returns: Schema.Schema; handler: ( a: ConfectValue, ) => Effect.Effect>; }) => ({ args: compileArgsSchema(args), returns: compileReturnsSchema(returns), handler: ( ctx: GenericActionCtx>, actualArgs: ConvexValue, ): Promise => pipe( actualArgs, Schema.decode(args), Effect.orDie, Effect.andThen((decodedArgs) => handler(decodedArgs).pipe( Effect.provideService( ConfectActionCtx(), makeConfectActionCtx(ctx), ), ), ), Effect.andThen((convexReturns) => Schema.encodeUnknown(returns)(convexReturns), ), Effect.runPromise, ), });