Layer.Layer<
| HttpPlatform.HttpPlatform
| Etag.Generator
| FileSystem.FileSystem
| Path.Path
| HttpServer.HttpServer
| HttpClient,
ServeError,
never
>Provides a test HTTP server listening on an ephemeral port together with a
Fetch-backed HttpClient configured for server integration tests.
export const const layerTest: Layer.Layer<
| HttpServer.HttpServer
| FileSystem.FileSystem
| Path.Path
| HttpPlatform.HttpPlatform
| Etag.Generator
| HttpClient,
ServeError,
never
>
const layerTest: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<FileSystem | Path | Generator | HttpClient | HttpPlatform | HttpServer>, ServeError, 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; <…;
}
Provides a test HTTP server listening on an ephemeral port together with a
Fetch-backed HttpClient configured for server integration tests.
layerTest: import LayerLayer.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<
| import HttpServerHttpServer.class HttpServerclass HttpServer {
key: Identifier;
Service: {
serve: { <E, R>(effect: Effect.Effect<HttpServerResponse, E, R>): Effect.Effect<void, never, Exclude<R, HttpServerRequest> | Scope.Scope>; <E, R, App extends Effect.Effect<HttpServerResponse, any, any>>(effect: Effect.Effect<HttpServerResponse, E…;
address: Address;
};
}
Service tag for an HTTP server runtime.
Details
The service can serve an HTTP response effect and exposes the address where the
server is listening.
HttpServer
| import FileSystemFileSystem.FileSystem
| import PathPath.Path
| import HttpPlatformHttpPlatform.class HttpPlatformclass HttpPlatform {
key: Identifier;
Service: {
fileResponse: (path: string, options?: Response.Options.WithContent & { readonly bytesToRead?: FileSystem.SizeInput | undefined; readonly chunkSize?: FileSystem.SizeInput | undefined; readonly offset?: FileSystem.SizeInput | undefined }) => Effect.Effec…;
fileWebResponse: (file: Body.HttpBody.FileLike, options?: Response.Options.WithContent & { readonly bytesToRead?: FileSystem.SizeInput | undefined; readonly chunkSize?: FileSystem.SizeInput | undefined; readonly offset?: FileSystem.SizeInput | undefined })…;
};
}
Service for platform-specific HTTP response helpers, including file-backed server responses.
HttpPlatform
| import EtagEtag.class Generatorclass Generator {
key: Identifier;
Service: {
fromFileInfo: (info: FileSystem.File.Info) => Effect.Effect<Etag>;
fromFileWeb: (file: Body.HttpBody.FileLike) => Effect.Effect<Etag>;
};
}
Service for generating ETags from filesystem file information or Web File-like metadata.
Generator
| HttpClient,
class ServeErrorclass ServeError {
name: string;
message: string;
stack: string;
cause: unknown;
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;
_tag: Tag;
}
Error wrapping a low-level failure from the HTTP server implementation.
ServeError,
never
> = import HttpServerHttpServer.const layerTestClient: Layer.Layer<
HttpClient.HttpClient,
never,
HttpServer | HttpClient.HttpClient
>
const layerTestClient: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<HttpClient>, never, HttpClient | HttpServer>;
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; <…;
}
Layer that provides the test HttpClient created by makeTestClient.
layerTestClient.Pipeable.pipe<Layer.Layer<HttpClient, never, HttpClient | HttpServer.HttpServer>, Layer.Layer<HttpClient, never, HttpServer.HttpServer>, Layer.Layer<HttpClient | HttpServer.HttpServer | NodeServices.NodeServices | HttpPlatform.HttpPlatform | Etag.Generator, ServeError, never>>(this: Layer.Layer<...>, ab: (_: Layer.Layer<HttpClient, never, HttpClient | HttpServer.HttpServer>) => Layer.Layer<...>, bc: (_: Layer.Layer<...>) => Layer.Layer<...>): Layer.Layer<...> (+21 overloads)pipe(
import LayerLayer.const provide: {
<RIn, E, ROut>(that: Layer<ROut, E, RIn>): <
RIn2,
E2,
ROut2
>(
self: Layer<ROut2, E2, RIn2>
) => Layer<
ROut2,
E | E2,
RIn | Exclude<RIn2, ROut>
>
<Layers extends [Any, ...Array<Any>]>(
that: Layers
): <A, E, R>(
self: Layer<A, E, R>
) => Layer<
A,
E | Error<Layers[number]>,
| Services<Layers[number]>
| Exclude<R, Success<Layers[number]>>
>
<RIn2, E2, ROut2, RIn, E, ROut>(
self: Layer<ROut2, E2, RIn2>,
that: Layer<ROut, E, RIn>
): Layer<
ROut2,
E | E2,
RIn | Exclude<RIn2, ROut>
>
<A, E, R, Layers extends [Any, ...Array<Any>]>(
self: Layer<A, E, R>,
that: Layers
): Layer<
A,
E | Error<Layers[number]>,
| Services<Layers[number]>
| Exclude<R, Success<Layers[number]>>
>
}
Feeds the output services of the dependency layer into the requirements of
this layer, returning a layer that only provides the services from this layer.
When to use
Use when you need to hide an implementation dependency layer from callers.
Details
In serviceLayer.pipe(Layer.provide(dependencyLayer)), the dependency layer is
built first and is used to satisfy the requirements of serviceLayer.
Example (Providing layer dependencies)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
class UserService extends Context.Service<UserService, {
readonly getUser: (id: string) => Effect.Effect<{
id: string
name: string
}>
}>()("UserService") {}
class Logger extends Context.Service<Logger, {
readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}
// Create dependency layers
const databaseLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`DB: ${sql}`))
})
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => console.log(`[LOG] ${msg}`)))
})
// UserService depends on Database and Logger
const userServiceLayer = Layer.effect(UserService, Effect.gen(function*() {
const database = yield* Database
const logger = yield* Logger
return {
getUser: Effect.fn("UserService.getUser")(function*(id: string) {
yield* logger.log(`Looking up user ${id}`)
const result = yield* database.query(
`SELECT * FROM users WHERE id = ${id}`
)
return { id, name: result }
})
}
}))
// Provide dependencies to UserService layer
const userServiceWithDependencies = userServiceLayer.pipe(
Layer.provide(Layer.mergeAll(databaseLayer, loggerLayer))
)
// Now UserService layer has no dependencies
const program = Effect.gen(function*() {
const userService = yield* UserService
return yield* userService.getUser("123")
}).pipe(
Effect.provide(userServiceWithDependencies)
)
provide(
import LayerLayer.const fresh: <A, E, R>(
self: Layer<A, E, R>
) => Layer<A, E, R>
Creates a fresh version of this layer that will not be shared.
When to use
Use when you need two parts of an application to receive separate instances
of a resource, such as two independent client sessions.
Gotchas
Do not use it just to work around confusing composition. By default, sharing
the same layer value is usually the desired behavior.
Example (Creating non-shared layer instances)
import { Context, Effect, Layer, Ref } from "effect"
class Counter extends Context.Service<Counter, {
readonly id: number
}>()("Counter") {}
class Left extends Context.Service<Left, {
readonly counterId: number
}>()("Left") {}
class Right extends Context.Service<Right, {
readonly counterId: number
}>()("Right") {}
const leftLayer = Layer.effect(Left, Effect.gen(function*() {
const counter = yield* Counter
return { counterId: counter.id }
}))
const rightLayer = Layer.effect(Right, Effect.gen(function*() {
const counter = yield* Counter
return { counterId: counter.id }
}))
const showIds = Effect.gen(function*() {
const left = yield* Left
const right = yield* Right
console.log(`same Counter: ${left.counterId === right.counterId}`)
})
const program = Effect.gen(function*() {
const nextId = yield* Ref.make(0)
const counterLayer = Layer.effect(Counter, Effect.gen(function*() {
const id = yield* Ref.updateAndGet(nextId, (n) => n + 1)
console.log("constructed Counter")
return { id }
}))
const shared = Layer.merge(
Layer.provide(leftLayer, counterLayer),
Layer.provide(rightLayer, counterLayer)
)
yield* Effect.provide(showIds, shared)
const freshCounterLayer = Layer.fresh(counterLayer)
const fresh = Layer.merge(
Layer.provide(leftLayer, freshCounterLayer),
Layer.provide(rightLayer, freshCounterLayer)
)
yield* Effect.provide(showIds, fresh)
})
Effect.runPromise(program)
// constructed Counter
// same Counter: true
// constructed Counter
// constructed Counter
// same Counter: false
fresh(import FetchHttpClientFetchHttpClient.const layer: Layer.Layer<HttpClient.HttpClient>const layer: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<HttpClient>, never, 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; <…;
}
Layer that provides an HttpClient implementation backed by the configured
Fetch function.
When to use
Use when an Effect program should execute HttpClient requests through the
platform fetch implementation, especially in browser, edge, or Node.js
runtimes with globalThis.fetch.
Details
The layer uses the current Fetch reference and optional RequestInit
service for each request. Request-specific method, headers, body, and abort
signal are supplied by the client and override matching RequestInit fields.
Gotchas
Fetch behavior comes from the runtime's implementation, so CORS, cookies,
redirects, abort handling, and streaming support can vary by platform. Stream
request bodies are sent as Web streams with duplex: "half", and any
content-length header is removed before calling fetch.
layer).Pipeable.pipe<Layer.Layer<HttpClient, never, never>, Layer.Layer<HttpClient, never, never>>(this: Layer.Layer<HttpClient, never, never>, ab: (_: Layer.Layer<HttpClient, never, never>) => Layer.Layer<HttpClient, never, never>): Layer.Layer<HttpClient, never, never> (+21 overloads)pipe(
import LayerLayer.const provide: {
<RIn, E, ROut>(that: Layer<ROut, E, RIn>): <
RIn2,
E2,
ROut2
>(
self: Layer<ROut2, E2, RIn2>
) => Layer<
ROut2,
E | E2,
RIn | Exclude<RIn2, ROut>
>
<Layers extends [Any, ...Array<Any>]>(
that: Layers
): <A, E, R>(
self: Layer<A, E, R>
) => Layer<
A,
E | Error<Layers[number]>,
| Services<Layers[number]>
| Exclude<R, Success<Layers[number]>>
>
<RIn2, E2, ROut2, RIn, E, ROut>(
self: Layer<ROut2, E2, RIn2>,
that: Layer<ROut, E, RIn>
): Layer<
ROut2,
E | E2,
RIn | Exclude<RIn2, ROut>
>
<A, E, R, Layers extends [Any, ...Array<Any>]>(
self: Layer<A, E, R>,
that: Layers
): Layer<
A,
E | Error<Layers[number]>,
| Services<Layers[number]>
| Exclude<R, Success<Layers[number]>>
>
}
Feeds the output services of the dependency layer into the requirements of
this layer, returning a layer that only provides the services from this layer.
When to use
Use when you need to hide an implementation dependency layer from callers.
Details
In serviceLayer.pipe(Layer.provide(dependencyLayer)), the dependency layer is
built first and is used to satisfy the requirements of serviceLayer.
Example (Providing layer dependencies)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
class UserService extends Context.Service<UserService, {
readonly getUser: (id: string) => Effect.Effect<{
id: string
name: string
}>
}>()("UserService") {}
class Logger extends Context.Service<Logger, {
readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}
// Create dependency layers
const databaseLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`DB: ${sql}`))
})
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => console.log(`[LOG] ${msg}`)))
})
// UserService depends on Database and Logger
const userServiceLayer = Layer.effect(UserService, Effect.gen(function*() {
const database = yield* Database
const logger = yield* Logger
return {
getUser: Effect.fn("UserService.getUser")(function*(id: string) {
yield* logger.log(`Looking up user ${id}`)
const result = yield* database.query(
`SELECT * FROM users WHERE id = ${id}`
)
return { id, name: result }
})
}
}))
// Provide dependencies to UserService layer
const userServiceWithDependencies = userServiceLayer.pipe(
Layer.provide(Layer.mergeAll(databaseLayer, loggerLayer))
)
// Now UserService layer has no dependencies
const program = Effect.gen(function*() {
const userService = yield* UserService
return yield* userService.getUser("123")
}).pipe(
Effect.provide(userServiceWithDependencies)
)
provide(import LayerLayer.const succeed: {
<I, S>(service: Context.Key<I, S>): (
resource: S
) => Layer<I>
<I, S>(
service: Context.Key<I, S>,
resource: Types.NoInfer<S>
): Layer<I>
}
Constructs a layer that provides a single service from an already available
value.
When to use
Use when you need a Layer that provides a service from an already
constructed implementation without effectful acquisition.
Example (Creating a layer from a service implementation)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
const DatabaseLive = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Query result: ${sql}`))
})
succeed(import FetchHttpClientFetchHttpClient.class RequestInitclass RequestInit {
key: Identifier;
Service: {
body: BodyInit | null;
cache: RequestCache;
credentials: RequestCredentials;
headers: HeadersInit;
integrity: string;
keepalive: boolean;
method: string;
mode: RequestMode;
priority: RequestPriority;
redirect: RequestRedirect;
referrer: string;
referrerPolicy: ReferrerPolicy;
signal: AbortSignal | null;
window: null;
};
of: (this: void, self: RequestInit) => RequestInit;
context: (self: RequestInit) => Context.Context<FetchHttpClient.RequestInit>;
use: (f: (service: RequestInit) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, FetchHttpClient.RequestInit | R>;
useSync: (f: (service: RequestInit) => A) => Effect.Effect<A, never, FetchHttpClient.RequestInit>;
Identifier: Identifier;
stack: string | undefined;
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;
}
Service that contains default fetch options for the fetch-based HTTP client.
When to use
Use to provide default credentials, cache, redirect, integrity, or other
fetch options for outgoing HTTP requests.
Details
Request-specific method, headers, body, and abort signal are supplied by the client when a request is executed.
RequestInit)({ RequestInit.keepalive?: boolean | undefinedA boolean to set request's keepalive.
keepalive: false }))
)
),
import LayerLayer.const provideMerge: {
<RIn, E, ROut>(that: Layer<ROut, E, RIn>): <
RIn2,
E2,
ROut2
>(
self: Layer<ROut2, E2, RIn2>
) => Layer<
ROut | ROut2,
E | E2,
RIn | Exclude<RIn2, ROut>
>
<Layers extends [Any, ...Array<Any>]>(
that: Layers
): <A, E, R>(
self: Layer<A, E, R>
) => Layer<
A | Success<Layers[number]>,
E | Error<Layers[number]>,
| Services<Layers[number]>
| Exclude<R, Success<Layers[number]>>
>
<RIn2, E2, ROut2, RIn, E, ROut>(
self: Layer<ROut2, E2, RIn2>,
that: Layer<ROut, E, RIn>
): Layer<
ROut | ROut2,
E | E2,
RIn | Exclude<RIn2, ROut>
>
<A, E, R, Layers extends [Any, ...Array<Any>]>(
self: Layer<A, E, R>,
that: Layers
): Layer<
A | Success<Layers[number]>,
E | Error<Layers[number]>,
| Services<Layers[number]>
| Exclude<R, Success<Layers[number]>>
>
}
Feeds the output services of the dependency layer into the requirements of
this layer, returning a layer that provides both sets of services.
When to use
Use when you need to compose Layers while keeping both the constructed
service and the dependency used to build it available.
Details
Prefer
provide
when the dependency should stay private.
Example (Providing dependencies while retaining services)
import { Context, Effect, Layer } from "effect"
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") {}
class UserService extends Context.Service<UserService, {
readonly getUser: (id: string) => Effect.Effect<{
id: string
name: string
}>
}>()("UserService") {}
// Create dependency layers
const databaseLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`DB: ${sql}`))
})
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => console.log(`[LOG] ${msg}`)))
})
// UserService depends on Database and Logger
const userServiceLayer = Layer.effect(UserService, Effect.gen(function*() {
const database = yield* Database
const logger = yield* Logger
return {
getUser: Effect.fn("UserService.getUser")(function*(id: string) {
yield* logger.log(`Looking up user ${id}`)
const result = yield* database.query(
`SELECT * FROM users WHERE id = ${id}`
)
return { id, name: result }
})
}
}))
// Provide dependencies and merge all services together
const allServicesLayer = userServiceLayer.pipe(
Layer.provideMerge(Layer.mergeAll(databaseLayer, loggerLayer))
)
// Now the resulting layer provides UserService, Database, AND Logger
const program = Effect.gen(function*() {
const userService = yield* UserService
const logger = yield* Logger // Still available!
const database = yield* Database // Still available!
const user = yield* userService.getUser("123")
yield* logger.log(`Found user: ${user.name}`)
return user
}).pipe(
Effect.provide(allServicesLayer)
)
provideMerge(const layer: (
evaluate: LazyArg<Http.Server>,
options: Net.ListenOptions & {
readonly disablePreemptiveShutdown?:
| boolean
| undefined
readonly gracefulShutdownTimeout?:
| Duration.Input
| undefined
}
) => Layer.Layer<
| HttpServer.HttpServer
| NodeServices.NodeServices
| HttpPlatform.HttpPlatform
| Etag.Generator,
ServeError
>
Provides a Node HttpServer together with the Node HTTP platform, ETag, and
core platform services required to serve requests.
layer(import HttpHttp.createServer, { port: numberport: 0 }))
)