/** * This module provides a data structure called `Context` that can be used for dependency injection in effectful * programs. It is essentially a table mapping `Tag`s to their implementations (called `Service`s), and can be used to * manage dependencies in a type-safe way. The `Context` data structure is essentially a way of providing access to a set * of related services that can be passed around as a single unit. This module provides functions to create, modify, and * query the contents of a `Context`, as well as a number of utility types for working with tags and services. * * @since 2.0.0 */ import type { Equal } from "./Equal.js"; import type { LazyArg } from "./Function.js"; import type { Inspectable } from "./Inspectable.js"; import type { Option } from "./Option.js"; import type { Pipeable } from "./Pipeable.js"; import type * as Types from "./Types.js"; import type * as Unify from "./Unify.js"; declare const TagTypeId: unique symbol; /** * @since 2.0.0 * @category symbol */ export type TagTypeId = typeof TagTypeId; /** * @since 3.5.9 * @category models */ export interface Tag extends Pipeable, Inspectable { readonly _op: "Tag"; readonly Service: Value; readonly Identifier: Id; readonly [TagTypeId]: { readonly _Service: Types.Invariant; readonly _Identifier: Types.Invariant; }; of(self: Value): Value; context(self: Value): Context; readonly stack?: string | undefined; readonly key: string; [Unify.typeSymbol]?: unknown; [Unify.unifySymbol]?: TagUnify; [Unify.ignoreSymbol]?: TagUnifyIgnore; } declare const ReferenceTypeId: unique symbol; /** * @since 3.11.0 * @category symbol */ export type ReferenceTypeId = typeof ReferenceTypeId; /** * @since 3.11.0 * @category models */ export interface Reference extends Pipeable, Inspectable { readonly [ReferenceTypeId]: ReferenceTypeId; readonly defaultValue: () => Value; readonly _op: "Tag"; readonly Service: Value; readonly Identifier: Id; readonly [TagTypeId]: { readonly _Service: Types.Invariant; readonly _Identifier: Types.Invariant; }; of(self: Value): Value; context(self: Value): Context; readonly stack?: string | undefined; readonly key: string; [Unify.typeSymbol]?: unknown; [Unify.unifySymbol]?: TagUnify; [Unify.ignoreSymbol]?: TagUnifyIgnore; } /** * @since 2.0.0 * @category models */ export interface TagClassShape { readonly [TagTypeId]: TagTypeId; readonly Type: Shape; readonly Id: Id; } /** * @since 2.0.0 * @category models */ export interface TagClass extends Tag { new (_: never): TagClassShape; readonly key: Id; } /** * @since 3.11.0 * @category models */ export interface ReferenceClass extends Reference { new (_: never): TagClassShape; readonly key: Id; } /** * @category models * @since 2.0.0 */ export interface TagUnify { Tag?: () => Extract>; } /** * @category models * @since 2.0.0 */ export interface TagUnifyIgnore { } /** * @since 2.0.0 */ export declare namespace Tag { /** * @since 2.0.0 */ type Service | TagClassShape> = T extends Tag ? T["Service"] : T extends TagClassShape ? A : never; /** * @since 2.0.0 */ type Identifier | TagClassShape> = T extends Tag ? T["Identifier"] : T extends TagClassShape ? T : never; } /** * Creates a new `Tag` instance with an optional key parameter. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * assert.strictEqual(Context.GenericTag("PORT").key === Context.GenericTag("PORT").key, true) * ``` * * @since 2.0.0 * @category constructors */ export declare const GenericTag: (key: string) => Tag; declare const TypeId: unique symbol; /** * @since 2.0.0 * @category symbol */ export type TypeId = typeof TypeId; /** * @since 2.0.0 * @category models */ export type ValidTagsById = R extends infer S ? Tag : never; /** * @since 2.0.0 * @category models */ export interface Context extends Equal, Pipeable, Inspectable { readonly [TypeId]: { readonly _Services: Types.Contravariant; }; readonly unsafeMap: Map; } /** * @since 2.0.0 * @category constructors */ export declare const unsafeMake: (unsafeMap: Map) => Context; /** * Checks if the provided argument is a `Context`. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * assert.strictEqual(Context.isContext(Context.empty()), true) * ``` * * @since 2.0.0 * @category guards */ export declare const isContext: (input: unknown) => input is Context; /** * Checks if the provided argument is a `Tag`. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * assert.strictEqual(Context.isTag(Context.GenericTag("Tag")), true) * ``` * * @since 2.0.0 * @category guards */ export declare const isTag: (input: unknown) => input is Tag; /** * Checks if the provided argument is a `Reference`. * * @since 3.11.0 * @category guards * @experimental */ export declare const isReference: (u: unknown) => u is Reference; /** * Returns an empty `Context`. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * assert.strictEqual(Context.isContext(Context.empty()), true) * ``` * * @since 2.0.0 * @category constructors */ export declare const empty: () => Context; /** * Creates a new `Context` with a single service associated to the tag. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * * const Services = Context.make(Port, { PORT: 8080 }) * * assert.deepStrictEqual(Context.get(Services, Port), { PORT: 8080 }) * ``` * * @since 2.0.0 * @category constructors */ export declare const make: (tag: Tag, service: Types.NoInfer) => Context; /** * Adds a service to a given `Context`. * * @example * ```ts * import * as assert from "node:assert" * import { Context, pipe } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const someContext = Context.make(Port, { PORT: 8080 }) * * const Services = pipe( * someContext, * Context.add(Timeout, { TIMEOUT: 5000 }) * ) * * assert.deepStrictEqual(Context.get(Services, Port), { PORT: 8080 }) * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 */ export declare const add: { /** * Adds a service to a given `Context`. * * @example * ```ts * import * as assert from "node:assert" * import { Context, pipe } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const someContext = Context.make(Port, { PORT: 8080 }) * * const Services = pipe( * someContext, * Context.add(Timeout, { TIMEOUT: 5000 }) * ) * * assert.deepStrictEqual(Context.get(Services, Port), { PORT: 8080 }) * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 */ (tag: Tag, service: Types.NoInfer): (self: Context) => Context; /** * Adds a service to a given `Context`. * * @example * ```ts * import * as assert from "node:assert" * import { Context, pipe } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const someContext = Context.make(Port, { PORT: 8080 }) * * const Services = pipe( * someContext, * Context.add(Timeout, { TIMEOUT: 5000 }) * ) * * assert.deepStrictEqual(Context.get(Services, Port), { PORT: 8080 }) * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 */ (self: Context, tag: Tag, service: Types.NoInfer): Context; }; /** * Get a service from the context that corresponds to the given tag. * * @example * ```ts * import * as assert from "node:assert" * import { pipe, Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = pipe( * Context.make(Port, { PORT: 8080 }), * Context.add(Timeout, { TIMEOUT: 5000 }) * ) * * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 * @category getters */ export declare const get: { /** * Get a service from the context that corresponds to the given tag. * * @example * ```ts * import * as assert from "node:assert" * import { pipe, Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = pipe( * Context.make(Port, { PORT: 8080 }), * Context.add(Timeout, { TIMEOUT: 5000 }) * ) * * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 * @category getters */ (tag: Reference): (self: Context) => S; /** * Get a service from the context that corresponds to the given tag. * * @example * ```ts * import * as assert from "node:assert" * import { pipe, Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = pipe( * Context.make(Port, { PORT: 8080 }), * Context.add(Timeout, { TIMEOUT: 5000 }) * ) * * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 * @category getters */ (tag: Tag): (self: Context) => S; /** * Get a service from the context that corresponds to the given tag. * * @example * ```ts * import * as assert from "node:assert" * import { pipe, Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = pipe( * Context.make(Port, { PORT: 8080 }), * Context.add(Timeout, { TIMEOUT: 5000 }) * ) * * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 * @category getters */ (self: Context, tag: Reference): S; /** * Get a service from the context that corresponds to the given tag. * * @example * ```ts * import * as assert from "node:assert" * import { pipe, Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = pipe( * Context.make(Port, { PORT: 8080 }), * Context.add(Timeout, { TIMEOUT: 5000 }) * ) * * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 * @category getters */ (self: Context, tag: Tag): S; }; /** * Get a service from the context that corresponds to the given tag, or * use the fallback value. * * @since 3.7.0 * @category getters */ export declare const getOrElse: { /** * Get a service from the context that corresponds to the given tag, or * use the fallback value. * * @since 3.7.0 * @category getters */ (tag: Tag, orElse: LazyArg): (self: Context) => S | B; /** * Get a service from the context that corresponds to the given tag, or * use the fallback value. * * @since 3.7.0 * @category getters */ (self: Context, tag: Tag, orElse: LazyArg): S | B; }; /** * Get a service from the context that corresponds to the given tag. * This function is unsafe because if the tag is not present in the context, a runtime error will be thrown. * * For a safer version see {@link getOption}. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = Context.make(Port, { PORT: 8080 }) * * assert.deepStrictEqual(Context.unsafeGet(Services, Port), { PORT: 8080 }) * assert.throws(() => Context.unsafeGet(Services, Timeout)) * ``` * * @since 2.0.0 * @category unsafe */ export declare const unsafeGet: { /** * Get a service from the context that corresponds to the given tag. * This function is unsafe because if the tag is not present in the context, a runtime error will be thrown. * * For a safer version see {@link getOption}. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = Context.make(Port, { PORT: 8080 }) * * assert.deepStrictEqual(Context.unsafeGet(Services, Port), { PORT: 8080 }) * assert.throws(() => Context.unsafeGet(Services, Timeout)) * ``` * * @since 2.0.0 * @category unsafe */ (tag: Tag): (self: Context) => S; /** * Get a service from the context that corresponds to the given tag. * This function is unsafe because if the tag is not present in the context, a runtime error will be thrown. * * For a safer version see {@link getOption}. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = Context.make(Port, { PORT: 8080 }) * * assert.deepStrictEqual(Context.unsafeGet(Services, Port), { PORT: 8080 }) * assert.throws(() => Context.unsafeGet(Services, Timeout)) * ``` * * @since 2.0.0 * @category unsafe */ (self: Context, tag: Tag): S; }; /** * Get the value associated with the specified tag from the context wrapped in an `Option` object. If the tag is not * found, the `Option` object will be `None`. * * @example * ```ts * import * as assert from "node:assert" * import { Context, Option } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = Context.make(Port, { PORT: 8080 }) * * assert.deepStrictEqual(Context.getOption(Services, Port), Option.some({ PORT: 8080 })) * assert.deepStrictEqual(Context.getOption(Services, Timeout), Option.none()) * ``` * * @since 2.0.0 * @category getters */ export declare const getOption: { /** * Get the value associated with the specified tag from the context wrapped in an `Option` object. If the tag is not * found, the `Option` object will be `None`. * * @example * ```ts * import * as assert from "node:assert" * import { Context, Option } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = Context.make(Port, { PORT: 8080 }) * * assert.deepStrictEqual(Context.getOption(Services, Port), Option.some({ PORT: 8080 })) * assert.deepStrictEqual(Context.getOption(Services, Timeout), Option.none()) * ``` * * @since 2.0.0 * @category getters */ (tag: Tag): (self: Context) => Option; /** * Get the value associated with the specified tag from the context wrapped in an `Option` object. If the tag is not * found, the `Option` object will be `None`. * * @example * ```ts * import * as assert from "node:assert" * import { Context, Option } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = Context.make(Port, { PORT: 8080 }) * * assert.deepStrictEqual(Context.getOption(Services, Port), Option.some({ PORT: 8080 })) * assert.deepStrictEqual(Context.getOption(Services, Timeout), Option.none()) * ``` * * @since 2.0.0 * @category getters */ (self: Context, tag: Tag): Option; }; /** * Merges two `Context`s, returning a new `Context` containing the services of both. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const firstContext = Context.make(Port, { PORT: 8080 }) * const secondContext = Context.make(Timeout, { TIMEOUT: 5000 }) * * const Services = Context.merge(firstContext, secondContext) * * assert.deepStrictEqual(Context.get(Services, Port), { PORT: 8080 }) * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 */ export declare const merge: { /** * Merges two `Context`s, returning a new `Context` containing the services of both. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const firstContext = Context.make(Port, { PORT: 8080 }) * const secondContext = Context.make(Timeout, { TIMEOUT: 5000 }) * * const Services = Context.merge(firstContext, secondContext) * * assert.deepStrictEqual(Context.get(Services, Port), { PORT: 8080 }) * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 */ (that: Context): (self: Context) => Context; /** * Merges two `Context`s, returning a new `Context` containing the services of both. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const firstContext = Context.make(Port, { PORT: 8080 }) * const secondContext = Context.make(Timeout, { TIMEOUT: 5000 }) * * const Services = Context.merge(firstContext, secondContext) * * assert.deepStrictEqual(Context.get(Services, Port), { PORT: 8080 }) * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * ``` * * @since 2.0.0 */ (self: Context, that: Context): Context; }; /** * Merges any number of `Context`s, returning a new `Context` containing the services of all. * * @example * ```ts * import * as assert from "node:assert" * import { Context } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * const Host = Context.GenericTag<{ HOST: string }>("Host") * * const firstContext = Context.make(Port, { PORT: 8080 }) * const secondContext = Context.make(Timeout, { TIMEOUT: 5000 }) * const thirdContext = Context.make(Host, { HOST: "localhost" }) * * const Services = Context.mergeAll(firstContext, secondContext, thirdContext) * * assert.deepStrictEqual(Context.get(Services, Port), { PORT: 8080 }) * assert.deepStrictEqual(Context.get(Services, Timeout), { TIMEOUT: 5000 }) * assert.deepStrictEqual(Context.get(Services, Host), { HOST: "localhost" }) * ``` * * @since 3.12.0 */ export declare const mergeAll: >(...ctxs: [...{ [K in keyof T]: Context; }]) => Context; /** * Returns a new `Context` that contains only the specified services. * * @example * ```ts * import * as assert from "node:assert" * import { pipe, Context, Option } from "effect" * * const Port = Context.GenericTag<{ PORT: number }>("Port") * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const someContext = pipe( * Context.make(Port, { PORT: 8080 }), * Context.add(Timeout, { TIMEOUT: 5000 }) * ) * * const Services = pipe(someContext, Context.pick(Port)) * * assert.deepStrictEqual(Context.getOption(Services, Port), Option.some({ PORT: 8080 })) * assert.deepStrictEqual(Context.getOption(Services, Timeout), Option.none()) * ``` * * @since 2.0.0 */ export declare const pick: >>(...tags: Tags) => (self: Context) => Context>; /** * @since 2.0.0 */ export declare const omit: >>(...tags: Tags) => (self: Context) => Context>>; /** * @example * ```ts * import * as assert from "node:assert" * import { Context, Layer } from "effect" * * class MyTag extends Context.Tag("MyTag")< * MyTag, * { readonly myNum: number } * >() { * static Live = Layer.succeed(this, { myNum: 108 }) * } * ``` * * @since 2.0.0 * @category constructors */ export declare const Tag: (id: Id) => () => TagClass; /** * Creates a context tag with a default value. * * **Details** * * `Context.Reference` allows you to create a tag that can hold a value. You can * provide a default value for the service, which will automatically be used * when the context is accessed, or override it with a custom implementation * when needed. * * **Example** (Declaring a Tag with a default value) * * ```ts * import * as assert from "node:assert" * import { Context, Effect } from "effect" * * class SpecialNumber extends Context.Reference()( * "SpecialNumber", * { defaultValue: () => 2048 } * ) {} * * // ┌─── Effect * // ▼ * const program = Effect.gen(function* () { * const specialNumber = yield* SpecialNumber * console.log(`The special number is ${specialNumber}`) * }) * * // No need to provide the SpecialNumber implementation * Effect.runPromise(program) * // Output: The special number is 2048 * ``` * * **Example** (Overriding the default value) * * ```ts * import { Context, Effect } from "effect" * * class SpecialNumber extends Context.Reference()( * "SpecialNumber", * { defaultValue: () => 2048 } * ) {} * * const program = Effect.gen(function* () { * const specialNumber = yield* SpecialNumber * console.log(`The special number is ${specialNumber}`) * }) * * Effect.runPromise(program.pipe(Effect.provideService(SpecialNumber, -1))) * // Output: The special number is -1 * ``` * * @since 3.11.0 * @category constructors * @experimental */ export declare const Reference: () => (id: Id, options: { readonly defaultValue: () => Service; }) => ReferenceClass; export {}; //# sourceMappingURL=Context.d.ts.map