-
-
Save adamgoose/58e2ba1c8160d9e4760eb075ff9e9d03 to your computer and use it in GitHub Desktop.
prisma + effect-ts integration - client which returns effects instead of promises
This file contains hidden or 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 { Data, Effect } from "effect"; | |
import { Prisma, 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> | |
? (...a: Args) => Effect.Effect<Result, PrismaError, never> | |
: 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]>; | |
}; | |
export class PrismaService extends Effect.Service<PrismaService>()("Prisma", { | |
sync: () => { | |
const prisma = new PrismaClient(); | |
return new Proxy( | |
{}, | |
{ | |
getOwnPropertyDescriptor() { | |
return { | |
enumerable: true, | |
configurable: true, | |
}; | |
}, | |
ownKeys() { | |
return Object.values(Prisma.ModelName); | |
}, | |
get(_target, model) { | |
return new Proxy( | |
{}, | |
{ | |
get(_target, method) { | |
return (...args: any[]) => | |
Effect.tryPromise(() => | |
(prisma as any)[model][method](...args), | |
); | |
}, | |
}, | |
); | |
}, | |
}, | |
) as EffectPrisma; | |
}, | |
}) {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment