Hyperlinkv0.8.0-beta.28

Layer

Layer.flatMapconsteffect/Layer.ts:1598
<A, A2, E2, R2>(f: (context: Context.Context<A>) => Layer<A2, E2, R2>): <
  E,
  R
>(
  self: Layer<A, E, R>
) => Layer<A2, E2 | E, R2 | R>
<A, E, R, A2, E2, R2>(
  self: Layer<A, E, R>,
  f: (context: Context.Context<A>) => Layer<A2, E2, R2>
): Layer<A2, E | E2, R | R2>

Constructs a layer dynamically based on the output of this layer.

Example (Creating services from layer output)

import { Context, Effect, Layer } from "effect"

class Config extends Context.Service<Config, {
  readonly dbUrl: string
  readonly logLevel: string
}>()("Config") {}

class Database extends Context.Service<Database, {
  readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}

class Logger extends Context.Service<Logger, {
  readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}

// Base config layer
const configLayer = Layer.succeed(Config, {
  dbUrl: "postgres://localhost:5432/mydb",
  logLevel: "debug"
})

// Dynamically create services based on config
const dynamicServiceLayer = configLayer.pipe(
  Layer.flatMap((context) => {
    const config = Context.get(context, Config)

    // Create database layer based on config
    const dbLayer = Layer.succeed(Database, {
      query: Effect.fn("Database.query")((sql: string) =>
        Effect.succeed(
          `Querying ${config.dbUrl}: ${sql}`
        ))
    })

    // Create logger layer based on config
    const loggerLayer = Layer.succeed(Logger, {
      log: Effect.fn("Logger.log")((msg: string) =>
        config.logLevel === "debug"
          ? Effect.sync(() => console.log(`[DEBUG] ${msg}`))
          : Effect.sync(() => console.log(msg))
      )
    })

    // Return combined layer
    return Layer.mergeAll(dbLayer, loggerLayer)
  })
)

// Use the dynamic services
const program = Effect.gen(function*() {
  const database = yield* Database
  const logger = yield* Logger

  yield* logger.log("Starting database query")
  const result = yield* database.query("SELECT * FROM users")

  return result
}).pipe(
  Effect.provide(dynamicServiceLayer)
)
sequencing
Source effect/Layer.ts:159818 lines
export const flatMap: {
  <A, A2, E2, R2>(
    f: (context: Context.Context<A>) => Layer<A2, E2, R2>
  ): <E, R>(self: Layer<A, E, R>) => Layer<A2, E2 | E, R2 | R>
  <A, E, R, A2, E2, R2>(
    self: Layer<A, E, R>,
    f: (context: Context.Context<A>) => Layer<A2, E2, R2>
  ): Layer<A2, E | E2, R | R2>
} = dual(2, <A, E, R, A2, E2, R2>(
  self: Layer<A, E, R>,
  f: (context: Context.Context<A>) => Layer<A2, E2, R2>
): Layer<A2, E | E2, R | R2> =>
  fromBuild((memoMap, scope) =>
    internalEffect.flatMap(
      self.build(memoMap, scope),
      (context) => f(context).build(memoMap, scope)
    )
  ))
Referenced by 1 symbols