<Self, RIn>(
node: NodeKey<Self>,
protocol: Layer.Layer<RpcClient.Protocol, never, RIn>
): Layer.Layer<Self, never, RIn>
<RIn>(protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): <Self>(
node: NodeKey<Self>
) => Layer.Layer<Self, never, RIn>
<Self>(node: AddressedNode<Self>): Layer.Layer<Self>Wire a Node's transport — the transport-agnostic primitive, dual:
MyNode.pipe(Node.connect) // derive the transport from the node's declared kind + url
MyNode.pipe(Node.connect(protocol)) // data-last: an explicit RpcClient.Protocol
Node.connect(MyNode) // data-first, derived (needs an AddressedNode)
Node.connect(MyNode, protocol) // data-first, explicitThe derived forms read the node's ProtocolKind — so a node that declares kind: "WebSocket"
dials WS and one that declares "Http" dials http; picking the wrong transport isn't
expressible. MyNode.pipe(Node.connect) only type-checks for an AddressedNode (a node
with both url/path and kind); a bare node is a compile error pointing you to declare its
address or pass a protocol.
Derived connect Layers are WeakMap-memoized per Node class so multiple
Hyperlink.client(Tag, MyNode) call sites share one MemoMap transport.
export const const connect: {
<Self, RIn>(
node: NodeKey<Self>,
protocol: Layer.Layer<
RpcClient.Protocol,
never,
RIn
>
): Layer.Layer<Self, never, RIn>
<RIn>(
protocol: Layer.Layer<
RpcClient.Protocol,
never,
RIn
>
): <Self>(
node: NodeKey<Self>
) => Layer.Layer<Self, never, RIn>
<Self>(
node: AddressedNode<Self>
): Layer.Layer<Self>
}
Wire a
Node
's transport — the transport-agnostic primitive, dual:
MyNode.pipe(Node.connect) // derive the transport from the node's declared kind + url
MyNode.pipe(Node.connect(protocol)) // data-last: an explicit RpcClient.Protocol
Node.connect(MyNode) // data-first, derived (needs an AddressedNode)
Node.connect(MyNode, protocol) // data-first, explicit
The derived forms read the node's
ProtocolKind
— so a node that declares kind: "WebSocket"
dials WS and one that declares "Http" dials http; picking the wrong transport isn't
expressible. MyNode.pipe(Node.connect) only type-checks for an
AddressedNode
(a node
with both url/path and kind); a bare node is a compile error pointing you to declare its
address or pass a protocol.
Derived connect Layers are WeakMap-memoized per Node class so multiple
Hyperlink.client(Tag, MyNode) call sites share one MemoMap transport.
connect: {
// Order matters: TS selects the LAST matching overload when the function is used as a bare value
// (`node.pipe(connect)`), so the node→Layer form is last to make the pipe form resolve to it; direct
// calls still match top-down by arg count / shape.
<function (type parameter) Self in <Self, RIn>(node: NodeKey<Self>, protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): Layer.Layer<Self, never, RIn>Self, function (type parameter) RIn in <Self, RIn>(node: NodeKey<Self>, protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): Layer.Layer<Self, never, RIn>RIn>(
node: NodeKey<Self>node: import NodeKeyNodeKey<function (type parameter) Self in <Self, RIn>(node: NodeKey<Self>, protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): Layer.Layer<Self, never, RIn>Self>,
protocol: Layer.Layer<
RpcClient.Protocol,
never,
RIn
>
(parameter) protocol: {
build: (memoMap: Layer.MemoMap, scope: Scope) => Effect.Effect<Context.Context<RpcClient.Protocol>, never, RIn>;
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; <…;
}
protocol: 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<import RpcClientRpcClient.class Protocolclass Protocol {
key: Identifier;
Service: {
run: (clientId: number, f: (data: FromServerEncoded) => Effect.Effect<void>) => Effect.Effect<never>;
send: (clientId: number, request: FromClientEncoded, transferables?: ReadonlyArray<globalThis.Transferable>) => Effect.Effect<void, RpcClientError>;
supportsAck: boolean;
supportsTransferables: boolean;
};
}
Defines the service interface for an RPC client transport, responsible for running the
receive loop and sending encoded client messages.
When to use
Use to provide the transport boundary for RPC clients over HTTP, WebSocket,
workers, sockets, or custom protocols.
Protocol, never, function (type parameter) RIn in <Self, RIn>(node: NodeKey<Self>, protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): Layer.Layer<Self, never, 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<function (type parameter) Self in <Self, RIn>(node: NodeKey<Self>, protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): Layer.Layer<Self, never, RIn>Self, never, function (type parameter) RIn in <Self, RIn>(node: NodeKey<Self>, protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): Layer.Layer<Self, never, RIn>RIn>;
<function (type parameter) RIn in <RIn>(protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): <Self>(node: NodeKey<Self>) => Layer.Layer<Self, never, RIn>RIn>(
protocol: Layer.Layer<
RpcClient.Protocol,
never,
RIn
>
(parameter) protocol: {
build: (memoMap: Layer.MemoMap, scope: Scope) => Effect.Effect<Context.Context<RpcClient.Protocol>, never, RIn>;
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; <…;
}
protocol: 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<import RpcClientRpcClient.class Protocolclass Protocol {
key: Identifier;
Service: {
run: (clientId: number, f: (data: FromServerEncoded) => Effect.Effect<void>) => Effect.Effect<never>;
send: (clientId: number, request: FromClientEncoded, transferables?: ReadonlyArray<globalThis.Transferable>) => Effect.Effect<void, RpcClientError>;
supportsAck: boolean;
supportsTransferables: boolean;
};
}
Defines the service interface for an RPC client transport, responsible for running the
receive loop and sending encoded client messages.
When to use
Use to provide the transport boundary for RPC clients over HTTP, WebSocket,
workers, sockets, or custom protocols.
Protocol, never, function (type parameter) RIn in <RIn>(protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): <Self>(node: NodeKey<Self>) => Layer.Layer<Self, never, RIn>RIn>,
): <function (type parameter) Self in <Self>(node: NodeKey<Self>): Layer.Layer<Self, never, RIn>Self>(node: NodeKey<Self>node: import NodeKeyNodeKey<function (type parameter) Self in <Self>(node: NodeKey<Self>): Layer.Layer<Self, never, RIn>Self>) => 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<function (type parameter) Self in <Self>(node: NodeKey<Self>): Layer.Layer<Self, never, RIn>Self, never, function (type parameter) RIn in <RIn>(protocol: Layer.Layer<RpcClient.Protocol, never, RIn>): <Self>(node: NodeKey<Self>) => Layer.Layer<Self, never, RIn>RIn>;
/** Derived transport — only {@link AddressedNode}; error channel is empty (address proven). */
<function (type parameter) Self in <Self>(node: AddressedNode<Self>): Layer.Layer<Self>Self>(node: AddressedNode<Self>node: import AddressedNodeAddressedNode<function (type parameter) Self in <Self>(node: AddressedNode<Self>): Layer.Layer<Self>Self>): 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<function (type parameter) Self in <Self>(node: AddressedNode<Self>): Layer.Layer<Self>Self>;
} = import FnFn.const dual: <(...args: Array<any>) => any, (node: AnyNode, protocol?: Layer.Layer<RpcClient.Protocol, never, never>) => Layer.Layer<never, UnaddressedNode | InvalidHttpTarget, never>>(isDataFirst: (args: IArguments) => boolean, body: (node: AnyNode, protocol?: Layer.Layer<RpcClient.Protocol, never, never>) => Layer.Layer<never, UnaddressedNode | InvalidHttpTarget, never>) => ((...args: Array<any>) => any) & ((node: AnyNode, protocol?: Layer.Layer<RpcClient.Protocol, never, never>) => Layer.Layer<never, UnaddressedNode | InvalidHttpTarget, never>) (+1 overload)Creates a function that can be called in data-first style or data-last
(pipe-friendly) style.
When to use
Use to expose one implementation through both direct and pipe-friendly
call styles.
Details
Pass either the arity of the uncurried function or a predicate that decides
whether the current call is data-first. Arity is the common case. Use a
predicate when optional arguments make arity ambiguous.
Example (Selecting data-first or data-last style by arity)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(2, (self, that) => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Defining overloads with call signatures)
import { Function, pipe } from "effect"
const sum: {
(that: number): (self: number) => number
(self: number, that: number): number
} = Function.dual(2, (self: number, that: number): number => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Selecting data-first or data-last style with a predicate)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(
(args) => args.length === 2,
(self, that) => self + that
)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
dual(
// data-first when there are two args, or when the single arg is a node (not a protocol layer).
(args: IArgumentsargs: IArguments) => args: IArgumentsargs.IArguments.length: numberlength >= 2 || !import LayerLayer.const isLayer: (
u: unknown
) => u is Layer.Layer<unknown, unknown, unknown>
Returns true if the specified value is a Layer, false otherwise.
Example (Checking whether a value is a layer)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
const dbLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed("result"))
})
const notALayer = { someProperty: "value" }
console.log(Layer.isLayer(dbLayer)) // true
console.log(Layer.isLayer(notALayer)) // false
isLayer(args: IArgumentsargs[0]),
(
node: AnyNodenode: import AnyNodeAnyNode,
protocol: | Layer.Layer<RpcClient.Protocol, never, never>
| undefined
protocol?: 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<import RpcClientRpcClient.class Protocolclass Protocol {
key: Identifier;
Service: {
run: (clientId: number, f: (data: FromServerEncoded) => Effect.Effect<void>) => Effect.Effect<never>;
send: (clientId: number, request: FromClientEncoded, transferables?: ReadonlyArray<globalThis.Transferable>) => Effect.Effect<void, RpcClientError>;
supportsAck: boolean;
supportsTransferables: boolean;
};
}
Defines the service interface for an RPC client transport, responsible for running the
receive loop and sending encoded client messages.
When to use
Use to provide the transport boundary for RPC clients over HTTP, WebSocket,
workers, sockets, or custom protocols.
Protocol, never, never>,
): 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<never, import UnaddressedNodeUnaddressedNode | import InvalidHttpTargetInvalidHttpTarget, never> => {
if (protocol: | Layer.Layer<RpcClient.Protocol, never, never>
| undefined
protocol !== var undefinedundefined) {
return import connectLayerconnectLayer(node: AnyNodenode, protocol: Layer.Layer<
RpcClient.Protocol,
never,
never
>
(parameter) protocol: {
build: (memoMap: Layer.MemoMap, scope: Scope) => Effect.Effect<Context.Context<RpcClient.Protocol>, never, never>;
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; <…;
}
protocol);
}
// Addressed path — canonical memoized Layer (same object Hyperlink.client auto-connect uses).
if (
(node: AnyNodenode.kind === "IpcSocket" && typeof node: AnyNodenode.path === "string") ||
((node: AnyNodenode.kind === "Http" || node: AnyNodenode.kind === "WebSocket") &&
typeof node: AnyNodenode.url === "string")
) {
return import connectAddressedconnectAddressed(node: AnyNodenode as import AddressedNodeAddressedNode<unknown>);
}
return import connectLayerconnectLayer(node: AnyNodenode, import protocolForNodeprotocolForNode(node: AnyNodenode));
},
);