(): Effect.Effect<
{
readonly get: Effect.Effect<ReadonlyMap<string, DirectoryEntry>>
readonly getNode: (
nodeKey: string
) => Effect.Effect<Option.Option<DirectoryEntry>>
},
never,
Directory | Scope.Scope
>Live dial table driven by Directory.changes — for node-level peer rebind.
Starts empty; applies upserts/removes as they arrive. Pair with an initial
nodesServing seed when you need a cold snapshot before the first event.
export const const directoryTable: () => Effect.Effect<
{
readonly get: Effect.Effect<
ReadonlyMap<string, DirectoryEntry>
>
readonly getNode: (
nodeKey: string
) => Effect.Effect<
Option.Option<DirectoryEntry>
>
},
never,
Directory | Scope.Scope
>
Live dial table driven by
Directory.changes
— for node-level peer rebind.
Starts empty; applies upserts/removes as they arrive. Pair with an initial
nodesServing seed when you need a cold snapshot before the first event.
directoryTable = (): 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<
{
readonly get: Effect.Effect<
ReadonlyMap<string, DirectoryEntry>
>
(property) get: {
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;
}
get: 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<interface ReadonlyMap<K, V>ReadonlyMap<string, class DirectoryEntryclass DirectoryEntry {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
Directory row — dial target plus HyperService keys this node serves (listen catalog).
DirectoryEntry>>;
readonly getNode: (
nodeKey: string
) => Effect.Effect<Option.Option<DirectoryEntry>>
getNode: (
nodeKey: stringnodeKey: 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<import OptionOption.type Option<A> = Option.None<A> | Option.Some<A>The Option data type represents optional values. An Option<A> is either
Some<A>, containing a value of type A, or None, representing absence.
When to use
Use to represent initial values that may not yet exist
- Returning from partial functions (not defined for all inputs)
- Managing optional fields in data structures
Namespace containing utility types for Option.
When to use
Use to access type-level helpers associated with Option.
Option<class DirectoryEntryclass DirectoryEntry {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
Directory row — dial target plus HyperService keys this node serves (listen catalog).
DirectoryEntry>>;
},
never,
class Directoryclass Directory {
key: Identifier;
Service: {
advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; serves: ReadonlyArray<string>; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumbent' | 'reject' | 'inherit' | undefined }…;
unregister: (payload: { nodeKey: string; kind?: 'Http' | 'WebSocket' | 'IpcSocket' | undefined; url?: string | undefined; path?: string | undefined }) => Effect.Effect<boolean, never, never>;
nodesServing: (payload: { serviceKey: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, never>;
changes: Stream.Stream<DirectoryUpserted | DirectoryRemoved, never, never>;
};
}
Lookup node directory — advertise / unregister / list by served HyperService key /
directorySpec.changes
membership push.
Directory | import ScopeScope.Scope
> =>
import EffectEffect.const gen: {
<Eff extends Effect<any, any, any>, AEff>(
f: () => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
<Self, Eff extends Effect<any, any, any>, AEff>(
options: { readonly self: Self },
f: (this: Self) => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
}
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 table: Ref.Ref<
Map<string, DirectoryEntry>
>
const table: {
ref: MutableRef.MutableRef<A>;
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; <…;
}
table = yield* import RefRef.const make: <A>(
value: A
) => Effect.Effect<Ref<A>>
Creates a new Ref with the specified initial value.
When to use
Use to create a Ref for shared mutable state inside an Effect program.
Example (Creating a ref)
import { Effect, Ref } from "effect"
const program = Effect.gen(function*() {
const ref = yield* Ref.make(42)
const value = yield* Ref.get(ref)
console.log(value) // 42
})
make(new var Map: MapConstructor
new <string, DirectoryEntry>(iterable?: Iterable<readonly [string, DirectoryEntry]> | null | undefined) => Map<string, DirectoryEntry> (+3 overloads)
Map<string, class DirectoryEntryclass DirectoryEntry {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
Directory row — dial target plus HyperService keys this node serves (listen catalog).
DirectoryEntry>());
yield* const changes: Stream.Stream<
DirectoryChange,
never,
Directory
>
const changes: {
channel: Channel.Channel<Arr.NonEmptyReadonlyArray<A>, E, void, unknown, unknown, unknown, R>;
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; <…;
}
Live directory membership push — sugar over
Directory
.changes.
Subscribe from a node process to notice A→B dial swaps (DirectoryUpserted with
dialChanged: true) and rebind peer clients without restart.
yield* Lookup.changes.pipe(
Stream.filter((e) => e._tag === "DirectoryUpserted" && e.dialChanged),
Stream.runForEach((e) => Effect.logInfo(`dial moved ${e.entry.nodeKey}`)),
)
changes.Pipeable.pipe<Stream.Stream<DirectoryUpserted | DirectoryRemoved, never, Directory>, Effect.Effect<void, never, Directory>, Effect.Effect<Fiber<void, never>, never, Directory | Scope.Scope>>(this: Stream.Stream<...>, ab: (_: Stream.Stream<DirectoryUpserted | DirectoryRemoved, never, Directory>) => Effect.Effect<void, never, Directory>, bc: (_: Effect.Effect<void, never, Directory>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)pipe(
import StreamStream.const runForEach: {
<A, X, E2, R2>(
f: (a: A) => Effect.Effect<X, E2, R2>
): <E, R>(
self: Stream<A, E, R>
) => Effect.Effect<void, E2 | E, R2 | R>
<A, E, R, X, E2, R2>(
self: Stream<A, E, R>,
f: (a: A) => Effect.Effect<X, E2, R2>
): Effect.Effect<void, E | E2, R | R2>
}
Runs the provided effectful callback for each element of the stream.
Example (Running an effect for each value)
import { Console, Effect, Stream } from "effect"
const stream = Stream.make(1, 2, 3)
const program = Effect.gen(function*() {
yield* Stream.runForEach(stream, (n) => Console.log(`Processing: ${n}`))
})
Effect.runPromise(program)
// Processing: 1
// Processing: 2
// Processing: 3
runForEach((event: DirectoryUpserted | DirectoryRemovedevent) => {
if (event: DirectoryUpserted | DirectoryRemovedevent._tag: "DirectoryUpserted" | "DirectoryRemoved"_tag === "DirectoryRemoved") {
return import RefRef.const update: (<A>(
f: (a: A) => A
) => (self: Ref.Ref<A>) => Effect.Effect<void>) &
(<A>(
self: Ref.Ref<A>,
f: (a: A) => A
) => Effect.Effect<void>)
update(const table: Ref.Ref<
Map<string, DirectoryEntry>
>
const table: {
ref: MutableRef.MutableRef<A>;
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; <…;
}
table, (current: Map<string, DirectoryEntry>current) => {
const const next: Map<string, DirectoryEntry>next = new var Map: MapConstructor
new <string, DirectoryEntry>(iterable?: Iterable<readonly [string, DirectoryEntry]> | null | undefined) => Map<string, DirectoryEntry> (+3 overloads)
Map(current: Map<string, DirectoryEntry>current);
const next: Map<string, DirectoryEntry>next.Map<string, DirectoryEntry>.delete(key: string): booleandelete(event: DirectoryRemoved(parameter) event: {
_tag: 'DirectoryRemoved';
nodeKey: string;
previous: DirectoryEntry;
}
event.nodeKey: stringnodeKey);
return const next: Map<string, DirectoryEntry>next;
});
}
return import RefRef.const update: (<A>(
f: (a: A) => A
) => (self: Ref.Ref<A>) => Effect.Effect<void>) &
(<A>(
self: Ref.Ref<A>,
f: (a: A) => A
) => Effect.Effect<void>)
update(const table: Ref.Ref<
Map<string, DirectoryEntry>
>
const table: {
ref: MutableRef.MutableRef<A>;
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; <…;
}
table, (current: Map<string, DirectoryEntry>current) => {
const const next: Map<string, DirectoryEntry>next = new var Map: MapConstructor
new <string, DirectoryEntry>(iterable?: Iterable<readonly [string, DirectoryEntry]> | null | undefined) => Map<string, DirectoryEntry> (+3 overloads)
Map(current: Map<string, DirectoryEntry>current);
const next: Map<string, DirectoryEntry>next.Map<string, DirectoryEntry>.set(key: string, value: DirectoryEntry): Map<string, DirectoryEntry>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(event: DirectoryUpserted(parameter) event: {
_tag: 'DirectoryUpserted';
entry: DirectoryEntry;
dialChanged: boolean;
previous: DirectoryEntry | undefined;
}
event.entry: DirectoryEntry(property) entry: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
entry.nodeKey: stringnodeKey, event: DirectoryUpserted(parameter) event: {
_tag: 'DirectoryUpserted';
entry: DirectoryEntry;
dialChanged: boolean;
previous: DirectoryEntry | undefined;
}
event.entry: DirectoryEntry(property) entry: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
entry);
return const next: Map<string, DirectoryEntry>next;
});
}),
import EffectEffect.const forkScoped: <
Arg extends
| Effect<any, any, any>
| {
readonly startImmediately?:
| boolean
| undefined
readonly uninterruptible?:
| boolean
| "inherit"
| undefined
}
| undefined = {
readonly startImmediately?:
| boolean
| undefined
readonly uninterruptible?:
| boolean
| "inherit"
| undefined
}
>(
effectOrOptions?: Arg,
options?:
| {
readonly startImmediately?:
| boolean
| undefined
readonly uninterruptible?:
| boolean
| "inherit"
| undefined
}
| undefined
) => [Arg] extends [
Effect<infer _A, infer _E, infer _R>
]
? Effect<Fiber<_A, _E>, never, _R | Scope>
: <A, E, R>(
self: Effect<A, E, R>
) => Effect<Fiber<A, E>, never, R | Scope>
Forks the fiber in a Scope, interrupting it when the scope is closed.
Example (Forking into the current scope)
import { Effect } from "effect"
const backgroundTask = Effect.gen(function*() {
yield* Effect.sleep("5 seconds")
yield* Effect.log("Background task completed")
return "result"
})
const program = Effect.scoped(
Effect.gen(function*() {
const fiber = yield* backgroundTask.pipe(Effect.forkScoped)
// or fork a fiber that starts immediately:
yield* backgroundTask.pipe(Effect.forkScoped({ startImmediately: true }))
yield* Effect.log("Task forked in scope")
yield* Effect.sleep("1 second")
// Fiber will be interrupted when scope closes
return "scope completed"
})
)
forkScoped,
);
return {
get: Effect.Effect<
Map<string, DirectoryEntry>,
never,
never
>
(property) get: {
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;
}
get: import RefRef.const get: <A>(
self: Ref<A>
) => Effect.Effect<A, never, never>
Gets the current value of the Ref.
When to use
Use to read the current Ref value without changing it.
Example (Getting the current value)
import { Effect, Ref } from "effect"
const program = Effect.gen(function*() {
const ref = yield* Ref.make(42)
const value = yield* Ref.get(ref)
console.log(value) // 42
})
get(const table: Ref.Ref<
Map<string, DirectoryEntry>
>
const table: {
ref: MutableRef.MutableRef<A>;
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; <…;
}
table),
getNode: (
nodeKey: string
) => Effect.Effect<
Option.Option<DirectoryEntry>,
never,
never
>
getNode: (nodeKey: stringnodeKey: string) =>
import RefRef.const get: <A>(
self: Ref<A>
) => Effect.Effect<A, never, never>
Gets the current value of the Ref.
When to use
Use to read the current Ref value without changing it.
Example (Getting the current value)
import { Effect, Ref } from "effect"
const program = Effect.gen(function*() {
const ref = yield* Ref.make(42)
const value = yield* Ref.get(ref)
console.log(value) // 42
})
get(const table: Ref.Ref<
Map<string, DirectoryEntry>
>
const table: {
ref: MutableRef.MutableRef<A>;
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; <…;
}
table).Pipeable.pipe<Effect.Effect<Map<string, DirectoryEntry>, never, never>, Effect.Effect<Option.Option<DirectoryEntry>, never, never>>(this: Effect.Effect<Map<string, DirectoryEntry>, never, never>, ab: (_: Effect.Effect<Map<string, DirectoryEntry>, never, never>) => Effect.Effect<Option.Option<DirectoryEntry>, never, never>): Effect.Effect<Option.Option<DirectoryEntry>, never, never> (+21 overloads)pipe(
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((current: Map<string, DirectoryEntry>current) => import OptionOption.const fromNullishOr: <A>(
a: A
) => Option<NonNullable<A>>
Converts a nullable value (null or undefined) into an Option.
When to use
Use when you need JavaScript nullish values to become absence at an API
boundary while all other values, including falsy ones, remain present.
Details
null or undefined → None
- Any other value →
Some (typed as NonNullable<A>)
Example (Converting nullable values to an Option)
import { Option } from "effect"
console.log(Option.fromNullishOr(undefined))
// Output: { _id: 'Option', _tag: 'None' }
console.log(Option.fromNullishOr(null))
// Output: { _id: 'Option', _tag: 'None' }
console.log(Option.fromNullishOr(1))
// Output: { _id: 'Option', _tag: 'Some', value: 1 }
fromNullishOr(current: Map<string, DirectoryEntry>current.Map<string, DirectoryEntry>.get(key: string): DirectoryEntry | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(nodeKey: stringnodeKey))),
),
};
});