Created
October 27, 2023 14:59
-
-
Save arekmaz/6fdcf9e84e7f7a46172ce256e81a403b to your computer and use it in GitHub Desktop.
prisma + effect-ts integration - client which returns effects instead of promises
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { db } from "../services/db.server"; | |
import { Data, Effect } from "effect"; | |
import type { PrismaClient } from "@prisma/client"; | |
import type { | |
PrismaClientKnownRequestError, | |
PrismaClientUnknownRequestError, | |
PrismaClientRustPanicError, | |
PrismaClientInitializationError, | |
PrismaClientValidationError, | |
} from "@prisma/client/runtime/library"; | |
export class PrismaError extends Data.TaggedError("PrismaError")<{ | |
details: | |
| PrismaClientKnownRequestError | |
| PrismaClientUnknownRequestError | |
| PrismaClientRustPanicError | |
| PrismaClientInitializationError | |
| PrismaClientValidationError; | |
}> {} | |
type FilterNotContaining< | |
Set, | |
Needle extends string | |
// eslint-disable-next-line @typescript-eslint/no-unused-vars | |
> = Set extends `${infer _A}${Needle}${infer _B}` ? never : Set; | |
type ExcludeFromUnionOtherTypes<From, E> = From extends E ? From : never; | |
type ExcludeNonStringKeys<Obj> = { | |
[k in ExcludeFromUnionOtherTypes<keyof Obj, string>]: k extends string | |
? Obj[k] | |
: never; | |
}; | |
type ExcludeKeysContaining< | |
Obj extends Record<string, any>, | |
Key extends string | |
> = { | |
[key in FilterNotContaining<keyof Obj, Key>]: Obj[key]; | |
}; | |
export type Client = ExcludeKeysContaining< | |
ExcludeNonStringKeys<PrismaClient>, | |
"$" | "_" | |
> & {}; | |
type LazyPromiseToLazyEffect<Fn extends (...a: any[]) => any> = Fn extends ( | |
...a: infer Args | |
) => Promise<infer Result> | |
? <R, E>(...a: Args) => Effect.Effect<R, E, Result> | |
: never; | |
type EffectifyObject< | |
Obj extends Record<string, F>, | |
F extends (...a: any[]) => any = any | |
> = { | |
[op in keyof Obj]: LazyPromiseToLazyEffect<Obj[op]>; | |
}; | |
type EffectPrisma = { | |
[model in keyof Client]: EffectifyObject<Client[model]>; | |
}; | |
const createEffectClient = () => { | |
return new Proxy( | |
{}, | |
{ | |
get(_target, model) { | |
return new Proxy( | |
{}, | |
{ | |
get(_target, method) { | |
return (...args: any[]) => | |
Effect.tryPromise(() => (db as any)[model][method](...args)); | |
}, | |
} | |
); | |
}, | |
} | |
) as EffectPrisma; | |
}; | |
// example usage: | |
// standard prisma: | |
const a = await db.log.findMany(); | |
// a: { | |
// id: number; | |
// date: Date; | |
// login: string | null; | |
// info: string | null; | |
// }[] | |
// standard prisma: | |
const e = createEffectClient().log.findMany(); | |
// Effect.Effect<unknown, unknown, { | |
// id: number; | |
// date: Date; | |
// login: string | null; | |
// info: string | null; | |
// }[]> | |
const e1 = createEffectClient().log.findMany<never, PrismaError>(); | |
// Effect.Effect<never, PrismaError, { | |
// id: number; | |
// date: Date; | |
// login: string | null; | |
// info: string | null; | |
// }[]> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Working in 2025: