Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save hiramhuang/779ec74a7548c4d5cfc127e5606e0ca4 to your computer and use it in GitHub Desktop.
Save hiramhuang/779ec74a7548c4d5cfc127e5606e0ca4 to your computer and use it in GitHub Desktop.
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<PrismaModelOp> = [
"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<number>
$executeRawEffect: function <T>(
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<number, UnknownException, never> {
return Effect.tryPromise<number>(() => {
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<number>
$executeRawUnsafeEffect: function <T>(
this: T,
query: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...values: any[]
): Effect.Effect<number, UnknownException, never> {
return Effect.tryPromise<number>(() => {
const prismaExtensionContextClient = Prisma.getExtensionContext(this);
// @ts-expect-error Can't predict these in advance
return prismaExtensionContextClient["$executeRawUnsafe"](
query,
...values
);
});
},
// $queryRaw: <T = unknown>(query: TemplateStringsArray | Sql, ...values: any[]) => PrismaPromise<T>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
$queryRawEffect: function <A = unknown, T = any>(
this: T,
query: Prisma.Sql | TemplateStringsArray,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...values: any[]
): Effect.Effect<A, UnknownException, never> {
return Effect.tryPromise<A>(() => {
const prismaExtensionContextClient = Prisma.getExtensionContext(this);
// @ts-expect-error Can't predict these in advance
return prismaExtensionContextClient["$queryRaw"](query, ...values);
});
},
// $queryRawTyped: <T>(query: TypedSql<unknown[], T>) => PrismaPromise<T[]>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
$queryRawTypedEffect: function <A = unknown, T = any>(
this: T,
query: TypedSql<unknown[], T>
): Effect.Effect<A, UnknownException, never> {
return Effect.tryPromise<A>(() => {
const prismaExtensionContextClient = Prisma.getExtensionContext(this);
// @ts-expect-error Can't predict these in advance
return prismaExtensionContextClient["$queryRawTyped"](query);
});
},
// $queryRawUnsafe: <T = unknown>(query: string, ...values: any[]) => PrismaPromise<T>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
$queryRawUnsafeEffect: function <A = unknown, T = any>(
this: T,
query: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...values: any[]
): Effect.Effect<A, UnknownException, never> {
return Effect.tryPromise<A>(() => {
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 <T, A, O extends typeof method>(
// `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<T, O>
>
// 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<Prisma.Result<T, A, O>, UnknownException, never> {
return Effect.tryPromise<Prisma.Result<T, A, O>>(() => {
// 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<K, "Effect", "">,
>(
this: T,
x?: Prisma.Exact<A, Prisma.Args<T, O>>
) => Effect.Effect<Prisma.Result<T, A, O>, UnknownException, never>;
}),
findFirstEffect<T, A, O extends "findFirstOrThrow">(
this: T,
x?: Prisma.Exact<A, Prisma.Args<T, O>>
): Effect.Effect<Prisma.Result<T, A, O>, UnknownException, never> {
return Effect.tryPromise<Prisma.Result<T, A, O>>(() => {
const prismaExtensionContextClient = Prisma.getExtensionContext(this);
// @ts-expect-error Can't predict these in advance
return prismaExtensionContextClient.findFirstOrThrow(x);
});
},
findFirstOption<T, A, O extends "findFirst">(
this: T,
x?: Prisma.Exact<A, Prisma.Args<T, O>>
): Effect.Effect<
Option.Option<NonNullable<Prisma.Result<T, A, O>>>,
UnknownException,
never
> {
return Effect.tryPromise<Prisma.Result<T, A, O>>(() => {
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<T, A, O extends "findUniqueOrThrow">(
this: T,
x?: Prisma.Exact<A, Prisma.Args<T, O>>
): Effect.Effect<Prisma.Result<T, A, O>, UnknownException, never> {
return Effect.tryPromise<Prisma.Result<T, A, O>>(() => {
const prismaExtensionContextClient = Prisma.getExtensionContext(this);
// @ts-expect-error Can't predict these in advance
return prismaExtensionContextClient.findUniqueOrThrow(x);
});
},
findUniqueOption<T, A, O extends "findUnique">(
this: T,
x?: Prisma.Exact<A, Prisma.Args<T, O>>
): Effect.Effect<
Option.Option<NonNullable<Prisma.Result<T, A, O>>>,
UnknownException,
never
> {
return Effect.tryPromise<Prisma.Result<T, A, O>>(() => {
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)));
},
},
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment