<Self, S extends Spec, EIn = never, RIn = never>(
tag: HyperlinkTag<Self, S>,
self: AnyNode,
options?: {
readonly nodes?: ReadonlyArray<AnyNode>
readonly url?: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
}
): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>Provide the peers capability on this node: connect every OTHER node in the tag's
distributed / nodes set and expose them as the peer clients. Also provides the
selfNode capability (this node's key) for byNode-style folds. The opt-in mesh — add
it to a node's serve only where the HyperService's own logic reaches across nodes. self is the node
you are, so you're excluded from your own peer set.
Membership (D3):
- Fixed — non-empty
options.nodesor stampednodes([…])/distributed([…]). - Directory — stamped empty set (bare
.pipe(Hyperlink.distributed)/nodes([])): read LookupDirectory.nodesServing(tag.key)at layer build. Soft empty map when Directory is absent. - Undeclared — no
nodesSymand nooptions.nodes→ empty static peers (not directory).
Peer addresses: each Node's own url / path is the default. Pass options.url to
override the url per node — an env-specific port, a tunnel, or a value from Effect Config —
falling back to Node.url when the resolver returns undefined. A node with no dialable address
is skipped (never a throw), so a partial mesh degrades cleanly. IpcSocket peers dial via
protocolIpc when only path is set. The resolver's error and requirements flow to the
layer (typed).
export const const peersLayer: <
Self,
S extends Spec,
EIn = never,
RIn = never
>(
tag: HyperlinkTag<Self, S>,
self: AnyNode,
options?: {
readonly nodes?: ReadonlyArray<AnyNode>
readonly url?: (
node: AnyNode
) => Effect.Effect<
string | undefined,
EIn,
RIn
>
}
) => Layer.Layer<
PeersId<Self> | SelfNodeId<Self>,
EIn,
RIn
>
Provide the
peers
capability on this node: connect every OTHER node in the tag's
distributed
/
nodes
set and expose them as the peer clients. Also provides the
selfNode
capability (this node's key) for byNode-style folds. The opt-in mesh — add
it to a node's serve only where the HyperService's own logic reaches across nodes. self is the node
you are, so you're excluded from your own peer set.
Membership (D3):
- Fixed — non-empty
options.nodes or stamped nodes([…]) / distributed([…]).
- Directory — stamped empty set (bare
.pipe(Hyperlink.distributed) / nodes([])): read
Lookup Directory.nodesServing(tag.key) at layer build. Soft empty map when Directory is absent.
- Undeclared — no
nodesSym and no options.nodes → empty static peers (not directory).
Peer addresses: each
Node
's own url / path is the default. Pass options.url to
override the url per node — an env-specific port, a tunnel, or a value from Effect Config —
falling back to Node.url when the resolver returns undefined. A node with no dialable address
is skipped (never a throw), so a partial mesh degrades cleanly. IpcSocket peers dial via
protocolIpc
when only path is set. The resolver's error and requirements flow to the
layer (typed).
peersLayer = <function (type parameter) Self in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
Self, function (type parameter) S in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
S extends Spec, function (type parameter) EIn in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
EIn = never, function (type parameter) RIn in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
RIn = never>(
tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
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;
}
tag: interface HyperlinkTag<Self, S extends Spec, Svc = Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<...> : S[K] extends DefaultMethod<...> ? F : S[K] extends { ...; } ? SuccessOf<...> : S[K] extends { ...; } ? Subscribable<...> : S[K] extends { ...; } ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }>>The type of a HyperService tag carrying spec S — what
Hyperlink.Tag
produces
(and what you extend). Lets a consumer write
<S extends Spec>(tag: HyperlinkTag<Self, S>) and read the spec through named types
(
specOf
/
groupOf
) instead of a Parameters<typeof specOf> workaround.
HyperlinkTag<function (type parameter) Self in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
Self, function (type parameter) S in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
S>,
self: AnyNodeself: type AnyNode = NodeKey<unknown> & {
readonly url: string | undefined;
readonly path: string | undefined;
readonly kind: ProtocolKind | undefined;
readonly endpoints?: Endpoints;
readonly onConflict?: OnConflict;
readonly [portSym]?: number;
}
A
Tag
erased — its transport endpoints set, plus the primary address
(url and/or Unix path) and
ProtocolKind
kind (the first-declared endpoint, kept for
single-protocol readers), so a tag's distributed set is self-describing about where AND how to
reach each one.
AnyNode,
options: {
readonly nodes?: ReadonlyArray<AnyNode>
readonly url?: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
}
options?: {
/** The fleet (including `self`) — supply it **at the use site** so a shared resource can be defined
* node-free and exported; falls back to the tag's baked-in {@link distributed} set when omitted.
* An explicit empty array is directory-backed (same as bare {@link distributed}). */
readonly nodes?: ReadonlyArray<AnyNode>The fleet (including self) — supply it at the use site so a shared resource can be defined
node-free and exported; falls back to the tag's baked-in
distributed
set when omitted.
An explicit empty array is directory-backed (same as bare
distributed
).
nodes?: interface ReadonlyArray<T>ReadonlyArray<type AnyNode = NodeKey<unknown> & {
readonly url: string | undefined;
readonly path: string | undefined;
readonly kind: ProtocolKind | undefined;
readonly endpoints?: Endpoints;
readonly onConflict?: OnConflict;
readonly [portSym]?: number;
}
A
Tag
erased — its transport endpoints set, plus the primary address
(url and/or Unix path) and
ProtocolKind
kind (the first-declared endpoint, kept for
single-protocol readers), so a tag's distributed set is self-describing about where AND how to
reach each one.
AnyNode>;
readonly url?: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
url?: (node: AnyNodenode: type AnyNode = NodeKey<unknown> & {
readonly url: string | undefined;
readonly path: string | undefined;
readonly kind: ProtocolKind | undefined;
readonly endpoints?: Endpoints;
readonly onConflict?: OnConflict;
readonly [portSym]?: number;
}
A
Tag
erased — its transport endpoints set, plus the primary address
(url and/or Unix path) and
ProtocolKind
kind (the first-declared endpoint, kept for
single-protocol readers), so a tag's distributed set is self-describing about where AND how to
reach each one.
AnyNode) => 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<string | undefined, function (type parameter) EIn in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
EIn, function (type parameter) RIn in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
RIn>;
},
): 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<interface PeersId<Self>Phantom brand for the per-HyperService
peers
capability, so distinct HyperServices' peer sets
don't collide in one context.
PeersId<function (type parameter) Self in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
Self> | interface SelfNodeId<Self>Phantom brand for the per-HyperService
selfNode
capability (which node this instance runs as),
so distinct HyperServices' self-node identities don't collide in one context.
SelfNodeId<function (type parameter) Self in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
Self>, function (type parameter) EIn in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
EIn, function (type parameter) RIn in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
RIn> =>
import LayerLayer.const merge: {
<RIn, E, ROut>(that: Layer<ROut, E, RIn>): <
RIn2,
E2,
ROut2
>(
self: Layer<ROut2, E2, RIn2>
) => Layer<ROut | ROut2, E | E2, RIn | RIn2>
<Layers extends [Any, ...Array<Any>]>(
that: Layers
): <A, E, R>(
self: Layer<A, E, R>
) => Layer<
A | Success<Layers[number]>,
E | Error<Layers[number]>,
Services<Layers[number]> | R
>
<RIn2, E2, ROut2, RIn, E, ROut>(
self: Layer<ROut2, E2, RIn2>,
that: Layer<ROut, E, RIn>
): Layer<ROut | ROut2, E | E2, RIn | RIn2>
<A, E, R, Layers extends [Any, ...Array<Any>]>(
self: Layer<A, E, R>,
that: Layers
): Layer<
A | Success<Layers[number]>,
E | Error<Layers[number]>,
Services<Layers[number]> | R
>
}
Merges this layer with another layer concurrently, producing a new layer with
combined input, error, and output types.
When to use
Use to combine an existing Layer with another Layer or an array of
layers while preserving pipeline style.
Details
This is a binary version of mergeAll that merges exactly two layers or one
layer with an array of layers. The layers are built concurrently and their
outputs are combined.
Example (Merging two layers)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
class Logger extends Context.Service<Logger, {
readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}
const dbLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed("result"))
})
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => console.log(msg)))
})
const mergedLayer = Layer.merge(dbLayer, loggerLayer)
merge(
import LayerLayer.const effect: {
<I, S>(service: Context.Key<I, S>): <E, R>(
effect: Effect<S, E, R>
) => Layer<I, E, Exclude<R, Scope.Scope>>
<I, S, E, R>(
service: Context.Key<I, S>,
effect: Effect<Types.NoInfer<S>, E, R>
): Layer<I, E, Exclude<R, Scope.Scope>>
}
Constructs a layer from an effect that produces a single service.
When to use
Use when you need to construct a Layer-provided service with an Effect,
dependencies, or scoped resource acquisition.
Details
This allows you to create a Layer from an Effect that produces a service.
The Effect is executed in the scope of the layer, allowing for proper
resource management.
Example (Creating a layer from an effect)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
const layer = Layer.effect(Database,
Effect.sync(() => ({
query: (sql: string) => Effect.succeed(`Query: ${sql}`)
}))
)
effect(
tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
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;
}
tag[const peersSym: typeof peersSymHolds a tag's per-HyperService
peers
capability key.
peersSym],
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 stamped:
| readonly AnyNode[]
| undefined
stamped =
options: {
readonly nodes?: ReadonlyArray<AnyNode>
readonly url?: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
}
options?.nodes?: ReadonlyArray<AnyNode>The fleet (including self) — supply it at the use site so a shared resource can be defined
node-free and exported; falls back to the tag's baked-in
distributed
set when omitted.
An explicit empty array is directory-backed (same as bare
distributed
).
nodes !== var undefinedundefined ? options: {
readonly nodes?: ReadonlyArray<AnyNode>
readonly url?: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
}
options.nodes?: ReadonlyArray<AnyNode>The fleet (including self) — supply it at the use site so a shared resource can be defined
node-free and exported; falls back to the tag's baked-in
distributed
set when omitted.
An explicit empty array is directory-backed (same as bare
distributed
).
nodes : tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
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;
}
tag[const nodesSym: typeof nodesSymHolds a tag's distributed set (the fleet).
nodesSym];
// D3: stamped empty set → Lookup directory membership (soft if Directory absent).
if (const stamped:
| readonly AnyNode[]
| undefined
stamped !== var undefinedundefined && const stamped: ReadonlyArray<AnyNode>stamped.ReadonlyArray<AnyNode>.length: numberGets the length of the array. This is a number one higher than the highest element defined in an array.
length === 0) {
const const Lookup: typeof import("/Users/nikolasstow/Coding/Hyperlink/worktrees/epsilon/src/Lookup")const Lookup: {
resolveOnConflict: (...prefs: ReadonlyArray<OnConflict | undefined>) => OnConflictResolved;
Endpoint: typeof Endpoint;
ClaimRequest: typeof ClaimRequest;
ResolveRequest: typeof ResolveRequest;
DuplicateIdentity: typeof DuplicateIdentity;
DirectoryEntry: typeof LookupDirectoryEntry;
AdvertiseRequest: typeof AdvertiseRequest;
UnregisterRequest: typeof UnregisterRequest;
NodesServingRequest: typeof NodesServingRequest;
IncumbentAlive: typeof IncumbentAlive;
AdviseRequest: typeof AdviseRequest;
ClearAdviceRequest: typeof ClearAdviceRequest;
PreferredRequest: typeof PreferredRequest;
LookupUnaddressed: typeof LookupUnaddressed;
kind: 'hyperlink-ts/Lookup';
Identity: typeof LookupIdentity;
Directory: typeof LookupDirectory;
Advice: typeof LookupAdvice;
nodesServing: (service: string | { readonly key: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, Directory>;
advise: (input: { readonly serviceKey: string; readonly prefer: string }) => Effect.Effect<string, never, Advice>;
prefer: (service: string | { readonly key: string }, nodeKey: string) => Effect.Effect<string, never, Advice>;
preferEntry: (service: string | { readonly key: string }, entry: { readonly nodeKey: string }) => Effect.Effect<string, never, Advice>;
clearAdvice: (service: string | { readonly key: string }) => Effect.Effect<boolean, never, Advice>;
preferred: (service: string | { readonly key: string }) => Effect.Effect<Option.Option<string>, never, Advice>;
defaultIpcPath: '/tmp/hyperlink-ts-lookup.sock';
layerIpc: (path: string, options?: { readonly unlink?: boolean; readonly onConflict?: OnConflictResolved }) => Layer.Layer<Directory | Identity | Advice | Hyperlink.Local<Identity> | Handler<'claim'> | Handler<'resolve'> | Hyperlink.Local<Directory>…;
layerNode: (node: AnyNode & { readonly key: string }, options?: { readonly unlink?: boolean }) => Layer.Layer<never, LookupUnaddressed>;
directoryAdvertiseLayer: (node: AnyNode & { readonly key: string }, serves: ReadonlyArray<string>, options?: { readonly onConflict?: OnConflict }) => Layer.Layer<never, IncumbentAlive>;
client: (node: AnyNode & { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
clientOptions: (options?: { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
layerOptions: (options?: { readonly path?: string; readonly unlink?: boolean }) => Layer.Layer<Services>;
layer: Layer.Layer<Services>;
}
Lookup = yield* import EffectEffect.const promise: <A>(
evaluate: (
signal: AbortSignal
) => PromiseLike<A>
) => Effect<A>
Creates an Effect that represents an asynchronous computation guaranteed to
succeed.
When to use
Use to convert a Promise into an Effect when the async operation is
guaranteed to succeed and will not reject.
Details
An optional AbortSignal can be provided to allow for interruption of the
wrapped Promise API.
Gotchas
The Promise must not reject. If it rejects, the rejection is treated as a
defect, not as a typed failure. Use tryPromise when rejection is expected.
Interruption aborts the provided AbortSignal, but the underlying
asynchronous operation only stops if it observes that signal.
Example (Wrapping a non-rejecting Promise)
import { Effect } from "effect"
const delay = (message: string) =>
Effect.promise<string>(
() =>
new Promise((resolve) => {
setTimeout(() => {
resolve(message)
}, 2000)
})
)
// ┌─── Effect<string, never, never>
// ▼
const program = delay("Async operation completed successfully!")
promise(() => import("./Lookup"));
const const dirOpt: Option.Option<{
readonly advertise: (payload: {
kind: "Http" | "WebSocket" | "IpcSocket"
serves: ReadonlyArray<string>
nodeKey: string
url?: string | undefined
path?: string | undefined
onConflict?:
| "livenessReplace"
| "askIncumbent"
| "reject"
| "inherit"
| undefined
}) => Effect.Effect<
LookupDirectoryEntry,
IncumbentAlive,
never
>
readonly unregister: (payload: {
nodeKey: string
kind?:
| "Http"
| "WebSocket"
| "IpcSocket"
| undefined
url?: string | undefined
path?: string | undefined
}) => Effect.Effect<boolean, never, never>
readonly nodesServing: (payload: {
serviceKey: string
}) => Effect.Effect<
ReadonlyArray<LookupDirectoryEntry>,
never,
never
>
}>
dirOpt = yield* import EffectEffect.const serviceOption: <I, S>(
key: Context.Key<I, S>
) => Effect<Option<S>>
Optionally accesses a service from the environment.
When to use
Use to read an optional dependency from the current context without making
that dependency part of the effect's required environment.
Details
This function attempts to access a service from the environment. If the
service is available, it returns Some(service). If the service is not
available, it returns None. Unlike service, this function does not
require the service to be present in the environment.
Example (Accessing an optional service)
import { Context, Effect, Option } from "effect"
// Define a service key
const Logger = Context.Service<{
log: (msg: string) => void
}>("Logger")
// Use serviceOption to optionally access the logger
const program = Effect.gen(function*() {
const maybeLogger = yield* Effect.serviceOption(Logger)
if (Option.isSome(maybeLogger)) {
maybeLogger.value.log("Service is available")
} else {
console.log("Service not available")
}
})
serviceOption(const Lookup: typeof import("/Users/nikolasstow/Coding/Hyperlink/worktrees/epsilon/src/Lookup")const Lookup: {
resolveOnConflict: (...prefs: ReadonlyArray<OnConflict | undefined>) => OnConflictResolved;
Endpoint: typeof Endpoint;
ClaimRequest: typeof ClaimRequest;
ResolveRequest: typeof ResolveRequest;
DuplicateIdentity: typeof DuplicateIdentity;
DirectoryEntry: typeof LookupDirectoryEntry;
AdvertiseRequest: typeof AdvertiseRequest;
UnregisterRequest: typeof UnregisterRequest;
NodesServingRequest: typeof NodesServingRequest;
IncumbentAlive: typeof IncumbentAlive;
AdviseRequest: typeof AdviseRequest;
ClearAdviceRequest: typeof ClearAdviceRequest;
PreferredRequest: typeof PreferredRequest;
LookupUnaddressed: typeof LookupUnaddressed;
kind: 'hyperlink-ts/Lookup';
Identity: typeof LookupIdentity;
Directory: typeof LookupDirectory;
Advice: typeof LookupAdvice;
nodesServing: (service: string | { readonly key: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, Directory>;
advise: (input: { readonly serviceKey: string; readonly prefer: string }) => Effect.Effect<string, never, Advice>;
prefer: (service: string | { readonly key: string }, nodeKey: string) => Effect.Effect<string, never, Advice>;
preferEntry: (service: string | { readonly key: string }, entry: { readonly nodeKey: string }) => Effect.Effect<string, never, Advice>;
clearAdvice: (service: string | { readonly key: string }) => Effect.Effect<boolean, never, Advice>;
preferred: (service: string | { readonly key: string }) => Effect.Effect<Option.Option<string>, never, Advice>;
defaultIpcPath: '/tmp/hyperlink-ts-lookup.sock';
layerIpc: (path: string, options?: { readonly unlink?: boolean; readonly onConflict?: OnConflictResolved }) => Layer.Layer<Directory | Identity | Advice | Hyperlink.Local<Identity> | Handler<'claim'> | Handler<'resolve'> | Hyperlink.Local<Directory>…;
layerNode: (node: AnyNode & { readonly key: string }, options?: { readonly unlink?: boolean }) => Layer.Layer<never, LookupUnaddressed>;
directoryAdvertiseLayer: (node: AnyNode & { readonly key: string }, serves: ReadonlyArray<string>, options?: { readonly onConflict?: OnConflict }) => Layer.Layer<never, IncumbentAlive>;
client: (node: AnyNode & { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
clientOptions: (options?: { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
layerOptions: (options?: { readonly path?: string; readonly unlink?: boolean }) => Layer.Layer<Services>;
layer: Layer.Layer<Services>;
}
Lookup.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<LookupDirectoryEntry>, never, never>;
};
description: string | undefined;
of: (this: void, self: { readonly advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; serves: ReadonlyArray<string>; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumb…;
context: (self: { readonly advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; serves: ReadonlyArray<string>; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumbent' | 'reje…;
use: (f: (service: { readonly advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; serves: ReadonlyArray<string>; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumbent' …;
useSync: (f: (service: { readonly advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; serves: ReadonlyArray<string>; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumbent' …;
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;
}
Lookup node directory — advertise / unregister / list by served HyperService key.
Directory);
if (import OptionOption.const isNone: <A>(
self: Option<A>
) => self is None<A>
Checks whether an Option is None (absent).
When to use
Use when you need to branch on an absent Option before accessing .value.
Details
- Acts as a type guard, narrowing to
None<A>
Example (Checking for None)
import { Option } from "effect"
console.log(Option.isNone(Option.some(1)))
// Output: false
console.log(Option.isNone(Option.none()))
// Output: true
isNone(const dirOpt: Option.Option<{
readonly advertise: (payload: {
kind: "Http" | "WebSocket" | "IpcSocket"
serves: ReadonlyArray<string>
nodeKey: string
url?: string | undefined
path?: string | undefined
onConflict?:
| "livenessReplace"
| "askIncumbent"
| "reject"
| "inherit"
| undefined
}) => Effect.Effect<
LookupDirectoryEntry,
IncumbentAlive,
never
>
readonly unregister: (payload: {
nodeKey: string
kind?:
| "Http"
| "WebSocket"
| "IpcSocket"
| undefined
url?: string | undefined
path?: string | undefined
}) => Effect.Effect<boolean, never, never>
readonly nodesServing: (payload: {
serviceKey: string
}) => Effect.Effect<
ReadonlyArray<LookupDirectoryEntry>,
never,
never
>
}>
dirOpt)) {
return {} as type Record<K extends keyof any, T> = {
[P in K]: T
}
Construct a type with a set of properties K of type T
Record<string, type PeerServiceOf<S extends Spec> = {
readonly [K in keyof S as S[K] extends {
readonly fleet: true
}
? never
: S[K] extends
| AnyLocalMethod
| AnyDefaultMethod
? never
: K]: S[K] extends {
readonly _tag: "ref"
}
? Effect.Effect<
SuccessOf<AsMethod<S[K]>>,
never,
never
>
: S[K] extends {
readonly kind: MethodKind
}
? ServiceMethod<AsMethod<S[K]>>
: S[K] extends Spec
? PeerServiceOf<S[K]>
: never
}
A peer's service as seen by
peers
— the per-instance ("leaf") wire methods only:
FleetField
s and
LocalMethod
s are excluded, so a fold can't recurse into a peer's
own fleet field. A full
ServiceOf
is assignable to it (width), so real clients fit.
PeerServiceOf<function (type parameter) S in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
S>>;
}
const const rows: ReadonlyArray<LookupDirectoryEntry>rows = yield* const Lookup: typeof import("/Users/nikolasstow/Coding/Hyperlink/worktrees/epsilon/src/Lookup")const Lookup: {
resolveOnConflict: (...prefs: ReadonlyArray<OnConflict | undefined>) => OnConflictResolved;
Endpoint: typeof Endpoint;
ClaimRequest: typeof ClaimRequest;
ResolveRequest: typeof ResolveRequest;
DuplicateIdentity: typeof DuplicateIdentity;
DirectoryEntry: typeof LookupDirectoryEntry;
AdvertiseRequest: typeof AdvertiseRequest;
UnregisterRequest: typeof UnregisterRequest;
NodesServingRequest: typeof NodesServingRequest;
IncumbentAlive: typeof IncumbentAlive;
AdviseRequest: typeof AdviseRequest;
ClearAdviceRequest: typeof ClearAdviceRequest;
PreferredRequest: typeof PreferredRequest;
LookupUnaddressed: typeof LookupUnaddressed;
kind: 'hyperlink-ts/Lookup';
Identity: typeof LookupIdentity;
Directory: typeof LookupDirectory;
Advice: typeof LookupAdvice;
nodesServing: (service: string | { readonly key: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, Directory>;
advise: (input: { readonly serviceKey: string; readonly prefer: string }) => Effect.Effect<string, never, Advice>;
prefer: (service: string | { readonly key: string }, nodeKey: string) => Effect.Effect<string, never, Advice>;
preferEntry: (service: string | { readonly key: string }, entry: { readonly nodeKey: string }) => Effect.Effect<string, never, Advice>;
clearAdvice: (service: string | { readonly key: string }) => Effect.Effect<boolean, never, Advice>;
preferred: (service: string | { readonly key: string }) => Effect.Effect<Option.Option<string>, never, Advice>;
defaultIpcPath: '/tmp/hyperlink-ts-lookup.sock';
layerIpc: (path: string, options?: { readonly unlink?: boolean; readonly onConflict?: OnConflictResolved }) => Layer.Layer<Directory | Identity | Advice | Hyperlink.Local<Identity> | Handler<'claim'> | Handler<'resolve'> | Hyperlink.Local<Directory>…;
layerNode: (node: AnyNode & { readonly key: string }, options?: { readonly unlink?: boolean }) => Layer.Layer<never, LookupUnaddressed>;
directoryAdvertiseLayer: (node: AnyNode & { readonly key: string }, serves: ReadonlyArray<string>, options?: { readonly onConflict?: OnConflict }) => Layer.Layer<never, IncumbentAlive>;
client: (node: AnyNode & { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
clientOptions: (options?: { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
layerOptions: (options?: { readonly path?: string; readonly unlink?: boolean }) => Layer.Layer<Services>;
layer: Layer.Layer<Services>;
}
Lookup.const nodesServing: (
service: string | { readonly key: string }
) => Effect.Effect<
ReadonlyArray<DirectoryEntry>,
never,
Directory
>
List directory rows that advertise a HyperService (Tag or wire key).
Sugar over
Directory
.nodesServing — wire stays
NodesServingRequest
.
const rows = yield* Lookup.nodesServing(Jobs)
// or Lookup.nodesServing("fleet/Jobs")
nodesServing(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
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;
}
tag).Pipeable.pipe<Effect.Effect<readonly LookupDirectoryEntry[], never, LookupDirectory>, Effect.Effect<readonly LookupDirectoryEntry[], never, never>>(this: Effect.Effect<readonly LookupDirectoryEntry[], never, LookupDirectory>, ab: (_: Effect.Effect<readonly LookupDirectoryEntry[], never, LookupDirectory>) => Effect.Effect<readonly LookupDirectoryEntry[], never, never>): Effect.Effect<readonly LookupDirectoryEntry[], never, never> (+21 overloads)pipe(
import EffectEffect.const provideService: {
<I, S>(service: Context.Key<I, S>): {
(implementation: S): <A, E, R>(
self: Effect<A, E, R>
) => Effect<A, E, Exclude<R, I>>
<A, E, R>(
self: Effect<A, E, R>,
implementation: S
): Effect<A, E, Exclude<R, I>>
}
<I, S>(
service: Context.Key<I, S>,
implementation: S
): <A, E, R>(
self: Effect<A, E, R>
) => Effect<A, E, Exclude<R, I>>
<A, E, R, I, S>(
self: Effect<A, E, R>,
service: Context.Key<I, S>,
implementation: S
): Effect<A, E, Exclude<R, I>>
}
Provides one concrete service implementation to an effect.
When to use
Use to satisfy one service requirement with an already-built implementation.
Details
The service requirement identified by the Context.Key is removed from the
effect requirements after the implementation is provided.
Example (Providing a service value)
import { Console, Context, Effect } from "effect"
// Define a service for configuration
const Config = Context.Service<{
apiUrl: string
timeout: number
}>("Config")
const fetchData = Effect.gen(function*() {
const config = yield* Effect.service(Config)
yield* Console.log(`Fetching from: ${config.apiUrl}`)
yield* Console.log(`Timeout: ${config.timeout}ms`)
return "data"
})
// Provide the service implementation
const program = Effect.provideService(fetchData, Config, {
apiUrl: "https://api.example.com",
timeout: 5000
})
Effect.runPromise(program).then(console.log)
// Output:
// Fetching from: https://api.example.com
// Timeout: 5000ms
// data
provideService(const Lookup: typeof import("/Users/nikolasstow/Coding/Hyperlink/worktrees/epsilon/src/Lookup")const Lookup: {
resolveOnConflict: (...prefs: ReadonlyArray<OnConflict | undefined>) => OnConflictResolved;
Endpoint: typeof Endpoint;
ClaimRequest: typeof ClaimRequest;
ResolveRequest: typeof ResolveRequest;
DuplicateIdentity: typeof DuplicateIdentity;
DirectoryEntry: typeof LookupDirectoryEntry;
AdvertiseRequest: typeof AdvertiseRequest;
UnregisterRequest: typeof UnregisterRequest;
NodesServingRequest: typeof NodesServingRequest;
IncumbentAlive: typeof IncumbentAlive;
AdviseRequest: typeof AdviseRequest;
ClearAdviceRequest: typeof ClearAdviceRequest;
PreferredRequest: typeof PreferredRequest;
LookupUnaddressed: typeof LookupUnaddressed;
kind: 'hyperlink-ts/Lookup';
Identity: typeof LookupIdentity;
Directory: typeof LookupDirectory;
Advice: typeof LookupAdvice;
nodesServing: (service: string | { readonly key: string }) => Effect.Effect<ReadonlyArray<DirectoryEntry>, never, Directory>;
advise: (input: { readonly serviceKey: string; readonly prefer: string }) => Effect.Effect<string, never, Advice>;
prefer: (service: string | { readonly key: string }, nodeKey: string) => Effect.Effect<string, never, Advice>;
preferEntry: (service: string | { readonly key: string }, entry: { readonly nodeKey: string }) => Effect.Effect<string, never, Advice>;
clearAdvice: (service: string | { readonly key: string }) => Effect.Effect<boolean, never, Advice>;
preferred: (service: string | { readonly key: string }) => Effect.Effect<Option.Option<string>, never, Advice>;
defaultIpcPath: '/tmp/hyperlink-ts-lookup.sock';
layerIpc: (path: string, options?: { readonly unlink?: boolean; readonly onConflict?: OnConflictResolved }) => Layer.Layer<Directory | Identity | Advice | Hyperlink.Local<Identity> | Handler<'claim'> | Handler<'resolve'> | Hyperlink.Local<Directory>…;
layerNode: (node: AnyNode & { readonly key: string }, options?: { readonly unlink?: boolean }) => Layer.Layer<never, LookupUnaddressed>;
directoryAdvertiseLayer: (node: AnyNode & { readonly key: string }, serves: ReadonlyArray<string>, options?: { readonly onConflict?: OnConflict }) => Layer.Layer<never, IncumbentAlive>;
client: (node: AnyNode & { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
clientOptions: (options?: { readonly path?: string }) => Layer.Layer<Services, LookupUnaddressed>;
layerOptions: (options?: { readonly path?: string; readonly unlink?: boolean }) => Layer.Layer<Services>;
layer: Layer.Layer<Services>;
}
Lookup.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<LookupDirectoryEntry>, never, never>;
};
description: string | undefined;
of: (this: void, self: { readonly advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; serves: ReadonlyArray<string>; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumb…;
context: (self: { readonly advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; serves: ReadonlyArray<string>; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumbent' | 'reje…;
use: (f: (service: { readonly advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; serves: ReadonlyArray<string>; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumbent' …;
useSync: (f: (service: { readonly advertise: (payload: { kind: 'Http' | 'WebSocket' | 'IpcSocket'; serves: ReadonlyArray<string>; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: 'livenessReplace' | 'askIncumbent' …;
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;
}
Lookup node directory — advertise / unregister / list by served HyperService key.
Directory, const dirOpt: Option.Some<{
readonly advertise: (payload: {
kind: "Http" | "WebSocket" | "IpcSocket"
serves: ReadonlyArray<string>
nodeKey: string
url?: string | undefined
path?: string | undefined
onConflict?:
| "livenessReplace"
| "askIncumbent"
| "reject"
| "inherit"
| undefined
}) => Effect.Effect<
LookupDirectoryEntry,
IncumbentAlive,
never
>
readonly unregister: (payload: {
nodeKey: string
kind?:
| "Http"
| "WebSocket"
| "IpcSocket"
| undefined
url?: string | undefined
path?: string | undefined
}) => Effect.Effect<boolean, never, never>
readonly nodesServing: (payload: {
serviceKey: string
}) => Effect.Effect<
ReadonlyArray<LookupDirectoryEntry>,
never,
never
>
}>
const dirOpt: {
_tag: "Some";
_op: "Some";
value: A;
valueOrUndefined: 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; <…;
toString: () => string;
toJSON: () => unknown;
}
dirOpt.Some<{ readonly advertise: (payload: { kind: "Http" | "WebSocket" | "IpcSocket"; serves: readonly string[]; nodeKey: string; url?: string | undefined; path?: string | undefined; onConflict?: "livenessReplace" | "askIncumbent" | "reject" | "inherit" | undefined; }) => Effect<...>; readonly unregister: (payload: { ...; }) => Effect<...>; readonly nodesServing: (payload: { ...; }) => Effect<...>; }>.value: {
readonly advertise: (payload: {
kind: "Http" | "WebSocket" | "IpcSocket";
serves: readonly string[];
nodeKey: string;
url?: string | undefined;
path?: string | undefined;
onConflict?: "livenessReplace" | "askIncumbent" | "reject" | "inherit" | undefined;
}) => Effect.Effect<LookupDirectoryEntry, IncumbentAlive, never>;
readonly unregister: (payload: {
nodeKey: string;
kind?: "Http" | "WebSocket" | "IpcSocket" | undefined;
url?: string | undefined;
path?: string | undefined;
}) => Effect.Effect<boolean, never, never>;
readonly nodesServing: (payload: {
...;
}) => Effect.Effect<...>;
}
value),
);
type type DialTarget = {
readonly key: string
readonly kind: ProtocolKind
readonly url?: string
readonly path?: string
}
DialTarget = {
readonly key: stringkey: string;
readonly kind: ProtocolKindkind: type ProtocolKind = "Http" | "WebSocket" | "IpcSocket"The transport a
Node
speaks — tag-style names (apps rarely type this alias; they write
the literals or get inference from url / path):
"Http" — RpcClient.layerProtocolHttp (servers / CLIs)
"WebSocket" — browser WS (layerProtocolWebsocket / client layerProtocolSocket over WS)
"IpcSocket" — Unix-domain socket (same-machine; see
ipcServer
)
Stamped on the node so the topology is self-describing about how to reach it — connect/client
derive the transport from it. Inferred from a ws(s):// url, an http target, or { path } →
IpcSocket; otherwise declare it explicitly.
ProtocolKind;
readonly url?: string | undefinedurl?: string;
readonly path?: string | undefinedpath?: string;
};
const const dialable: DialTarget[]dialable: interface Array<T>Array<type DialTarget = {
readonly key: string
readonly kind: ProtocolKind
readonly url?: string
readonly path?: string
}
DialTarget> = [];
for (const const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row of const rows: ReadonlyArray<LookupDirectoryEntry>rows) {
if (const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.nodeKey: stringnodeKey === self: AnyNodeself.Key<unknown, NodeProtocol>.key: stringkey) continue;
if (const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.kind: "Http" | "WebSocket" | "IpcSocket"kind === "IpcSocket" && const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.path?: string | undefinedpath !== var undefinedundefined) {
const dialable: DialTarget[]dialable.Array<DialTarget>.push(...items: DialTarget[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push({
key: stringkey: const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.nodeKey: stringnodeKey,
kind: ProtocolKindkind: const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.kind: "IpcSocket"kind,
path?: string | undefinedpath: const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.path?: stringpath,
});
continue;
}
if (const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.url?: string | undefinedurl !== var undefinedundefined) {
const dialable: DialTarget[]dialable.Array<DialTarget>.push(...items: DialTarget[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push({
key: stringkey: const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.nodeKey: stringnodeKey,
kind: ProtocolKindkind: const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.kind: "Http" | "WebSocket" | "IpcSocket"kind,
url?: string | undefinedurl: const row: LookupDirectoryEntryconst row: {
kind: 'Http' | 'WebSocket' | 'IpcSocket';
serves: ReadonlyArray<string>;
nodeKey: string;
url: string | undefined;
path: string | undefined;
}
row.url?: stringurl,
});
}
}
const const discovered: (readonly [
string,
PeerServiceOf<S>
])[]
discovered = yield* import EffectEffect.const forEach: {
<
B,
E,
R,
S extends Iterable<any>,
Discard extends boolean = false
>(
f: (
a: Arr.ReadonlyArray.Infer<S>,
i: number
) => Effect<B, E, R>,
options?:
| {
readonly concurrency?:
| Concurrency
| undefined
readonly discard?: Discard | undefined
}
| undefined
): (
self: S
) => Effect<
Discard extends false
? Arr.ReadonlyArray.With<S, B>
: void,
E,
R
>
<
B,
E,
R,
S extends Iterable<any>,
Discard extends boolean = false
>(
self: S,
f: (
a: Arr.ReadonlyArray.Infer<S>,
i: number
) => Effect<B, E, R>,
options?:
| {
readonly concurrency?:
| Concurrency
| undefined
readonly discard?: Discard | undefined
}
| undefined
): Effect<
Discard extends false
? Arr.ReadonlyArray.With<S, B>
: void,
E,
R
>
}
Executes an effectful operation for each element in an Iterable.
When to use
Use to traverse an iterable with an effectful function while preserving
element order in the collected results.
Details
The forEach function applies a provided operation to each element in the
iterable, producing a new effect that returns an array of results.
If any effect fails, the iteration stops immediately (short-circuiting), and
the error is propagated.
Concurrency:
The concurrency option controls how many operations are performed
concurrently. By default, the operations are performed sequentially.
Discarding Results:
If the discard option is set to true, the intermediate results are not
collected, and the final result of the operation is void.
Example (Mapping over an iterable with effects)
import { Console, Effect } from "effect"
const result = Effect.forEach(
[1, 2, 3, 4, 5],
(n, index) =>
Console.log(`Currently at index ${index}`).pipe(Effect.as(n * 2))
)
Effect.runPromise(result).then(console.log)
// Output:
// Currently at index 0
// Currently at index 1
// Currently at index 2
// Currently at index 3
// Currently at index 4
// [ 2, 4, 6, 8, 10 ]
Example (Running effects without collecting results)
import { Console, Effect } from "effect"
// Apply effects but discard the results
const result = Effect.forEach(
[1, 2, 3, 4, 5],
(n, index) =>
Console.log(`Currently at index ${index}`).pipe(Effect.as(n * 2)),
{ discard: true }
)
Effect.runPromise(result).then(console.log)
// Output:
// Currently at index 0
// Currently at index 1
// Currently at index 2
// Currently at index 3
// Currently at index 4
// undefined
forEach(const dialable: DialTarget[]dialable, (target: DialTarget(parameter) target: {
key: string;
kind: ProtocolKind;
url: string;
path: string;
}
target) =>
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(
const buildPeerClientAt: <
Self,
S extends Spec
>(
tag: HyperlinkTag<Self, S>,
target: {
readonly key: string
readonly kind?: ProtocolKind
readonly url?: string
readonly path?: string
}
) => Effect.Effect<
PeerServiceOf<S>,
never,
Scope.Scope
>
Dial a peer from a directory row or static Node address — kind-aware (D3).
Prefer url when set (honors options.url overrides +
peerProtocolRef
);
WebSocket kind uses
protocolWebsocket
. Else IpcSocket/path →
protocolIpc
.
buildPeerClientAt(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
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;
}
tag, target: DialTarget(parameter) target: {
key: string;
kind: ProtocolKind;
url: string;
path: string;
}
target),
(client: PeerServiceOf<S>client) => [target: DialTarget(parameter) target: {
key: string;
kind: ProtocolKind;
url: string;
path: string;
}
target.key: stringkey, client: PeerServiceOf<S>client] as type const = readonly [string, PeerServiceOf<S>]const,
),
);
return var Object: ObjectConstructorProvides functionality common to all JavaScript objects.
Object.ObjectConstructor.fromEntries<PeerServiceOf<S>>(entries: Iterable<readonly [PropertyKey, PeerServiceOf<S>]>): {
[k: string]: PeerServiceOf<S>;
} (+1 overload)
Returns an object created by key-value entries for properties and methods
fromEntries(const discovered: (readonly [
string,
PeerServiceOf<S>
])[]
discovered) as unknown as type Record<K extends keyof any, T> = {
[P in K]: T
}
Construct a type with a set of properties K of type T
Record<
string,
type PeerServiceOf<S extends Spec> = {
readonly [K in keyof S as S[K] extends {
readonly fleet: true
}
? never
: S[K] extends
| AnyLocalMethod
| AnyDefaultMethod
? never
: K]: S[K] extends {
readonly _tag: "ref"
}
? Effect.Effect<
SuccessOf<AsMethod<S[K]>>,
never,
never
>
: S[K] extends {
readonly kind: MethodKind
}
? ServiceMethod<AsMethod<S[K]>>
: S[K] extends Spec
? PeerServiceOf<S[K]>
: never
}
A peer's service as seen by
peers
— the per-instance ("leaf") wire methods only:
FleetField
s and
LocalMethod
s are excluded, so a fold can't recurse into a peer's
own fleet field. A full
ServiceOf
is assignable to it (width), so real clients fit.
PeerServiceOf<function (type parameter) S in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
S>
>;
}
// Fixed fleet (or undeclared → []); drop self to get the peers.
const const fleet: ReadonlyArray<AnyNode>fleet = const stamped:
| readonly AnyNode[]
| undefined
stamped ?? [];
const const others: Array<AnyNode>others = const fleet: ReadonlyArray<AnyNode>fleet.ReadonlyArray<AnyNode>.filter(predicate: (value: AnyNode, index: number, array: readonly AnyNode[]) => unknown, thisArg?: any): AnyNode[] (+1 overload)Returns the elements of an array that meet the condition specified in a callback function.
filter((node: AnyNodenode) => node: AnyNodenode.Key<unknown, NodeProtocol>.key: stringkey !== self: AnyNodeself.Key<unknown, NodeProtocol>.key: stringkey);
const const resolveUrl: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
resolveUrl = (
node: AnyNodenode: type AnyNode = NodeKey<unknown> & {
readonly url: string | undefined;
readonly path: string | undefined;
readonly kind: ProtocolKind | undefined;
readonly endpoints?: Endpoints;
readonly onConflict?: OnConflict;
readonly [portSym]?: number;
}
A
Tag
erased — its transport endpoints set, plus the primary address
(url and/or Unix path) and
ProtocolKind
kind (the first-declared endpoint, kept for
single-protocol readers), so a tag's distributed set is self-describing about where AND how to
reach each one.
AnyNode,
): 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<string | undefined, function (type parameter) EIn in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
EIn, function (type parameter) RIn in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
RIn> =>
options: {
readonly nodes?: ReadonlyArray<AnyNode>
readonly url?: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
}
options?.url?: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
url === var undefinedundefined
? import EffectEffect.const succeed: <A>(value: A) => Effect<A>Creates an Effect that always succeeds with a given value.
When to use
Use when an effect should complete successfully with a specific value without any errors
or external dependencies.
Example (Creating a successful effect)
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)
succeed(node: AnyNodenode.url: string | undefinedurl)
: 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(options: {
readonly nodes?: ReadonlyArray<AnyNode>
readonly url?: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
}
options.url?: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
url(node: AnyNodenode), (override: string | undefinedoverride) => override: string | undefinedoverride ?? node: AnyNodenode.url: string | undefinedurl);
const const resolved: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}[]
resolved = yield* import EffectEffect.const forEach: {
<
B,
E,
R,
S extends Iterable<any>,
Discard extends boolean = false
>(
f: (
a: Arr.ReadonlyArray.Infer<S>,
i: number
) => Effect<B, E, R>,
options?:
| {
readonly concurrency?:
| Concurrency
| undefined
readonly discard?: Discard | undefined
}
| undefined
): (
self: S
) => Effect<
Discard extends false
? Arr.ReadonlyArray.With<S, B>
: void,
E,
R
>
<
B,
E,
R,
S extends Iterable<any>,
Discard extends boolean = false
>(
self: S,
f: (
a: Arr.ReadonlyArray.Infer<S>,
i: number
) => Effect<B, E, R>,
options?:
| {
readonly concurrency?:
| Concurrency
| undefined
readonly discard?: Discard | undefined
}
| undefined
): Effect<
Discard extends false
? Arr.ReadonlyArray.With<S, B>
: void,
E,
R
>
}
Executes an effectful operation for each element in an Iterable.
When to use
Use to traverse an iterable with an effectful function while preserving
element order in the collected results.
Details
The forEach function applies a provided operation to each element in the
iterable, producing a new effect that returns an array of results.
If any effect fails, the iteration stops immediately (short-circuiting), and
the error is propagated.
Concurrency:
The concurrency option controls how many operations are performed
concurrently. By default, the operations are performed sequentially.
Discarding Results:
If the discard option is set to true, the intermediate results are not
collected, and the final result of the operation is void.
Example (Mapping over an iterable with effects)
import { Console, Effect } from "effect"
const result = Effect.forEach(
[1, 2, 3, 4, 5],
(n, index) =>
Console.log(`Currently at index ${index}`).pipe(Effect.as(n * 2))
)
Effect.runPromise(result).then(console.log)
// Output:
// Currently at index 0
// Currently at index 1
// Currently at index 2
// Currently at index 3
// Currently at index 4
// [ 2, 4, 6, 8, 10 ]
Example (Running effects without collecting results)
import { Console, Effect } from "effect"
// Apply effects but discard the results
const result = Effect.forEach(
[1, 2, 3, 4, 5],
(n, index) =>
Console.log(`Currently at index ${index}`).pipe(Effect.as(n * 2)),
{ discard: true }
)
Effect.runPromise(result).then(console.log)
// Output:
// Currently at index 0
// Currently at index 1
// Currently at index 2
// Currently at index 3
// Currently at index 4
// undefined
forEach(const others: Array<AnyNode>others, (node: AnyNodenode) =>
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(const resolveUrl: (
node: AnyNode
) => Effect.Effect<string | undefined, EIn, RIn>
resolveUrl(node: AnyNodenode), (url: string | undefinedurl) => ({
key: stringkey: node: AnyNodenode.Key<unknown, NodeProtocol>.key: stringkey,
kind: ProtocolKind | undefinedkind: node: AnyNodenode.kind: ProtocolKind | undefinedkind,
url: string | undefinedurl,
path: string | undefinedpath: node: AnyNodenode.path: string | undefinedpath,
})),
);
const const entries: (readonly [
string,
PeerServiceOf<S>
])[]
entries = yield* import EffectEffect.const forEach: {
<
B,
E,
R,
S extends Iterable<any>,
Discard extends boolean = false
>(
f: (
a: Arr.ReadonlyArray.Infer<S>,
i: number
) => Effect<B, E, R>,
options?:
| {
readonly concurrency?:
| Concurrency
| undefined
readonly discard?: Discard | undefined
}
| undefined
): (
self: S
) => Effect<
Discard extends false
? Arr.ReadonlyArray.With<S, B>
: void,
E,
R
>
<
B,
E,
R,
S extends Iterable<any>,
Discard extends boolean = false
>(
self: S,
f: (
a: Arr.ReadonlyArray.Infer<S>,
i: number
) => Effect<B, E, R>,
options?:
| {
readonly concurrency?:
| Concurrency
| undefined
readonly discard?: Discard | undefined
}
| undefined
): Effect<
Discard extends false
? Arr.ReadonlyArray.With<S, B>
: void,
E,
R
>
}
Executes an effectful operation for each element in an Iterable.
When to use
Use to traverse an iterable with an effectful function while preserving
element order in the collected results.
Details
The forEach function applies a provided operation to each element in the
iterable, producing a new effect that returns an array of results.
If any effect fails, the iteration stops immediately (short-circuiting), and
the error is propagated.
Concurrency:
The concurrency option controls how many operations are performed
concurrently. By default, the operations are performed sequentially.
Discarding Results:
If the discard option is set to true, the intermediate results are not
collected, and the final result of the operation is void.
Example (Mapping over an iterable with effects)
import { Console, Effect } from "effect"
const result = Effect.forEach(
[1, 2, 3, 4, 5],
(n, index) =>
Console.log(`Currently at index ${index}`).pipe(Effect.as(n * 2))
)
Effect.runPromise(result).then(console.log)
// Output:
// Currently at index 0
// Currently at index 1
// Currently at index 2
// Currently at index 3
// Currently at index 4
// [ 2, 4, 6, 8, 10 ]
Example (Running effects without collecting results)
import { Console, Effect } from "effect"
// Apply effects but discard the results
const result = Effect.forEach(
[1, 2, 3, 4, 5],
(n, index) =>
Console.log(`Currently at index ${index}`).pipe(Effect.as(n * 2)),
{ discard: true }
)
Effect.runPromise(result).then(console.log)
// Output:
// Currently at index 0
// Currently at index 1
// Currently at index 2
// Currently at index 3
// Currently at index 4
// undefined
forEach(
// no dialable address → skip (partial mesh); ipc path counts when url absent
const resolved: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}[]
resolved.Array<{ key: string; kind: ProtocolKind | undefined; url: string | undefined; path: string | undefined; }>.filter(predicate: (value: {
key: string;
kind: ProtocolKind | undefined;
url: string | undefined;
path: string | undefined;
}, index: number, array: {
key: string;
kind: ProtocolKind | undefined;
url: string | undefined;
path: string | undefined;
}[]) => unknown, thisArg?: any): {
key: string;
kind: ProtocolKind | undefined;
url: string | undefined;
path: string | undefined;
}[] (+1 overload)
Returns the elements of an array that meet the condition specified in a callback function.
filter(
(entry: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
entry) =>
entry: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
entry.url: string | undefinedurl !== var undefinedundefined ||
(entry: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
entry.kind: ProtocolKind | undefinedkind === "IpcSocket" && entry: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
entry.path: string | undefinedpath !== var undefinedundefined),
),
(target: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
target) =>
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(
const buildPeerClientAt: <
Self,
S extends Spec
>(
tag: HyperlinkTag<Self, S>,
target: {
readonly key: string
readonly kind?: ProtocolKind
readonly url?: string
readonly path?: string
}
) => Effect.Effect<
PeerServiceOf<S>,
never,
Scope.Scope
>
Dial a peer from a directory row or static Node address — kind-aware (D3).
Prefer url when set (honors options.url overrides +
peerProtocolRef
);
WebSocket kind uses
protocolWebsocket
. Else IpcSocket/path →
protocolIpc
.
buildPeerClientAt(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
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;
}
tag, {
key: stringkey: target: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
target.key: stringkey,
kind?: ProtocolKind | undefinedkind: target: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
target.kind: ProtocolKind | undefinedkind,
...(target: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
target.url: string | undefinedurl !== var undefinedundefined ? { url?: string | undefinedurl: target: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
target.url: stringurl } : {}),
...(target: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
target.path: string | undefinedpath !== var undefinedundefined ? { path?: string | undefinedpath: target: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
target.path: stringpath } : {}),
}),
(client: PeerServiceOf<S>client) => [target: {
key: string
kind: ProtocolKind | undefined
url: string | undefined
path: string | undefined
}
target.key: stringkey, client: PeerServiceOf<S>client] as type const = readonly [string, PeerServiceOf<S>]const,
),
);
// Boundary: each peer client is a full `ServiceOf<S>` — a width-supertype of the leaf
// `PeerServiceOf<S>` the capability exposes — but the mapped types don't reduce under a generic
// `S`, so TS can't see the overlap; the erasure through `unknown` is the honest boundary.
return var Object: ObjectConstructorProvides functionality common to all JavaScript objects.
Object.ObjectConstructor.fromEntries<PeerServiceOf<S>>(entries: Iterable<readonly [PropertyKey, PeerServiceOf<S>]>): {
[k: string]: PeerServiceOf<S>;
} (+1 overload)
Returns an object created by key-value entries for properties and methods
fromEntries(const entries: (readonly [
string,
PeerServiceOf<S>
])[]
entries) as unknown as type Record<K extends keyof any, T> = {
[P in K]: T
}
Construct a type with a set of properties K of type T
Record<string, type PeerServiceOf<S extends Spec> = {
readonly [K in keyof S as S[K] extends {
readonly fleet: true
}
? never
: S[K] extends
| AnyLocalMethod
| AnyDefaultMethod
? never
: K]: S[K] extends {
readonly _tag: "ref"
}
? Effect.Effect<
SuccessOf<AsMethod<S[K]>>,
never,
never
>
: S[K] extends {
readonly kind: MethodKind
}
? ServiceMethod<AsMethod<S[K]>>
: S[K] extends Spec
? PeerServiceOf<S[K]>
: never
}
A peer's service as seen by
peers
— the per-instance ("leaf") wire methods only:
FleetField
s and
LocalMethod
s are excluded, so a fold can't recurse into a peer's
own fleet field. A full
ServiceOf
is assignable to it (width), so real clients fit.
PeerServiceOf<function (type parameter) S in <Self, S extends Spec, EIn = never, RIn = never>(tag: HyperlinkTag<Self, S>, self: AnyNode, options?: {
readonly nodes?: ReadonlyArray<AnyNode>;
readonly url?: (node: AnyNode) => Effect.Effect<string | undefined, EIn, RIn>;
}): Layer.Layer<PeersId<Self> | SelfNodeId<Self>, EIn, RIn>
S>>;
}),
),
const selfNodeLayer: <
Self,
S extends Spec
>(
tag: HyperlinkTag<Self, S>,
self: AnyNode
) => Layer.Layer<SelfNodeId<Self>>
Provide the
selfNode
capability on this node — the node key this instance runs as. Bundled
into
peersLayer
(so a mesh resource gets it for free); use this standalone when a HyperService
keys per node but doesn't gather peers, or alongside
peersFrom
in a test. No transport, no
failure path — just the identity.
selfNodeLayer(tag: HyperlinkTag<Self, S>(parameter) tag: {
description: string | undefined;
key: Identifier;
of: (this: void, self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends …;
context: (self: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { readonly _…;
use: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
useSync: (f: (service: Simplify<{ readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends DefaultMethod<infer F> ? F : S[K] extends { rea…;
Identifier: Identifier;
Service: Shape;
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;
}
tag, self: AnyNodeself),
);