Modular service composition and resource management system for building applications with managed dependencies, automatic resource cleanup, and hierarchical service construction.
interface Layer<out ROut, out E = never, out RIn = never> extends Pipeable {}
declare namespace Layer {
/**
* Creates a layer that provides a service
*/
function succeed<T>(tag: Tag<T, T>, resource: T): Layer<T>;
/**
* Creates a layer from an Effect
*/
function effect<T, E, R>(tag: Tag<T, T>, effect: Effect<T, E, R>): Layer<T, E, R>;
/**
* Creates a scoped layer with automatic cleanup
*/
function scoped<T, E, R>(tag: Tag<T, T>, effect: Effect<T, E, R>): Layer<T, E, Exclude<R, Scope>>;
/**
* Provides a layer to an Effect
*/
function provide<RIn, E, ROut>(layer: Layer<RIn, E>): <A, E1, ROut1>(self: Effect<A, E1, RIn | ROut1>) => Effect<A, E | E1, ROut | ROut1>;
/**
* Merges two layers
*/
function merge<R1, E1, R2, E2>(that: Layer<R2, E2>): (self: Layer<R1, E1>) => Layer<R1 | R2, E1 | E2>;
}Usage Examples:
import { Layer, Context, Effect } from "effect";
// Service definitions
interface Database {
query(sql: string): Effect<unknown[]>;
}
interface Logger {
log(message: string): Effect<void>;
}
const Database = Context.GenericTag<Database>("Database");
const Logger = Context.GenericTag<Logger>("Logger");
// Layer implementations
const DatabaseLive = Layer.effect(
Database,
Effect.gen(function* () {
yield* Effect.log("Connecting to database");
return {
query: (sql: string) => Effect.succeed([{ result: `Query: ${sql}` }])
};
})
);
const LoggerLive = Layer.succeed(Logger, {
log: (message) => Effect.sync(() => console.log(message))
});
// Combined layer
const AppLayer = Layer.merge(DatabaseLive)(LoggerLive);
// Usage
const program = Effect.gen(function* () {
const db = yield* Database;
const logger = yield* Logger;
yield* logger.log("Starting application");
const results = yield* db.query("SELECT * FROM users");
yield* logger.log(`Found ${results.length} results`);
return results;
});
const runnable = pipe(program, Layer.provide(AppLayer));interface Scope {
readonly close: (exit: Exit<unknown, unknown>) => Effect<void>;
}