import { Prisma } from "@prisma/client"; import type { Replace, UnionToTuple } from "type-fest"; import { Effect, Option } from "effect"; import { UnknownException } from "effect/Cause"; type PrismaModelOp = Exclude< // You can import operation types from the generated Prisma client Operation, | "$executeRaw" | "$executeRawUnsafe" | "$queryRaw" | "$queryRawUnsafe" | "$runCommandRaw" | "aggregateRaw" | "findFirst" | "findFirstOrThrow" | "findRaw" | "findUnique" | "findUniqueOrThrow" >; const PrismaModelOps: UnionToTuple = [ "findMany", "create", "createMany", "createManyAndReturn", "update", "updateMany", "updateManyAndReturn", "upsert", "delete", "deleteMany", "aggregate", "count", "groupBy", ] as const; export const prismaEffectExtension = { client: { // $executeRaw: (query: TemplateStringsArray | Sql, ...values: any[]) => PrismaPromise $executeRawEffect: function ( this: T, // This type will work after generating the Prisma client query: Prisma.Sql | TemplateStringsArray, // eslint-disable-next-line @typescript-eslint/no-explicit-any ...values: any[] ): Effect.Effect { return Effect.tryPromise(() => { const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance return prismaExtensionContextClient["$executeRaw"](query, ...values); }); }, // $executeRawUnsafe: (query: string, ...values: any[]) => PrismaPromise $executeRawUnsafeEffect: function ( this: T, query: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any ...values: any[] ): Effect.Effect { return Effect.tryPromise(() => { const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance return prismaExtensionContextClient["$executeRawUnsafe"]( query, ...values ); }); }, // $queryRaw: (query: TemplateStringsArray | Sql, ...values: any[]) => PrismaPromise // eslint-disable-next-line @typescript-eslint/no-explicit-any $queryRawEffect: function ( this: T, query: Prisma.Sql | TemplateStringsArray, // eslint-disable-next-line @typescript-eslint/no-explicit-any ...values: any[] ): Effect.Effect { return Effect.tryPromise(() => { const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance return prismaExtensionContextClient["$queryRaw"](query, ...values); }); }, // $queryRawTyped: (query: TypedSql) => PrismaPromise // eslint-disable-next-line @typescript-eslint/no-explicit-any $queryRawTypedEffect: function ( this: T, query: TypedSql ): Effect.Effect { return Effect.tryPromise(() => { const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance return prismaExtensionContextClient["$queryRawTyped"](query); }); }, // $queryRawUnsafe: (query: string, ...values: any[]) => PrismaPromise // eslint-disable-next-line @typescript-eslint/no-explicit-any $queryRawUnsafeEffect: function ( this: T, query: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any ...values: any[] ): Effect.Effect { return Effect.tryPromise(() => { const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance return prismaExtensionContextClient["$queryRawUnsafe"]( query, ...values ); }); }, }, model: { $allModels: { ...(Object.fromEntries( PrismaModelOps.map((method) => [ `${method}Effect`, function ( // `this` is the current type (for example // it might be `prisma.user` at runtime). this: T, x?: Prisma.Exact< A, // For `customCall`, use the arguments from model `T` and the // operation `findFirst`. Add `customProperty` to the operation. Prisma.Args > // Get the correct result types for the model of type `T`, // and the arguments of type `A` for `findFirst`. // `Prisma.Result` computes the result for a given operation // such as `select {id: true}` in function `main` below. //, ): Effect.Effect, UnknownException, never> { return Effect.tryPromise>(() => { // eslint-disable-next-line no-invalid-this const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance // eslint-disable-next-line @typescript-eslint/no-explicit-any return prismaExtensionContextClient[method](x) as any; }); }, ]) ) as { [K in `${(typeof PrismaModelOps)[number]}Effect`]: < T, A, O extends Replace, >( this: T, x?: Prisma.Exact> ) => Effect.Effect, UnknownException, never>; }), findFirstEffect( this: T, x?: Prisma.Exact> ): Effect.Effect, UnknownException, never> { return Effect.tryPromise>(() => { const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance return prismaExtensionContextClient.findFirstOrThrow(x); }); }, findFirstOption( this: T, x?: Prisma.Exact> ): Effect.Effect< Option.Option>>, UnknownException, never > { return Effect.tryPromise>(() => { const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance return prismaExtensionContextClient.findFirst(x); }).pipe(Effect.map((result) => Option.fromNullable(result))); }, findUniqueEffect( this: T, x?: Prisma.Exact> ): Effect.Effect, UnknownException, never> { return Effect.tryPromise>(() => { const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance return prismaExtensionContextClient.findUniqueOrThrow(x); }); }, findUniqueOption( this: T, x?: Prisma.Exact> ): Effect.Effect< Option.Option>>, UnknownException, never > { return Effect.tryPromise>(() => { const prismaExtensionContextClient = Prisma.getExtensionContext(this); // @ts-expect-error Can't predict these in advance return prismaExtensionContextClient.findUnique(x); }).pipe(Effect.map((result) => Option.fromNullable(result))); }, }, }, };