(node: AnyNode, options?: VerifyConnectionOptions): Effect.Effect<
void,
NodeUnreachable | UnaddressedNode
>
(node: AnyNode, options: VerifyConnectionDeepOptions): Effect.Effect<
void,
ClientVerifyError
>Verify a node is reachable, eagerly — a fail-fast startup check for a remote Node.
Default: one bounded transport probe (tier 1) against the endpoint connect would
dial (selectEndpoint, or every endpoint with { all: true }). Fails
NodeUnreachable if nothing answers.
With { deep: true }, escalates after transport OK: dials the node's auto-served status
RPC over that endpoint. Transport up but RPC silent → ProtocolUnanswered; optional
serviceKey key → ServiceNotServed / ServiceNotReady; optional
contractHash → ContractMismatch (F4).
yield* Hyperlink.verifyConnection(Droplet); // tier 1
yield* Hyperlink.verifyConnection(Droplet, { timeout: "1 second" });
yield* Hyperlink.verifyConnection(Droplet, { deep: true }); // + node status RPC
yield* Hyperlink.verifyConnection(Droplet, {
deep: true,
serviceKey: Emails.key,
contractHash: Hyperlink.contractHash(Emails),
});
yield* Hyperlink.verifyConnection(Droplet, { all: true }); // every endpointComplements connect: connect prevents mis-wiring the client transport;
verifyConnection catches a peer that isn't there (or, with deep, isn't speaking RPC /
isn't serving the HyperService you need / has a stale contract).
export function function verifyConnection(node: AnyNode, options?: VerifyConnectionOptions): Effect.Effect<void, NodeUnreachable | UnaddressedNode> (+1 overload)Verify a node is reachable, eagerly — a fail-fast startup check for a remote
Node
.
Default: one bounded transport probe (tier 1) against the endpoint
connect
would
dial (selectEndpoint, or every endpoint with { all: true }). Fails
NodeUnreachable
if nothing answers.
With { deep: true }, escalates after transport OK: dials the node's auto-served status
RPC over that endpoint. Transport up but RPC silent →
ProtocolUnanswered
; optional
serviceKey key →
ServiceNotServed
/
ServiceNotReady
; optional
contractHash →
ContractMismatch
(F4).
yield* Hyperlink.verifyConnection(Droplet); // tier 1
yield* Hyperlink.verifyConnection(Droplet, { timeout: "1 second" });
yield* Hyperlink.verifyConnection(Droplet, { deep: true }); // + node status RPC
yield* Hyperlink.verifyConnection(Droplet, {
deep: true,
serviceKey: Emails.key,
contractHash: Hyperlink.contractHash(Emails),
});
yield* Hyperlink.verifyConnection(Droplet, { all: true }); // every endpoint
Complements
connect
: connect prevents mis-wiring the client transport;
verifyConnection catches a peer that isn't there (or, with deep, isn't speaking RPC /
isn't serving the HyperService you need / has a stale contract).
verifyConnection(
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,
options: VerifyConnectionOptionsoptions?: type VerifyConnectionOptions = {
readonly timeout?: Duration.Input
readonly url?: string
readonly path?: string
readonly all?: boolean
}
Options for the cheap (tier-1)
verifyConnection
probe.
VerifyConnectionOptions,
): import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<void, class NodeUnreachableclass NodeUnreachable {
message: string;
name: string;
stack: string;
cause: unknown;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
_tag: Tag;
node: string;
url: string;
}
A remote
Node
that didn't answer at its declared address — down, wrong port/url, or (for a
socket node) a server not speaking the socket protocol. Surfaced eagerly by
verifyConnection
so a client fails fast at startup instead of hanging or erroring opaquely at the first call.
NodeUnreachable | class UnaddressedNodeclass UnaddressedNode {
message: string;
name: string;
stack: string;
cause: unknown;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
_tag: Tag;
node: string;
}
Deriving a transport from a node that never declared one — a bare Node.Tag()("x") has no
address/kind, so connect / listen can't know how to reach it. Surfaces on the Layer / Effect
error channel (never a sync throw).
UnaddressedNode>;
export function function verifyConnection(node: AnyNode, options: VerifyConnectionDeepOptions): Effect.Effect<void, ClientVerifyError> (+1 overload)Verify a node is reachable, eagerly — a fail-fast startup check for a remote
Node
.
Default: one bounded transport probe (tier 1) against the endpoint
connect
would
dial (selectEndpoint, or every endpoint with { all: true }). Fails
NodeUnreachable
if nothing answers.
With { deep: true }, escalates after transport OK: dials the node's auto-served status
RPC over that endpoint. Transport up but RPC silent →
ProtocolUnanswered
; optional
serviceKey key →
ServiceNotServed
/
ServiceNotReady
; optional
contractHash →
ContractMismatch
(F4).
yield* Hyperlink.verifyConnection(Droplet); // tier 1
yield* Hyperlink.verifyConnection(Droplet, { timeout: "1 second" });
yield* Hyperlink.verifyConnection(Droplet, { deep: true }); // + node status RPC
yield* Hyperlink.verifyConnection(Droplet, {
deep: true,
serviceKey: Emails.key,
contractHash: Hyperlink.contractHash(Emails),
});
yield* Hyperlink.verifyConnection(Droplet, { all: true }); // every endpoint
Complements
connect
: connect prevents mis-wiring the client transport;
verifyConnection catches a peer that isn't there (or, with deep, isn't speaking RPC /
isn't serving the HyperService you need / has a stale contract).
verifyConnection(
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,
options: VerifyConnectionDeepOptionsoptions: type VerifyConnectionDeepOptions =
VerifyConnectionOptions & {
readonly deep: true
readonly serviceKey?: string
readonly contractHash?: string
}
Options for deep (tier-2/3/4)
verifyConnection
— RPC + optional resource / F4 hash.
VerifyConnectionDeepOptions,
): import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<void, type ClientVerifyError =
| NodeUnreachable
| UnaddressedNode
| ProtocolUnanswered
| ServiceNotServed
| ServiceNotReady
| ContractMismatch
Errors default-on / deep client verify may surface on addressed client Layers.
ClientVerifyError>;
export function function verifyConnection(node: AnyNode, options?: VerifyConnectionOptions): Effect.Effect<void, NodeUnreachable | UnaddressedNode> (+1 overload)Verify a node is reachable, eagerly — a fail-fast startup check for a remote
Node
.
Default: one bounded transport probe (tier 1) against the endpoint
connect
would
dial (selectEndpoint, or every endpoint with { all: true }). Fails
NodeUnreachable
if nothing answers.
With { deep: true }, escalates after transport OK: dials the node's auto-served status
RPC over that endpoint. Transport up but RPC silent →
ProtocolUnanswered
; optional
serviceKey key →
ServiceNotServed
/
ServiceNotReady
; optional
contractHash →
ContractMismatch
(F4).
yield* Hyperlink.verifyConnection(Droplet); // tier 1
yield* Hyperlink.verifyConnection(Droplet, { timeout: "1 second" });
yield* Hyperlink.verifyConnection(Droplet, { deep: true }); // + node status RPC
yield* Hyperlink.verifyConnection(Droplet, {
deep: true,
serviceKey: Emails.key,
contractHash: Hyperlink.contractHash(Emails),
});
yield* Hyperlink.verifyConnection(Droplet, { all: true }); // every endpoint
Complements
connect
: connect prevents mis-wiring the client transport;
verifyConnection catches a peer that isn't there (or, with deep, isn't speaking RPC /
isn't serving the HyperService you need / has a stale contract).
verifyConnection(
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,
options: VerifyConnectionOptions & {
readonly deep?: boolean
readonly serviceKey?: string
readonly contractHash?: string
}
options?: type VerifyConnectionOptions = {
readonly timeout?: Duration.Input
readonly url?: string
readonly path?: string
readonly all?: boolean
}
Options for the cheap (tier-1)
verifyConnection
probe.
VerifyConnectionOptions & {
readonly deep?: boolean | undefineddeep?: boolean;
readonly serviceKey?: string | undefinedserviceKey?: string;
readonly contractHash?: string | undefinedcontractHash?: string;
},
): import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<void, type ClientVerifyError =
| NodeUnreachable
| UnaddressedNode
| ProtocolUnanswered
| ServiceNotServed
| ServiceNotReady
| ContractMismatch
Errors default-on / deep client verify may surface on addressed client Layers.
ClientVerifyError> {
const const endpoints:
| UnaddressedNode
| readonly VerifyEndpoint[]
endpoints = const verifyEndpointsOf: (
node: AnyNode,
options?: {
readonly url?: string
readonly path?: string
readonly all?: boolean
}
) =>
| ReadonlyArray<VerifyEndpoint>
| UnaddressedNode
Endpoints
verifyConnection
probes. Overrides (url/path) win as a single synthetic
endpoint; { all: true } walks every declared transport; otherwise the same
selectEndpoint
pick
connect
would dial.
verifyEndpointsOf(node: AnyNodenode, options: VerifyConnectionOptions & {
readonly deep?: boolean
readonly serviceKey?: string
readonly contractHash?: string
}
options);
if (const endpoints:
| UnaddressedNode
| readonly VerifyEndpoint[]
endpoints instanceof class UnaddressedNodeDeriving a transport from a node that never declared one — a bare Node.Tag()("x") has no
address/kind, so connect / listen can't know how to reach it. Surfaces on the Layer / Effect
error channel (never a sync throw).
UnaddressedNode) {
return import EffectEffect.const fail: <E>(
error: E
) => Effect<never, E>
Creates an Effect that represents a recoverable error.
When to use
Use to explicitly signal a recoverable error in an Effect.
Details
The error keeps propagating unless it is handled. You can handle tagged
errors with functions like
catchTag
or
catchTags
.
Example (Creating a failed effect)
import { Data, Effect } from "effect"
class OperationFailedError extends Data.TaggedError("OperationFailedError")<{}> {}
// ┌─── Effect<never, OperationFailedError, never>
// ▼
const failure = Effect.fail(
new OperationFailedError()
)
fail(const endpoints: UnaddressedNodeconst endpoints: {
message: string;
name: string;
stack: string;
cause: unknown;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
_tag: Tag;
node: string;
}
endpoints);
}
const const timeout: Duration.Inputtimeout = options: VerifyConnectionOptions & {
readonly deep?: boolean
readonly serviceKey?: string
readonly contractHash?: string
}
options?.timeout?: Duration.Inputtimeout ?? "3 seconds";
const const deep: booleandeep = options: VerifyConnectionOptions & {
readonly deep?: boolean
readonly serviceKey?: string
readonly contractHash?: string
}
options?.deep?: boolean | undefineddeep === true;
const const serviceKey: string | undefinedserviceKey = options: VerifyConnectionOptions & {
readonly deep?: boolean
readonly serviceKey?: string
readonly contractHash?: string
}
options?.serviceKey?: string | undefinedserviceKey;
const const expectedHash: string | undefinedexpectedHash = options: VerifyConnectionOptions & {
readonly deep?: boolean
readonly serviceKey?: string
readonly contractHash?: string
}
options?.contractHash?: string | undefinedcontractHash;
return 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 endpoints: readonly VerifyEndpoint[]endpoints,
(ep: VerifyEndpoint(parameter) ep: {
kind: ProtocolKind;
url: string;
path: string;
}
ep) =>
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* () {
yield* const probeEndpointReachable: (
nodeKey: string,
ep: VerifyEndpoint,
timeout: Duration.Input
) => Effect.Effect<
void,
NodeUnreachable | UnaddressedNode
>
Tier-1 transport reachability for one endpoint.
probeEndpointReachable(node: AnyNodenode.Key<unknown, NodeProtocol>.key: stringkey, ep: VerifyEndpoint(parameter) ep: {
kind: ProtocolKind;
url: string;
path: string;
}
ep, const timeout: Duration.Inputtimeout);
if (const deep: booleandeep) {
yield* const probeEndpointDeep: (
nodeKey: string,
ep: VerifyEndpoint,
timeout: Duration.Input,
serviceKey: string | undefined,
expectedHash: string | undefined
) => Effect.Effect<
void,
| ProtocolUnanswered
| ServiceNotServed
| ServiceNotReady
| ContractMismatch
| UnaddressedNode
>
Tier-2/3/4: after transport is up, dial the reserved node-status RPC over the endpoint's
protocol. Failures classify as
ProtocolUnanswered
; optional serviceKey checks
served-key / readiness; optional contractHash compares the F4 wire fingerprint.
Dynamic-imports the status tag so Hyperlink ⇄ nodeStatus stays acyclic.
probeEndpointDeep(node: AnyNodenode.Key<unknown, NodeProtocol>.key: stringkey, ep: VerifyEndpoint(parameter) ep: {
kind: ProtocolKind;
url: string;
path: string;
}
ep, const timeout: Duration.Inputtimeout, const serviceKey: string | undefinedserviceKey, const expectedHash: string | undefinedexpectedHash);
}
}),
{ discard?: true | undefineddiscard: true },
);
}