Creating Runtime-Dependent Layers in Cloudflare Workers

Is it possible to make a layer that depends on a runtime input?
I'm using Cloudflare Workers, which provides the database instance like this:
async fetch(request, env) {
  await env.DB.exec(...);
}

I need to use several env.<service> instances in different part of the code. In order to avoid having to pass env to each layer, I've attempted to do this:
export class WorkerEnv extends Context.Tag("WorkerEnv")<
  WorkerEnv,
  { getBinding: <T>(key: string, type: T) => T }
>() {
  static Live = (env: unknown) =>
    Layer.effect(
      this,
      E.succeed({
        // TODO: parse and validate
        getBinding: <T>(key: string): T => env[key] as T
      }),
    )
}

but I get an error here:
const D1Live = D1Client.layer({
  // error below at `db`: Property '[ConfigTypeId]' is missing in type 'Effect<any, never, WorkerEnv>' but required in type 'Config<D1Database>'
  db: Effect.gen(function* () {
    const env = yield* WorkerEnv
    return env.getBinding<D1Database>("DB")
  }),
})
export const DatabaseLive = SqliteDrizzle.layer.pipe(Layer.provide(D1Live))

I attempted to use the Config module, but as far as I could tell, it doesn't seem to like the fact the initial env.DB value isn't a string.

Questions:
(a) is it correct to define a layer like WorkerEnv.Live above that accepts an arg? (I'm passing env to it)
(b) is it possible to fix the error? or do I need to change both D1Live and DatabaseLive to functions accepting an env arg as well?
Was this page helpful?