How to Temporarily Override a Layer at Runtime in Effect Typescript

Question from X: Is it possible to temporarily override a layer at runtime?
For example, I have a Prisma service that sometimes I want to override the prisma context to be a prisma transaction context.
I don't want to have to call runPromise again though because I understand thats bad

import { Effect, Layer } from "effect"
import { DatabaseClientTag } from "@myapp/db"
import { TransactionServiceTag, TransactionError } from "@myapp/contracts"

export const TransactionServiceLive = Layer.effect(
  TransactionServiceTag,
  Effect.gen(function* () {
    const { prisma } = yield* DatabaseClientTag
    
    return {
      withTransaction: <A, E, R>(
        operation: Effect.Effect<A, E, R>
      ): Effect.Effect<A, E | TransactionError, R> =>
        Effect.async<A, E | TransactionError, R>((resume) => {
          prisma.$transaction(async (tx) => {
            try {
              // Create transaction layer
              const transactionLayer = Layer.succeed(
                DatabaseClientTag,
                { prisma: tx }
              )
              
              // Provide transaction layer to the operation
              const result = await Effect.runPromise(
                Effect.provide(operation, transactionLayer)
              )
              
              resume(Effect.succeed(result))
            } catch (error) {
              resume(Effect.fail(new TransactionError(`Transaction failed: ${error}`)))
            }
          }).catch((error) => {
            resume(Effect.fail(new TransactionError(`Transaction setup failed: ${error}`)))
          })
        })
    }
  })
)
Was this page helpful?