import * as Ref from "@confect/core/Ref";
import type { GenericActionCtx } from "convex/server";
import * as Context from "effect/Context";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import type * as Schema from "effect/Schema";
import * as MutationTransactionContext from "./MutationTransactionContext";
import * as QueryTransactionContext from "./QueryTransactionContext";
export type Options = MutationTransactionContext.QueryOptions;
const run = Effect.fn("QueryRunner.runQuery")(
(effect: Effect.Effect): Effect.Effect => effect,
);
const make = (nativeRunQuery: GenericActionCtx["runQuery"]) => {
function runQuery(
query: Query,
...args: [...Ref.OptionalArgs, options?: undefined]
): Effect.Effect, Ref.Error | Schema.SchemaError>;
function runQuery(
query: Query,
args: Ref.Args,
options:
| (QueryTransactionContext.Options & {
readonly useStaleSnapshot?: never;
})
| undefined,
): Effect.Effect<
Ref.Returns,
Ref.Error | Schema.SchemaError,
QueryTransactionContext.QueryTransactionContext
>;
function runQuery(
query: Query,
args: Ref.Args,
options: Options & { readonly useStaleSnapshot: boolean },
): Effect.Effect<
Ref.Returns,
Ref.Error | Schema.SchemaError,
MutationTransactionContext.MutationTransactionContext
>;
function runQuery(
query: Query,
args: Ref.Args,
options: Options | undefined,
): Effect.Effect<
Ref.Returns,
Ref.Error | Schema.SchemaError,
| QueryTransactionContext.QueryTransactionContext
| MutationTransactionContext.MutationTransactionContext
>;
function runQuery(
query: Query,
args?: Ref.Args,
options?: Options,
): Effect.Effect<
Ref.Returns,
Ref.Error | Schema.SchemaError,
| QueryTransactionContext.QueryTransactionContext
| MutationTransactionContext.MutationTransactionContext
> {
return run(
Effect.gen(function* () {
const actualArgs = (args ?? {}) as Ref.Args;
if (options?.useStaleSnapshot !== undefined) {
const controls =
yield* MutationTransactionContext.MutationTransactionContext;
return yield* controls.runQuery(query, actualArgs, options);
}
if (options !== undefined) {
const controls =
yield* QueryTransactionContext.QueryTransactionContext;
return yield* controls.runQuery(query, actualArgs, options);
}
return yield* Ref.runWithCodec(query, actualArgs, (ref, encodedArgs) =>
nativeRunQuery(ref, encodedArgs),
);
}),
);
}
return { runQuery };
};
export const QueryRunner = Context.Service>(
"@confect/server/QueryRunner",
);
export type QueryRunner = typeof QueryRunner.Identifier;
export const layer = (runQuery: GenericActionCtx["runQuery"]) =>
Layer.succeed(QueryRunner, make(runQuery));