(key: string, value: string): Effect.Effect<
void,
Config.ConfigError | ConfigKeyNotSwappable,
DynamicConfigStore
>Swap by raw env key — the string-keyed path for remote/RPC handlers that don't
hold a field (e.g. an RPC procedure that swaps an allowed key on its runtime).
Enforces the per-runtime allowlist — the key must have been declared swappable
— and validates the value through that key's Config.
export const const setByKey: (
key: string,
value: string
) => Effect.Effect<
void,
Config.ConfigError | ConfigKeyNotSwappable,
DynamicConfigStore
>
Swap by raw env key — the string-keyed path for remote/RPC handlers that don't
hold a field (e.g. an RPC procedure that swaps an allowed key on its runtime).
Enforces the per-runtime allowlist — the key must have been declared swappable
— and validates the value through that key's Config.
setByKey = (
key: stringkey: string,
value: stringvalue: string,
): import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<
void,
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 | class ConfigKeyNotSwappableclass ConfigKeyNotSwappable {
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;
key: string;
}
A string-keyed swap targeted a key that wasn't declared swappable in this
runtime's allowlist.
ConfigKeyNotSwappable,
class DynamicConfigStoreclass DynamicConfigStore {
key: Identifier;
Service: {
setRaw: (entries: ReadonlyArray<readonly [string, string]>) => Effect.Effect<void>;
unsetRaw: (keys: ReadonlyArray<string>) => Effect.Effect<void>;
changedKeys: Stream.Stream<ReadonlyArray<string>>;
allowed: ReadonlyMap<string, Config.Config<unknown>>;
};
}
Shared override store. Provided by
layer
; written by a swappable
field's .set / .reset (and
setByKey
), and read (as a
ConfigProvider) by every Config.
DynamicConfigStore
> =>
import EffectEffect.const gen: <Effect.Effect<{
readonly setRaw: (entries: ReadonlyArray<readonly [string, string]>) => Effect.Effect<void>;
readonly unsetRaw: (keys: ReadonlyArray<string>) => Effect.Effect<void>;
readonly changedKeys: Stream.Stream<ReadonlyArray<string>>;
readonly allowed: ReadonlyMap<string, Config.Config<unknown>>;
}, never, DynamicConfigStore> | Effect.Effect<never, ConfigKeyNotSwappable, never> | Effect.Effect<unknown, Config.ConfigError, never>, undefined>(f: () => Generator<...>) => Effect.Effect<...> (+1 overload)
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Example (Sequencing effects with generators)
import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function*() {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})
gen(function* () {
const const store: {
readonly setRaw: (
entries: ReadonlyArray<
readonly [string, string]
>
) => Effect.Effect<void>
readonly unsetRaw: (
keys: ReadonlyArray<string>
) => Effect.Effect<void>
readonly changedKeys: Stream.Stream<
ReadonlyArray<string>
>
readonly allowed: ReadonlyMap<
string,
Config.Config<unknown>
>
}
store = yield* class DynamicConfigStoreclass DynamicConfigStore {
key: Identifier;
Service: {
setRaw: (entries: ReadonlyArray<readonly [string, string]>) => Effect.Effect<void>;
unsetRaw: (keys: ReadonlyArray<string>) => Effect.Effect<void>;
changedKeys: Stream.Stream<ReadonlyArray<string>>;
allowed: ReadonlyMap<string, Config.Config<unknown>>;
};
of: (this: void, self: { readonly setRaw: (entries: ReadonlyArray<readonly [string, string]>) => Effect.Effect<void>; readonly unsetRaw: (keys: ReadonlyArray<string>) => Effect.Effect<void>; readonly changedKeys: Stream.Stream<ReadonlyArray<st…;
context: (self: { readonly setRaw: (entries: ReadonlyArray<readonly [string, string]>) => Effect.Effect<void>; readonly unsetRaw: (keys: ReadonlyArray<string>) => Effect.Effect<void>; readonly changedKeys: Stream.Stream<ReadonlyArray<string>>; read…;
use: (f: (service: { readonly setRaw: (entries: ReadonlyArray<readonly [string, string]>) => Effect.Effect<void>; readonly unsetRaw: (keys: ReadonlyArray<string>) => Effect.Effect<void>; readonly changedKeys: Stream.Stream<ReadonlyArray<string>…;
useSync: (f: (service: { readonly setRaw: (entries: ReadonlyArray<readonly [string, string]>) => Effect.Effect<void>; readonly unsetRaw: (keys: ReadonlyArray<string>) => Effect.Effect<void>; readonly changedKeys: Stream.Stream<ReadonlyArray<string>…;
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;
}
Shared override store. Provided by
layer
; written by a swappable
field's .set / .reset (and
setByKey
), and read (as a
ConfigProvider) by every Config.
DynamicConfigStore;
const const config:
| Config.Config<unknown>
| undefined
config = const store: {
readonly setRaw: (
entries: ReadonlyArray<
readonly [string, string]
>
) => Effect.Effect<void>
readonly unsetRaw: (
keys: ReadonlyArray<string>
) => Effect.Effect<void>
readonly changedKeys: Stream.Stream<
ReadonlyArray<string>
>
readonly allowed: ReadonlyMap<
string,
Config.Config<unknown>
>
}
store.allowed: ReadonlyMap<
string,
Config.Config<unknown>
>
This provision's
setByKey
allowlist: the process-wide
SwappableRegistry
(from
globalSwappable
) plus any
swappable
fields in the config passed to
layer
.
allowed.ReadonlyMap<string, Config<unknown>>.get(key: string): Config.Config<unknown> | undefinedget(key: stringkey);
if (const config:
| Config.Config<unknown>
| undefined
config === var undefinedundefined) {
return yield* new constructor ConfigKeyNotSwappable<{
readonly key: string;
}>(args: {
readonly key: string;
}): ConfigKeyNotSwappable
A string-keyed swap targeted a key that wasn't declared swappable in this
runtime's allowlist.
ConfigKeyNotSwappable({ key: stringkey });
}
yield* const config: Config.Config<unknown>const config: {
parse: (provider: ConfigProvider.ConfigProvider, pathPrefix?: Path) => Effect.Effect<T, ConfigError>;
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;
}
config.Config<unknown>.parse: (provider: ConfigProvider.ConfigProvider, pathPrefix?: ConfigProvider.Path) => Effect.Effect<unknown, Config.ConfigError, never>parse(const constProvider: (
raw: string
) => ConfigProvider.ConfigProvider
constProvider(value: stringvalue));
yield* const store: {
readonly setRaw: (
entries: ReadonlyArray<
readonly [string, string]
>
) => Effect.Effect<void>
readonly unsetRaw: (
keys: ReadonlyArray<string>
) => Effect.Effect<void>
readonly changedKeys: Stream.Stream<
ReadonlyArray<string>
>
readonly allowed: ReadonlyMap<
string,
Config.Config<unknown>
>
}
store.setRaw: (
entries: ReadonlyArray<
readonly [string, string]
>
) => Effect.Effect<void>
setRaw([[key: stringkey, value: stringvalue]]);
});