(config: Config.Wrap<SqliteClientConfig>): Layer.Layer<
SqliteClient | Client.SqlClient,
Config.ConfigError
>Builds a layer from an Effect Config value, providing both the node SqliteClient service and the generic SqlClient service.
export const const layerConfig: (
config: Config.Wrap<SqliteClientConfig>
) => Layer.Layer<
SqliteClient | Client.SqlClient,
Config.ConfigError
>
Builds a layer from an Effect Config value, providing both the node SqliteClient service and the generic SqlClient service.
layerConfig = (
config: Config.Wrap<SqliteClientConfig>config: import ConfigConfig.type Wrap<A> = [NonNullable<A>] extends [
infer T
]
? [IsPlainObject<T>] extends [true]
?
| {
readonly [K in keyof A]: Config.Wrap<
A[K]
>
}
| Config.Config<A>
: Config.Config<A>
: Config.Config<A>
Utility type that recursively replaces primitives with Config in a nested
structure.
When to use
Use when typing the input of
unwrap
so callers can pass either a Config
or a record of Configs.
Details
Config.Wrap<{ key: string }> becomes { key: Config<string> } | Config<{ key: string }>
Wrap<SqliteClientConfig>
): 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<SqliteClient | import ClientClient.SqlClient, import ConfigConfig.class ConfigErrorclass ConfigError {
_tag: 'ConfigError';
name: string;
cause: SourceError | Schema.SchemaError;
message: string;
toString: () => string;
}
Represents the error type produced when config loading or validation fails.
When to use
Use when you need to inspect config loading or validation failures.
Details
Wraps either:
- A
SourceError — the provider could not read data (I/O failure).
- A
SchemaError — the data was found but did not match the schema
(wrong type, out of range, missing key, etc.).
ConfigError> =>
import LayerLayer.const effectContext: <A, E, R>(
effect: Effect<Context.Context<A>, E, R>
) => Layer<A, E, Exclude<R, Scope.Scope>>
Constructs a layer from an effect that produces all services in a Context.
When to use
Use when you need a Layer that effectfully constructs a Context with
multiple services.
Details
This allows you to create a Layer from an effectful computation that
returns multiple services. The Effect is executed in the scope of the
layer.
Example (Creating a layer from an effectful context)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<
Database,
{ readonly query: (sql: string) => Effect.Effect<string> }
>()("Database") {}
const layer = Layer.effectContext(
Effect.succeed(Context.make(Database, {
query: (sql: string) => Effect.succeed(`Query: ${sql}`)
}))
)
effectContext(
import ConfigConfig.const unwrap: <T>(
wrapped: Wrap<T>
) => Config<T>
Constructs a Config<T> from a value matching Wrap<T>.
When to use
Use when accepting config from callers who may pass either a single Config or a
record of individual Configs.
Details
If the input is already a Config, it is returned as-is. Otherwise, each
key is recursively unwrapped and combined.
Example (Unwrapping a record of configs)
import { Config } from "effect"
interface Options {
key: string
}
const makeConfig = (config: Config.Wrap<Options>): Config.Config<Options> =>
Config.unwrap(config)
unwrap(config: Config.Wrap<SqliteClientConfig>config).Pipeable.pipe<Config.Config<SqliteClientConfig>, Effect.Effect<SqliteClient, Config.ConfigError, Scope.Scope | Reactivity.Reactivity>, Effect.Effect<Context.Context<SqliteClient | Client.SqlClient>, Config.ConfigError, Scope.Scope | Reactivity.Reactivity>>(this: Config.Config<...>, ab: (_: Config.Config<SqliteClientConfig>) => Effect.Effect<SqliteClient, Config.ConfigError, Scope.Scope | Reactivity.Reactivity>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)pipe(
import EffectEffect.const flatMap: {
<A, B, E1, R1>(
f: (a: A) => Effect<B, E1, R1>
): <E, R>(
self: Effect<A, E, R>
) => Effect<B, E1 | E, R1 | R>
<A, E, R, B, E1, R1>(
self: Effect<A, E, R>,
f: (a: A) => Effect<B, E1, R1>
): Effect<B, E | E1, R | R1>
}
Chains effects to produce new Effect instances, useful for combining
operations that depend on previous results.
When to use
Use when you need to chain multiple effects, ensuring that each
step produces a new Effect while flattening any nested effects that may
occur.
Details
flatMap lets you sequence effects so that the result of one effect can be
used in the next step. It is similar to flatMap used with arrays but works
specifically with Effect instances, allowing you to avoid deeply nested
effect structures.
Since effects are immutable, flatMap always returns a new effect instead of
changing the original one.
Example (Choosing flatMap syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => Effect.succeed(n + 1)
const flatMappedWithPipe = pipe(myEffect, Effect.flatMap(transformation))
const flatMappedWithDataFirst = Effect.flatMap(myEffect, transformation)
const flatMappedWithMethod = myEffect.pipe(Effect.flatMap(transformation))
Example (Sequencing dependent effects)
import { Data, Effect, pipe } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Chaining the fetch and discount application using `flatMap`
const finalAmount = pipe(
fetchTransactionAmount,
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 95
flatMap(const make: (
options: SqliteClientConfig
) => Effect.Effect<
SqliteClient,
never,
Scope.Scope | Reactivity.Reactivity
>
Creates a scoped node SQLite client from the supplied configuration, using a single serialized connection with WAL enabled by default and exposing SQLite-specific export, backup, and loadExtension operations.
make),
import EffectEffect.const map: {
<A, B>(f: (a: A) => B): <E, R>(
self: Effect<A, E, R>
) => Effect<B, E, R>
<A, E, R, B>(
self: Effect<A, E, R>,
f: (a: A) => B
): Effect<B, E, R>
}
Transforms the value inside an effect by applying a function to it.
When to use
Use to transform an effect's success value with a function that returns a
plain value, producing a new effect without changing the original effect's
typed error or context requirements.
Details
map takes a function and applies it to the value contained within an
effect, creating a new effect with the transformed value.
It's important to note that effects are immutable, meaning that the original
effect is not modified. Instead, a new effect is returned with the updated
value.
Example (Choosing map syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => n + 1
const mappedWithPipe = pipe(myEffect, Effect.map(transformation))
const mappedWithDataFirst = Effect.map(myEffect, transformation)
const mappedWithMethod = myEffect.pipe(Effect.map(transformation))
Example (Adding a service charge)
import { Effect, pipe } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const finalAmount = pipe(
fetchTransactionAmount,
Effect.map(addServiceCharge)
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 101
map((client: SqliteClientclient) =>
import ContextContext.const make: <I, S>(
key: Key<I, S>,
service: Types.NoInfer<S>
) => Context<I>
Creates a new Context with a single service associated to the key.
Example (Creating a context with one service)
import { Context } from "effect"
import * as assert from "node:assert"
const Port = Context.Service<{ PORT: number }>("Port")
const context = Context.make(Port, { PORT: 8080 })
assert.deepStrictEqual(Context.get(context, Port), { PORT: 8080 })
make(const SqliteClient: Context.Service<
SqliteClient,
SqliteClient
>
const SqliteClient: {
of: (this: void, self: SqliteClient) => SqliteClient;
context: (self: SqliteClient) => Context.Context<SqliteClient>;
use: (f: (service: SqliteClient) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, SqliteClient | R>;
useSync: (f: (service: SqliteClient) => A) => Effect.Effect<A, never, SqliteClient>;
Identifier: Identifier;
Service: Shape;
key: string;
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;
}
Node SQLite client service, extending SqlClient with database export, backup, and extension loading helpers. updateValues is not supported.
Service tag for the node SQLite client implementation.
SqliteClient, client: SqliteClientclient).Pipeable.pipe<Context.Context<SqliteClient>, Context.Context<SqliteClient | Client.SqlClient>>(this: Context.Context<SqliteClient>, ab: (_: Context.Context<SqliteClient>) => Context.Context<SqliteClient | Client.SqlClient>): Context.Context<SqliteClient | Client.SqlClient> (+21 overloads)pipe(
import ContextContext.const add: {
<I, S>(
key: Key<I, S>,
service: Types.NoInfer<S>
): <Services>(
self: Context<Services>
) => Context<Services | I>
<Services, I, S>(
self: Context<Services>,
key: Key<I, S>,
service: Types.NoInfer<S>
): Context<Services | I>
}
Adds a service to a given Context.
When to use
Use when you need to store a known service value in a Context.
Details
If the context already contains the same service key, the new service
replaces the previous one.
Example (Adding a service to a context)
import { Context, pipe } from "effect"
import * as assert from "node:assert"
const Port = Context.Service<{ PORT: number }>("Port")
const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout")
const someContext = Context.make(Port, { PORT: 8080 })
const context = pipe(
someContext,
Context.add(Timeout, { TIMEOUT: 5000 })
)
assert.deepStrictEqual(Context.get(context, Port), { PORT: 8080 })
assert.deepStrictEqual(Context.get(context, Timeout), { TIMEOUT: 5000 })
add(import ClientClient.const SqlClient: Context.Service<Client.SqlClient, Client.SqlClient>namespace SqlClient
const SqlClient: {
of: (this: void, self: Client.SqlClient) => Client.SqlClient;
context: (self: Client.SqlClient) => Context.Context<Client.SqlClient>;
use: (f: (service: Client.SqlClient) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, Client.SqlClient | R>;
useSync: (f: (service: Client.SqlClient) => A) => Effect.Effect<A, never, Client.SqlClient>;
Identifier: Identifier;
Service: Shape;
key: string;
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;
}
SQL client service interface, combining the statement constructor API with
connection reservation, transaction handling, and reactive query helpers.
Service tag for the active SQL client service.
When to use
Use to access or provide the SQL client used to build statements, stream
rows, reserve connections, and run transactions.
Namespace containing types associated with the SqlClient service.
SqlClient, client: SqliteClientclient)
)
)
)
).Pipeable.pipe<Layer.Layer<SqliteClient | Client.SqlClient, Config.ConfigError, Reactivity.Reactivity>, Layer.Layer<SqliteClient | Client.SqlClient, Config.ConfigError, never>>(this: Layer.Layer<...>, ab: (_: Layer.Layer<SqliteClient | Client.SqlClient, Config.ConfigError, Reactivity.Reactivity>) => Layer.Layer<SqliteClient | Client.SqlClient, Config.ConfigError, never>): 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 ReactivityReactivity.const layer: Layer.Layer<Reactivity>const layer: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<Reactivity>, 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; <…;
}
The default layer that provides an in-memory Reactivity service.
layer))