<RIn, E, ROut>(self: Layer<ROut, E, RIn>): Effect<never, E, RIn>Builds this layer and keeps it alive until the returned effect is interrupted.
When to use
Use when you model your entire application as a layer, such as an HTTP server.
Details
When the returned effect is interrupted, the layer scope is closed and all finalizers registered during layer acquisition are run.
Example (Launching an application layer)
import { Console, Context, Effect, Layer } from "effect"
class HttpServer extends Context.Service<HttpServer, {
readonly start: () => Effect.Effect<string>
readonly stop: () => Effect.Effect<string>
}>()("HttpServer") {}
class Logger extends Context.Service<Logger, {
readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}
// Server layer that starts an HTTP server
const serverLayer = Layer.effect(HttpServer, Effect.gen(function*() {
yield* Console.log("Starting HTTP server...")
return {
start: Effect.fn("HttpServer.start")(function*() {
yield* Console.log("Server listening on port 3000")
return "Server started"
}),
stop: Effect.fn("HttpServer.stop")(function*() {
yield* Console.log("Server stopped gracefully")
return "Server stopped"
})
}
}))
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Console.log(`[LOG] ${msg}`))
})
// Application layer combining all services
const appLayer = Layer.mergeAll(serverLayer, loggerLayer)
// Launch the application - runs until interrupted
const application = appLayer.pipe(
Layer.launch,
Effect.tapError((error) => Console.log(`Application failed: ${error}`)),
Effect.tap(() => Console.log("Application completed"))
)
// This will run forever until externally interrupted
// Effect.runFork(application)export const const launch: <RIn, E, ROut>(
self: Layer<ROut, E, RIn>
) => Effect<never, E, RIn>
Builds this layer and keeps it alive until the returned effect is interrupted.
When to use
Use when you model your entire application as a layer, such as an HTTP
server.
Details
When the returned effect is interrupted, the layer scope is closed and all
finalizers registered during layer acquisition are run.
Example (Launching an application layer)
import { Console, Context, Effect, Layer } from "effect"
class HttpServer extends Context.Service<HttpServer, {
readonly start: () => Effect.Effect<string>
readonly stop: () => Effect.Effect<string>
}>()("HttpServer") {}
class Logger extends Context.Service<Logger, {
readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}
// Server layer that starts an HTTP server
const serverLayer = Layer.effect(HttpServer, Effect.gen(function*() {
yield* Console.log("Starting HTTP server...")
return {
start: Effect.fn("HttpServer.start")(function*() {
yield* Console.log("Server listening on port 3000")
return "Server started"
}),
stop: Effect.fn("HttpServer.stop")(function*() {
yield* Console.log("Server stopped gracefully")
return "Server stopped"
})
}
}))
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Console.log(`[LOG] ${msg}`))
})
// Application layer combining all services
const appLayer = Layer.mergeAll(serverLayer, loggerLayer)
// Launch the application - runs until interrupted
const application = appLayer.pipe(
Layer.launch,
Effect.tapError((error) => Console.log(`Application failed: ${error}`)),
Effect.tap(() => Console.log("Application completed"))
)
// This will run forever until externally interrupted
// Effect.runFork(application)
launch = <function (type parameter) RIn in <RIn, E, ROut>(self: Layer<ROut, E, RIn>): Effect<never, E, RIn>RIn, function (type parameter) E in <RIn, E, ROut>(self: Layer<ROut, E, RIn>): Effect<never, E, RIn>E, function (type parameter) ROut in <RIn, E, ROut>(self: Layer<ROut, E, RIn>): Effect<never, E, RIn>ROut>(self: Layer<ROut, E, RIn>(parameter) self: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<ROut>, E, RIn>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self: interface Layer<in ROut, out E = never, out RIn = never>A Layer describes how to build one or more services for dependency injection.
When to use
Use to model construction of application services for dependency injection,
especially when services have dependencies, can fail during construction, or
need scoped setup and release.
Details
A Layer<ROut, E, RIn> represents ROut as the services this layer
provides, E as the possible errors during layer construction, and RIn as
the services this layer requires as dependencies.
Layer<function (type parameter) ROut in <RIn, E, ROut>(self: Layer<ROut, E, RIn>): Effect<never, E, RIn>ROut, function (type parameter) E in <RIn, E, ROut>(self: Layer<ROut, E, RIn>): Effect<never, E, RIn>E, function (type parameter) RIn in <RIn, E, ROut>(self: Layer<ROut, E, RIn>): Effect<never, E, RIn>RIn>): import EffectEffect<never, function (type parameter) E in <RIn, E, ROut>(self: Layer<ROut, E, RIn>): Effect<never, E, RIn>E, function (type parameter) RIn in <RIn, E, ROut>(self: Layer<ROut, E, RIn>): Effect<never, E, RIn>RIn> =>
import internalEffectinternalEffect.const scoped: <A, E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<A, E, Exclude<R, Scope.Scope>>
scoped(import internalEffectinternalEffect.const andThen: {
<A, B, E2, R2>(
f: (a: A) => Effect.Effect<B, E2, R2>
): <E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<B, E | E2, R | R2>
<B, E2, R2>(f: Effect.Effect<B, E2, R2>): <
A,
E,
R
>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<B, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: (a: A) => Effect.Effect<B, E2, R2>
): Effect.Effect<B, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect.Effect<A, E, R>,
f: Effect.Effect<B, E2, R2>
): Effect.Effect<B, E | E2, R | R2>
}
andThen(const build: <RIn, E, ROut>(
self: Layer<ROut, E, RIn>
) => Effect<
Context.Context<ROut>,
E,
RIn | Scope.Scope
>
Builds a layer into a scoped value.
Example (Building a layer into a context)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
// Build a layer to get its services
const program = Effect.gen(function*() {
const dbLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed("result"))
})
// Build the layer into Context - automatically manages scope and memoization
const context = yield* Layer.build(dbLayer)
// Extract the specific service from the built layer
const database = Context.get(context, Database)
return yield* database.query("SELECT * FROM users")
})
build(self: Layer<ROut, E, RIn>(parameter) self: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<ROut>, E, RIn>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
self), import internalEffectinternalEffect.const never: Effect.Effect<never>const never: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
never))