| import * as Effectable from "./Effectable.js"; | |
| import * as Equal from "./Equal.js"; | |
| import { dual } from "./Function.js"; | |
| import * as Hash from "./Hash.js"; | |
| import { exitSucceed, PipeInspectableProto, withFiber } from "./internal/core.js"; | |
| import * as Option from "./Option.js"; | |
| import { hasProperty } from "./Predicate.js"; | |
| /** | |
| * Runtime type identifier attached to `Context` service keys and used by | |
| * `isKey` to recognize them. | |
| * | |
| * @category type IDs | |
| * @since 4.0.0 | |
| */ | |
| export const ServiceTypeId = "~effect/Context/Service"; | |
| /** | |
| * Creates a `Context` service key. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to define a context service key for a dependency that must | |
| * be provided by the surrounding context. | |
| * | |
| * **Details** | |
| * | |
| * Call `Context.Service("Key")` for a function-style key, or use the two-stage | |
| * form `Context.Service<Self, Shape>()("Key")` for class-style service | |
| * declarations. The returned key can be yielded as an Effect and passed to | |
| * `Context.make`, `Context.add`, and the Context getter functions. | |
| * | |
| * **Gotchas** | |
| * | |
| * The string key is the runtime identity of the service. Reusing the same key | |
| * string for unrelated services makes them occupy the same slot in a | |
| * `Context`. | |
| * | |
| * **Example** (Creating service keys) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * | |
| * // Create a simple service | |
| * const Database = Context.Service<{ | |
| * query: (sql: string) => string | |
| * }>("Database") | |
| * | |
| * // Create a service class | |
| * class Config extends Context.Service<Config, { | |
| * port: number | |
| * }>()("Config") {} | |
| * | |
| * // Use the services to create contexts | |
| * const db = Context.make(Database, { | |
| * query: (sql) => `Result: ${sql}` | |
| * }) | |
| * const config = Context.make(Config, { port: 8080 }) | |
| * ``` | |
| * | |
| * @see {@link Reference} for service keys with default values | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const Service = function () { | |
| const prevLimit = Error.stackTraceLimit; | |
| Error.stackTraceLimit = 2; | |
| const err = new Error(); | |
| Error.stackTraceLimit = prevLimit; | |
| function KeyClass() {} | |
| const self = KeyClass; | |
| Object.setPrototypeOf(self, ServiceProto); | |
| // @effect-diagnostics-next-line floatingEffect:off | |
| Object.defineProperty(self, "stack", { | |
| get() { | |
| return err.stack; | |
| } | |
| }); | |
| if (arguments.length > 0) { | |
| self.key = arguments[0]; | |
| if (arguments[1]?.defaultValue) { | |
| self[ReferenceTypeId] = ReferenceTypeId; | |
| self.defaultValue = arguments[1].defaultValue; | |
| } | |
| return self; | |
| } | |
| return function (key, options) { | |
| self.key = key; | |
| if (options?.make) { | |
| ; | |
| self.make = options.make; | |
| } | |
| return self; | |
| }; | |
| }; | |
| const ServiceProto = { | |
| [ServiceTypeId]: ServiceTypeId, | |
| ... /*#__PURE__*/Effectable.Prototype({ | |
| label: "Service", | |
| evaluate(fiber) { | |
| return exitSucceed(get(fiber.context, this)); | |
| } | |
| }), | |
| toJSON() { | |
| return { | |
| _id: "Service", | |
| key: this.key, | |
| stack: this.stack | |
| }; | |
| }, | |
| of(self) { | |
| return self; | |
| }, | |
| context(self) { | |
| return make(this, self); | |
| }, | |
| use(f) { | |
| return withFiber(fiber => f(get(fiber.context, this))); | |
| }, | |
| useSync(f) { | |
| return withFiber(fiber => exitSucceed(f(get(fiber.context, this)))); | |
| } | |
| }; | |
| const ReferenceTypeId = "~effect/Context/Reference"; | |
| const TypeId = "~effect/Context"; | |
| /** | |
| * Creates a `Context` from an existing service map. | |
| * | |
| * **When to use** | |
| * | |
| * Use when constructing a low-level `Context` from a trusted map whose lifecycle | |
| * you control. | |
| * | |
| * **Gotchas** | |
| * | |
| * This is unsafe because later mutation of the provided map can affect the | |
| * created `Context`. Prefer `empty`, `make`, `add`, or `merge` for normal | |
| * Context construction. | |
| * | |
| * **Example** (Creating a context from a map) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * | |
| * // Create a context from a Map (unsafe) | |
| * const map = new Map([ | |
| * ["Logger", { log: (msg: string) => console.log(msg) }] | |
| * ]) | |
| * | |
| * const context = Context.makeUnsafe(map) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const makeUnsafe = mapUnsafe => { | |
| const self = Object.create(Proto); | |
| self.mapUnsafe = mapUnsafe; | |
| self.mutable = false; | |
| return self; | |
| }; | |
| const Proto = { | |
| ...PipeInspectableProto, | |
| [TypeId]: { | |
| _Services: _ => _ | |
| }, | |
| toJSON() { | |
| return { | |
| _id: "Context", | |
| services: Array.from(this.mapUnsafe).map(([key, value]) => ({ | |
| key, | |
| value | |
| })) | |
| }; | |
| }, | |
| [Equal.symbol](that) { | |
| if (!isContext(that) || this.mapUnsafe.size !== that.mapUnsafe.size) return false; | |
| for (const k of this.mapUnsafe.keys()) { | |
| if (!that.mapUnsafe.has(k) || !Equal.equals(this.mapUnsafe.get(k), that.mapUnsafe.get(k))) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| }, | |
| [Hash.symbol]() { | |
| return Hash.number(this.mapUnsafe.size); | |
| } | |
| }; | |
| /** | |
| * Checks whether the provided argument is a `Context`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to narrow an unknown value before passing it to APIs that require a | |
| * `Context`. | |
| * | |
| * **Details** | |
| * | |
| * This checks the runtime `Context` marker and does not inspect which services | |
| * the context contains. | |
| * | |
| * **Gotchas** | |
| * | |
| * This guard only proves that the value is a `Context`; it does not prove that | |
| * any specific service is present. | |
| * | |
| * **Example** (Checking for contexts) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * import * as assert from "node:assert" | |
| * | |
| * assert.strictEqual(Context.isContext(Context.empty()), true) | |
| * ``` | |
| * | |
| * @see {@link isKey} for checking service keys | |
| * @see {@link isReference} for checking references with defaults | |
| * | |
| * @category guards | |
| * @since 2.0.0 | |
| */ | |
| export const isContext = u => hasProperty(u, TypeId); | |
| /** | |
| * Checks whether the provided argument is a `Key`. | |
| * | |
| * **Example** (Checking for keys) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * import * as assert from "node:assert" | |
| * | |
| * assert.strictEqual(Context.isKey(Context.Service("Service")), true) | |
| * ``` | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isKey = u => hasProperty(u, ServiceTypeId); | |
| /** | |
| * Checks whether the provided argument is a `Reference`. | |
| * | |
| * **Example** (Checking for references) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * import * as assert from "node:assert" | |
| * | |
| * const LoggerRef = Context.Reference("Logger", { | |
| * defaultValue: () => ({ log: (msg: string) => console.log(msg) }) | |
| * }) | |
| * | |
| * assert.strictEqual(Context.isReference(LoggerRef), true) | |
| * assert.strictEqual(Context.isReference(Context.Service("Key")), false) | |
| * ``` | |
| * | |
| * @category guards | |
| * @since 3.11.0 | |
| */ | |
| export const isReference = u => hasProperty(u, ReferenceTypeId); | |
| /** | |
| * Returns an empty `Context`. | |
| * | |
| * **Example** (Creating an empty context) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * import * as assert from "node:assert" | |
| * | |
| * assert.strictEqual(Context.isContext(Context.empty()), true) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const empty = () => emptyContext; | |
| const emptyContext = /*#__PURE__*/makeUnsafe(/*#__PURE__*/new Map()); | |
| /** | |
| * Creates a new `Context` with a single service associated to the key. | |
| * | |
| * **Example** (Creating a context with one service) | |
| * | |
| * ```ts | |
| * 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 }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const make = (key, service) => makeUnsafe(new Map([[key.key, service]])); | |
| /** | |
| * 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) | |
| * | |
| * ```ts | |
| * 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 }) | |
| * ``` | |
| * | |
| * @see {@link addOrOmit} for adding or removing a service from an `Option` | |
| * | |
| * @category adders | |
| * @since 2.0.0 | |
| */ | |
| export const add = /*#__PURE__*/dual(3, (self, key, service) => withMapUnsafe(self, map => { | |
| map.set(key.key, service); | |
| })); | |
| /** | |
| * Adds or removes a service depending on an `Option`. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to add or omit a `Context` service based on an `Option`. | |
| * | |
| * **Details** | |
| * | |
| * When `service` is `Option.some`, the value is stored for the key. When it is | |
| * `Option.none`, the key is removed from the returned `Context`. | |
| * | |
| * **Example** (Adding optional services) | |
| * | |
| * ```ts | |
| * import { Context, Option } from "effect" | |
| * | |
| * const Port = Context.Service<{ PORT: number }>("Port") | |
| * | |
| * const withPort = Context.empty().pipe( | |
| * Context.addOrOmit(Port, Option.some({ PORT: 8080 })) | |
| * ) | |
| * | |
| * const withoutPort = withPort.pipe( | |
| * Context.addOrOmit(Port, Option.none()) | |
| * ) | |
| * ``` | |
| * | |
| * @see {@link add} for always storing a service value | |
| * | |
| * @category adders | |
| * @since 4.0.0 | |
| */ | |
| export const addOrOmit = /*#__PURE__*/dual(3, (self, key, service) => withMapUnsafe(self, map => { | |
| if (service._tag === "None") { | |
| map.delete(key.key); | |
| } else { | |
| map.set(key.key, service.value); | |
| } | |
| })); | |
| /** | |
| * Gets the service for a key, or evaluates the fallback when a non-reference | |
| * key is absent. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need a fallback for a missing `Context.Service` key while still | |
| * resolving `Context.Reference` defaults. | |
| * | |
| * **Details** | |
| * | |
| * If the key is a `Context.Reference` and no override is stored in the | |
| * context, its cached default value is returned instead of the fallback. | |
| * | |
| * **Gotchas** | |
| * | |
| * The fallback is not evaluated for missing `Context.Reference` keys because | |
| * references resolve to their default value. | |
| * | |
| * **Example** (Falling back for missing services) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * | |
| * const Logger = Context.Service<{ log: (msg: string) => void }>("Logger") | |
| * const Database = Context.Service<{ query: (sql: string) => string }>( | |
| * "Database" | |
| * ) | |
| * | |
| * const context = Context.make(Logger, { | |
| * log: (msg: string) => console.log(msg) | |
| * }) | |
| * | |
| * const logger = Context.getOrElse(context, Logger, () => ({ log: () => {} })) | |
| * const database = Context.getOrElse( | |
| * context, | |
| * Database, | |
| * () => ({ query: () => "fallback" }) | |
| * ) | |
| * | |
| * console.log(logger === Context.get(context, Logger)) // true | |
| * console.log(database.query("SELECT 1")) // "fallback" | |
| * ``` | |
| * | |
| * @see {@link getOption} for returning `Option.none` when a non-reference key is missing | |
| * | |
| * @category getters | |
| * @since 3.7.0 | |
| */ | |
| export const getOrElse = /*#__PURE__*/dual(3, (self, key, orElse) => { | |
| if (self.mapUnsafe.has(key.key)) { | |
| return self.mapUnsafe.get(key.key); | |
| } | |
| return isReference(key) ? getDefaultValue(key) : orElse(); | |
| }); | |
| /** | |
| * Returns the service currently stored for a key, or `undefined` when the key | |
| * is absent. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to read the service stored for a key without resolving | |
| * `Context.Reference` defaults. | |
| * | |
| * **Gotchas** | |
| * | |
| * This is a raw lookup and does not resolve default values for | |
| * `Context.Reference` keys. | |
| * | |
| * @see {@link getOption} for a reference-aware optional lookup | |
| * | |
| * @category getters | |
| * @since 4.0.0 | |
| */ | |
| export const getOrUndefined = /*#__PURE__*/dual(2, (self, key) => self.mapUnsafe.get(key.key)); | |
| /** | |
| * Gets the service for a key, throwing if an absent non-reference key cannot be | |
| * resolved. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to read a service from a context whose type does not prove | |
| * the service is present. | |
| * | |
| * **Details** | |
| * | |
| * If the key is a `Context.Reference` and no override is stored in the | |
| * context, its cached default value is returned. For absent non-reference keys, | |
| * this function throws a runtime error. | |
| * | |
| * **Example** (Getting services unsafely) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * import * as assert from "node:assert" | |
| * | |
| * const Port = Context.Service<{ PORT: number }>("Port") | |
| * const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout") | |
| * | |
| * const context = Context.make(Port, { PORT: 8080 }) | |
| * | |
| * assert.deepStrictEqual(Context.getUnsafe(context, Port), { PORT: 8080 }) | |
| * assert.throws(() => Context.getUnsafe(context, Timeout)) | |
| * ``` | |
| * | |
| * @see {@link get} for type-checked service access | |
| * @see {@link getOption} for optional service access | |
| * | |
| * @category unsafe | |
| * @since 4.0.0 | |
| */ | |
| export const getUnsafe = /*#__PURE__*/dual(2, (self, service) => { | |
| if (!self.mapUnsafe.has(service.key)) { | |
| if (ReferenceTypeId in service) return getDefaultValue(service); | |
| throw serviceNotFoundError(service); | |
| } | |
| return self.mapUnsafe.get(service.key); | |
| }); | |
| /** | |
| * Gets a service from the context that corresponds to the given key. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need type-checked access to a service already included in the | |
| * context type. | |
| * | |
| * **Example** (Getting a service from a context) | |
| * | |
| * ```ts | |
| * 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 context = pipe( | |
| * Context.make(Port, { PORT: 8080 }), | |
| * Context.add(Timeout, { TIMEOUT: 5000 }) | |
| * ) | |
| * | |
| * assert.deepStrictEqual(Context.get(context, Timeout), { TIMEOUT: 5000 }) | |
| * ``` | |
| * | |
| * @see {@link getOption} for optional service access | |
| * @see {@link getOrElse} for fallback values | |
| * | |
| * @category getters | |
| * @since 2.0.0 | |
| */ | |
| export const get = getUnsafe; | |
| /** | |
| * Gets the value for a `Context.Reference`, returning its cached default when | |
| * the context does not contain an override. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need a `Context.Reference` value resolved from either a stored | |
| * override or the reference's default value. | |
| * | |
| * **Details** | |
| * | |
| * Stored overrides take precedence. If no override is present, the reference's | |
| * default value is computed lazily and cached on the reference itself. | |
| * | |
| * **Gotchas** | |
| * | |
| * Mutable default values can be shared across contexts unless an override is | |
| * provided, because the default is cached on the `Context.Reference`. | |
| * | |
| * **Example** (Getting reference defaults unsafely) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * | |
| * const LoggerRef = Context.Reference("Logger", { | |
| * defaultValue: () => ({ log: (msg: string) => console.log(msg) }) | |
| * }) | |
| * | |
| * const context = Context.empty() | |
| * const logger = Context.getReferenceUnsafe(context, LoggerRef) | |
| * | |
| * console.log(typeof logger.log) // "function" | |
| * ``` | |
| * | |
| * @see {@link getUnsafe} for unsafe access with any service key | |
| * @see {@link get} for type-checked reference-aware access | |
| * @see {@link getOption} for optional access to non-reference keys | |
| * | |
| * @category unsafe | |
| * @since 4.0.0 | |
| */ | |
| export const getReferenceUnsafe = (self, service) => { | |
| if (!self.mapUnsafe.has(service.key)) { | |
| return getDefaultValue(service); | |
| } | |
| return self.mapUnsafe.get(service.key); | |
| }; | |
| const defaultValueCacheKey = "~effect/Context/defaultValue"; | |
| const getDefaultValue = ref => { | |
| if (defaultValueCacheKey in ref) { | |
| return ref[defaultValueCacheKey]; | |
| } | |
| return ref[defaultValueCacheKey] = ref.defaultValue(); | |
| }; | |
| const serviceNotFoundError = service => { | |
| const error = new Error(`Service not found${service.key ? `: ${String(service.key)}` : ""}`); | |
| if (service.stack) { | |
| const lines = service.stack.split("\n"); | |
| if (lines.length > 2) { | |
| const afterAt = lines[2].match(/at (.*)/); | |
| if (afterAt) { | |
| error.message = error.message + ` (defined at ${afterAt[1]})`; | |
| } | |
| } | |
| } | |
| if (error.stack) { | |
| const lines = error.stack.split("\n"); | |
| lines.splice(1, 3); | |
| error.stack = lines.join("\n"); | |
| } | |
| return error; | |
| }; | |
| /** | |
| * Gets the service for a key safely wrapped in an `Option`. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to read a `Context` service as an `Option` so absence is | |
| * represented as data. | |
| * | |
| * **Details** | |
| * | |
| * Returns `Option.some` when the service is stored in the context. If the key | |
| * is a `Context.Reference` and no override is stored, returns `Option.some` of | |
| * the cached default value. Missing non-reference keys return `Option.none`. | |
| * | |
| * **Example** (Getting optional services) | |
| * | |
| * ```ts | |
| * import { Context, Option } from "effect" | |
| * import * as assert from "node:assert" | |
| * | |
| * const Port = Context.Service<{ PORT: number }>("Port") | |
| * const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout") | |
| * | |
| * const context = Context.make(Port, { PORT: 8080 }) | |
| * | |
| * assert.deepStrictEqual( | |
| * Context.getOption(context, Port), | |
| * Option.some({ PORT: 8080 }) | |
| * ) | |
| * assert.deepStrictEqual(Context.getOption(context, Timeout), Option.none()) | |
| * ``` | |
| * | |
| * @see {@link getOrElse} for returning a fallback value directly | |
| * | |
| * @category getters | |
| * @since 2.0.0 | |
| */ | |
| export const getOption = /*#__PURE__*/dual(2, (self, service) => { | |
| if (self.mapUnsafe.has(service.key)) { | |
| return Option.some(self.mapUnsafe.get(service.key)); | |
| } | |
| return isReference(service) ? Option.some(getDefaultValue(service)) : Option.none(); | |
| }); | |
| /** | |
| * Merges two `Context`s into one. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to combine two contexts. | |
| * | |
| * **Details** | |
| * | |
| * When both contexts contain the same service key, the service from `that` | |
| * overrides the service from `self`. | |
| * | |
| * **Example** (Merging two contexts) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * import * as assert from "node:assert" | |
| * | |
| * const Port = Context.Service<{ PORT: number }>("Port") | |
| * const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout") | |
| * | |
| * const firstContext = Context.make(Port, { PORT: 8080 }) | |
| * const secondContext = Context.make(Timeout, { TIMEOUT: 5000 }) | |
| * | |
| * const context = Context.merge(firstContext, secondContext) | |
| * | |
| * assert.deepStrictEqual(Context.get(context, Port), { PORT: 8080 }) | |
| * assert.deepStrictEqual(Context.get(context, Timeout), { TIMEOUT: 5000 }) | |
| * ``` | |
| * | |
| * @see {@link mergeAll} for merging more than two contexts at once | |
| * | |
| * @category combining | |
| * @since 2.0.0 | |
| */ | |
| export const merge = /*#__PURE__*/dual(2, (self, that) => { | |
| if (self.mapUnsafe.size === 0) return that; | |
| if (that.mapUnsafe.size === 0) return self; | |
| return withMapUnsafe(self, map => { | |
| that.mapUnsafe.forEach((value, key) => map.set(key, value)); | |
| }); | |
| }); | |
| /** | |
| * Merges any number of `Context`s into one. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to combine a variadic list of contexts. | |
| * | |
| * **Details** | |
| * | |
| * When multiple contexts contain the same service key, the service from the | |
| * last context with that key is kept. | |
| * | |
| * **Example** (Merging multiple contexts) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * import * as assert from "node:assert" | |
| * | |
| * const Port = Context.Service<{ PORT: number }>("Port") | |
| * const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout") | |
| * const Host = Context.Service<{ 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 context = Context.mergeAll( | |
| * firstContext, | |
| * secondContext, | |
| * thirdContext | |
| * ) | |
| * | |
| * assert.deepStrictEqual(Context.get(context, Port), { PORT: 8080 }) | |
| * assert.deepStrictEqual(Context.get(context, Timeout), { TIMEOUT: 5000 }) | |
| * assert.deepStrictEqual(Context.get(context, Host), { HOST: "localhost" }) | |
| * ``` | |
| * | |
| * @see {@link merge} for merging two contexts | |
| * | |
| * @category combining | |
| * @since 3.12.0 | |
| */ | |
| export const mergeAll = (...ctxs) => { | |
| const map = new Map(); | |
| for (let i = 0; i < ctxs.length; i++) { | |
| ctxs[i].mapUnsafe.forEach((value, key) => { | |
| map.set(key, value); | |
| }); | |
| } | |
| return makeUnsafe(map); | |
| }; | |
| /** | |
| * Returns a new `Context` that contains only the specified services. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you want to keep an allowlist of services in a `Context`. | |
| * | |
| * **Example** (Picking services from a context) | |
| * | |
| * ```ts | |
| * import { Context, Option, 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 = pipe( | |
| * Context.make(Port, { PORT: 8080 }), | |
| * Context.add(Timeout, { TIMEOUT: 5000 }) | |
| * ) | |
| * | |
| * const context = pipe(someContext, Context.pick(Port)) | |
| * | |
| * assert.deepStrictEqual( | |
| * Context.getOption(context, Port), | |
| * Option.some({ PORT: 8080 }) | |
| * ) | |
| * assert.deepStrictEqual(Context.getOption(context, Timeout), Option.none()) | |
| * ``` | |
| * | |
| * @see {@link omit} for removing selected services | |
| * | |
| * @category filtering | |
| * @since 2.0.0 | |
| */ | |
| export const pick = (...services) => self => withMapUnsafe(self, map => { | |
| const keySet = new Set(services.map(key => key.key)); | |
| map.forEach((_, key) => { | |
| if (keySet.has(key)) return; | |
| map.delete(key); | |
| }); | |
| }); | |
| /** | |
| * Returns a new `Context` with the specified service keys removed. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you want to remove a denylist of services from a `Context`. | |
| * | |
| * **Example** (Omitting services from a context) | |
| * | |
| * ```ts | |
| * import { Context, Option, 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 = pipe( | |
| * Context.make(Port, { PORT: 8080 }), | |
| * Context.add(Timeout, { TIMEOUT: 5000 }) | |
| * ) | |
| * | |
| * const context = pipe(someContext, Context.omit(Timeout)) | |
| * | |
| * assert.deepStrictEqual( | |
| * Context.getOption(context, Port), | |
| * Option.some({ PORT: 8080 }) | |
| * ) | |
| * assert.deepStrictEqual(Context.getOption(context, Timeout), Option.none()) | |
| * ``` | |
| * | |
| * @see {@link pick} for keeping selected services | |
| * | |
| * @category filtering | |
| * @since 2.0.0 | |
| */ | |
| export const omit = (...keys) => self => withMapUnsafe(self, map => { | |
| for (let i = 0; i < keys.length; i++) { | |
| map.delete(keys[i].key); | |
| } | |
| }); | |
| /** | |
| * Performs a series of mutations on a `Context`. Prevents unnecessary copying | |
| * of the underlying map when multiple mutations are needed. | |
| * | |
| * **When to use** | |
| * | |
| * Use to apply several `Context` transformations in one callback while copying | |
| * the underlying service map only once. | |
| * | |
| * @see {@link add} for adding or replacing a service | |
| * @see {@link addOrOmit} for adding or removing a service from an `Option` | |
| * @see {@link merge} for combining two contexts | |
| * @see {@link pick} for keeping selected services | |
| * @see {@link omit} for removing selected services | |
| * | |
| * @category mutations | |
| * @since 4.0.0 | |
| */ | |
| export const mutate = /*#__PURE__*/dual(2, (self, f) => { | |
| const next = makeUnsafe(new Map(self.mapUnsafe)); | |
| next.mutable = true; | |
| const result = f(next); | |
| result.mutable = false; | |
| return result; | |
| }); | |
| const withMapUnsafe = (self, f) => { | |
| if (self.mutable) { | |
| f(self.mapUnsafe); | |
| return self; | |
| } | |
| const map = new Map(self.mapUnsafe); | |
| f(map); | |
| return makeUnsafe(map); | |
| }; | |
| /** | |
| * Creates a context key with a default value. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need to define a context key with a lazily computed default | |
| * value. | |
| * | |
| * **Details** | |
| * | |
| * `Context.Reference` allows you to create a key 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. The default value is computed lazily and cached on the | |
| * reference. | |
| * | |
| * **Example** (Creating references with default values) | |
| * | |
| * ```ts | |
| * import { Context } from "effect" | |
| * | |
| * // Create a reference with a default value | |
| * const LoggerRef = Context.Reference("Logger", { | |
| * defaultValue: () => ({ log: (msg: string) => console.log(msg) }) | |
| * }) | |
| * | |
| * // The reference provides the default value when accessed from an empty context | |
| * const context = Context.empty() | |
| * const logger = Context.get(context, LoggerRef) | |
| * | |
| * // You can also override the default value | |
| * const customContext = Context.make(LoggerRef, { | |
| * log: (msg: string) => `Custom: ${msg}` | |
| * }) | |
| * const customLogger = Context.get(customContext, LoggerRef) | |
| * ``` | |
| * | |
| * @see {@link Service} for required services without default values | |
| * | |
| * @category references | |
| * @since 3.11.0 | |
| */ | |
| export const Reference = Service; | |
| //# sourceMappingURL=Context.js.map |
Xet Storage Details
- Size:
- 24.8 kB
- Xet hash:
- f8be30223e417c35ada94e999927bcf76d329f913cd893fc6c87f7e956cc3137
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.