<HSelf>(node: AddressedNode<HSelf>): <T extends PipeableTag>(
tag: T
) => AndNodeResult<T, AddressedNode<HSelf>>
<HSelf>(node: NodeKey<HSelf>): <T extends PipeableTag>(
tag: T
) => AndNodeResult<T, NodeKey<HSelf>>
<T extends PipeableTag>(node: AnyNode): (tag: T) => T
<Self, S extends Spec, HSelf>(
tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>,
node: AddressedNode<HSelf>
): AndNodeResult<
HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>,
AddressedNode<HSelf>
>
<Self, S extends Spec, HSelf>(
tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>,
node: NodeKey<HSelf>
): AndNodeResult<
HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>,
NodeKey<HSelf>
>
<Self, S extends Spec, HSelf>(
tag: NodeBoundTag<Self, S, HSelf>,
node: AnyNode
): NodeBoundTag<Self, S, HSelf>
<Self, S extends Spec>(
tag: HyperlinkTag<Self, S>,
node: AnyNode
): HyperlinkTag<Self, S>Append one Node to a Tag's set (C1). From an empty set this is
nodes([node]) — including the size-1 type bind for client(Tag).
Identity Tags refuse a second Node (IdentityMultiNode).
class Mail extends Hyperlink.Tag<Mail>()("app/Mail", spec).pipe(
Hyperlink.andNode(Worker), // ≡ nodes([Worker]) when starting empty
) {}
class PoolPlus extends PoolBase.pipe(Hyperlink.andNode(StatsNode)) {}Type narrowing to a sole bind is only claimed when the input has no non-empty
Node set. After a populated set, overwrite with nodes([x]) if you need a
fresh typed sole bind for client(Tag).
export const const andNode: {
<HSelf>(node: AddressedNode<HSelf>): <
T extends PipeableTag
>(
tag: T
) => AndNodeResult<T, AddressedNode<HSelf>>
<HSelf>(node: NodeKey<HSelf>): <
T extends PipeableTag
>(
tag: T
) => AndNodeResult<T, NodeKey<HSelf>>
<T extends PipeableTag>(node: AnyNode): (
tag: T
) => T
<Self, S extends Spec, HSelf>(
tag:
| HyperlinkTag<Self, S>
| NodeBoundTag<Self, S, HSelf>,
node: AddressedNode<HSelf>
): AndNodeResult<
| HyperlinkTag<Self, S>
| NodeBoundTag<Self, S, HSelf>,
AddressedNode<HSelf>
>
<Self, S extends Spec, HSelf>(
tag:
| HyperlinkTag<Self, S>
| NodeBoundTag<Self, S, HSelf>,
node: NodeKey<HSelf>
): AndNodeResult<
| HyperlinkTag<Self, S>
| NodeBoundTag<Self, S, HSelf>,
NodeKey<HSelf>
>
<Self, S extends Spec, HSelf>(
tag: NodeBoundTag<Self, S, HSelf>,
node: AnyNode
): NodeBoundTag<Self, S, HSelf>
<Self, S extends Spec>(
tag: HyperlinkTag<Self, S>,
node: AnyNode
): HyperlinkTag<Self, S>
}
Append one
Node
to a Tag's set (C1). From an empty set this is
nodes
([node]) — including the size-1 type bind for
client
(Tag).
Identity Tags refuse a second Node (
IdentityMultiNode
).
class Mail extends Hyperlink.Tag<Mail>()("app/Mail", spec).pipe(
Hyperlink.andNode(Worker), // ≡ nodes([Worker]) when starting empty
) {}
class PoolPlus extends PoolBase.pipe(Hyperlink.andNode(StatsNode)) {}
Type narrowing to a sole bind is only claimed when the input has no non-empty
Node set. After a populated set, overwrite with
nodes
([x]) if you need a
fresh typed sole bind for
client
(Tag).
andNode: {
// data-last — addressed first (AddressedNode ⊆ NodeKey)
<function (type parameter) HSelf in <HSelf>(node: AddressedNode<HSelf>): <T extends PipeableTag>(tag: T) => AndNodeResult<T, AddressedNode<HSelf>>HSelf>(
node: AddressedNode<HSelf>node: type AddressedNode<HSelf> = NodeKey<HSelf> & ({
readonly kind: "IpcSocket";
readonly path: string;
readonly url: string | undefined;
} | {
readonly kind: "Http";
readonly url: string;
readonly path: string | undefined;
} | {
readonly kind: "WebSocket";
readonly url: string;
readonly path: string | undefined;
} | {
readonly kind: "Http" | "WebSocket";
readonly url: string;
readonly path: string | undefined;
})
An
AnyNode
that can derive
connect
with no protocol argument —
kind set, and either a url (Http/WebSocket) or a Unix path (IpcSocket).
AddressedNode<function (type parameter) HSelf in <HSelf>(node: AddressedNode<HSelf>): <T extends PipeableTag>(tag: T) => AndNodeResult<T, AddressedNode<HSelf>>HSelf>,
): <function (type parameter) T in <T extends PipeableTag>(tag: T): AndNodeResult<T, AddressedNode<HSelf>>T extends type PipeableTag = {
readonly [specSym]: FlatSpec
}
PipeableTag>(
tag: T extends PipeableTagtag: function (type parameter) T in <T extends PipeableTag>(tag: T): AndNodeResult<T, AddressedNode<HSelf>>T,
) => type AndNodeResult<T, N> = T extends {
readonly [nodesSym]: readonly [
AnyNode,
...ReadonlyArray<AnyNode>
]
}
? T
: T extends {
readonly [nodeSym]: NodeKey<any>
}
? T
: SoleNodeBind<T, N>
andNode
type result: sole-bind only from an empty/unbound tag. Appending onto a
non-empty set or a narrowed
nodeSym
keeps T (does not claim a fresh sole
bind). Prefer
nodes
([x]) to overwrite when you need a typed sole bind again.
AndNodeResult<function (type parameter) T in <T extends PipeableTag>(tag: T): AndNodeResult<T, AddressedNode<HSelf>>T, type AddressedNode<HSelf> = NodeKey<HSelf> & ({
readonly kind: "IpcSocket";
readonly path: string;
readonly url: string | undefined;
} | {
readonly kind: "Http";
readonly url: string;
readonly path: string | undefined;
} | {
readonly kind: "WebSocket";
readonly url: string;
readonly path: string | undefined;
} | {
readonly kind: "Http" | "WebSocket";
readonly url: string;
readonly path: string | undefined;
})
An
AnyNode
that can derive
connect
with no protocol argument —
kind set, and either a url (Http/WebSocket) or a Unix path (IpcSocket).
AddressedNode<function (type parameter) HSelf in <HSelf>(node: AddressedNode<HSelf>): <T extends PipeableTag>(tag: T) => AndNodeResult<T, AddressedNode<HSelf>>HSelf>>;
<function (type parameter) HSelf in <HSelf>(node: NodeKey<HSelf>): <T extends PipeableTag>(tag: T) => AndNodeResult<T, NodeKey<HSelf>>HSelf>(
node: NodeKey<HSelf>(parameter) node: {
key: string;
Service: {
protocol: Context.Service.Shape<typeof RpcClient.Protocol>;
ping: Effect.Effect<number, NodeUnreachable>;
status: { readonly get: Effect.Effect<NodeStatusSnapshot, NodeUnreachable>; readonly changes: Stream.Stream<NodeStatusSnapshot, NodeUnreachable> };
logs: { readonly stream: Stream.Stream<LogEntry, NodeUnreachable>; readonly query: (options: { readonly limit: number }) => Effect.Effect<ReadonlyArray<LogEntry>, NodeUnreachable> };
};
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;
}
node: type NodeKey<HSelf> = Context.Key<HSelf, NodeProtocol>The Context key of a
Node
(HSelf = its identity): a service whose value is the
transport
NodeProtocol
. Stored on a node-bearing tag under
nodeSym
; read by
Hyperlink.client
to resolve where to connect (its requirement channel).
NodeKey<function (type parameter) HSelf in <HSelf>(node: NodeKey<HSelf>): <T extends PipeableTag>(tag: T) => AndNodeResult<T, NodeKey<HSelf>>HSelf>,
): <function (type parameter) T in <T extends PipeableTag>(tag: T): AndNodeResult<T, NodeKey<HSelf>>T extends type PipeableTag = {
readonly [specSym]: FlatSpec
}
PipeableTag>(tag: T extends PipeableTagtag: function (type parameter) T in <T extends PipeableTag>(tag: T): AndNodeResult<T, NodeKey<HSelf>>T) => type AndNodeResult<T, N> = T extends {
readonly [nodesSym]: readonly [
AnyNode,
...ReadonlyArray<AnyNode>
]
}
? T
: T extends {
readonly [nodeSym]: NodeKey<any>
}
? T
: SoleNodeBind<T, N>
andNode
type result: sole-bind only from an empty/unbound tag. Appending onto a
non-empty set or a narrowed
nodeSym
keeps T (does not claim a fresh sole
bind). Prefer
nodes
([x]) to overwrite when you need a typed sole bind again.
AndNodeResult<function (type parameter) T in <T extends PipeableTag>(tag: T): AndNodeResult<T, NodeKey<HSelf>>T, type NodeKey<HSelf> = Context.Key<HSelf, NodeProtocol>The Context key of a
Node
(HSelf = its identity): a service whose value is the
transport
NodeProtocol
. Stored on a node-bearing tag under
nodeSym
; read by
Hyperlink.client
to resolve where to connect (its requirement channel).
NodeKey<function (type parameter) HSelf in <HSelf>(node: NodeKey<HSelf>): <T extends PipeableTag>(tag: T) => AndNodeResult<T, NodeKey<HSelf>>HSelf>>;
<function (type parameter) T in <T extends PipeableTag>(node: AnyNode): (tag: T) => TT extends type PipeableTag = {
readonly [specSym]: FlatSpec
}
PipeableTag>(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): (tag: T extends PipeableTagtag: function (type parameter) T in <T extends PipeableTag>(node: AnyNode): (tag: T) => TT) => function (type parameter) T in <T extends PipeableTag>(node: AnyNode): (tag: T) => TT;
// data-first
<function (type parameter) Self in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>S extends Spec, function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>HSelf>(
tag: | HyperlinkTag<Self, S>
| NodeBoundTag<Self, S, HSelf>
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, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>S> | interface NodeBoundTag<Self, S extends Spec, HSelf, 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; }>>A
HyperlinkTag
bound to a concrete
Node
— its [nodeSym] narrowed to that node's
NodeKey<HSelf>, which is how
Hyperlink.client
discriminates the node-aware path. Returned
by the node-bearing tag constructors. It's a named type (not an inline & { [nodeSym] }) so a
consumer can export a node-bearing tag without leaking the internal symbol (TS4020).
NodeBoundTag<function (type parameter) Self in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>S, function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>HSelf>,
node: AddressedNode<HSelf>node: type AddressedNode<HSelf> = NodeKey<HSelf> & ({
readonly kind: "IpcSocket";
readonly path: string;
readonly url: string | undefined;
} | {
readonly kind: "Http";
readonly url: string;
readonly path: string | undefined;
} | {
readonly kind: "WebSocket";
readonly url: string;
readonly path: string | undefined;
} | {
readonly kind: "Http" | "WebSocket";
readonly url: string;
readonly path: string | undefined;
})
An
AnyNode
that can derive
connect
with no protocol argument —
kind set, and either a url (Http/WebSocket) or a Unix path (IpcSocket).
AddressedNode<function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>HSelf>,
): type AndNodeResult<T, N> = T extends {
readonly [nodesSym]: readonly [
AnyNode,
...ReadonlyArray<AnyNode>
]
}
? T
: T extends {
readonly [nodeSym]: NodeKey<any>
}
? T
: SoleNodeBind<T, N>
andNode
type result: sole-bind only from an empty/unbound tag. Appending onto a
non-empty set or a narrowed
nodeSym
keeps T (does not claim a fresh sole
bind). Prefer
nodes
([x]) to overwrite when you need a typed sole bind again.
AndNodeResult<
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, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>S> | interface NodeBoundTag<Self, S extends Spec, HSelf, 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; }>>A
HyperlinkTag
bound to a concrete
Node
— its [nodeSym] narrowed to that node's
NodeKey<HSelf>, which is how
Hyperlink.client
discriminates the node-aware path. Returned
by the node-bearing tag constructors. It's a named type (not an inline & { [nodeSym] }) so a
consumer can export a node-bearing tag without leaking the internal symbol (TS4020).
NodeBoundTag<function (type parameter) Self in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>S, function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>HSelf>,
type AddressedNode<HSelf> = NodeKey<HSelf> & ({
readonly kind: "IpcSocket";
readonly path: string;
readonly url: string | undefined;
} | {
readonly kind: "Http";
readonly url: string;
readonly path: string | undefined;
} | {
readonly kind: "WebSocket";
readonly url: string;
readonly path: string | undefined;
} | {
readonly kind: "Http" | "WebSocket";
readonly url: string;
readonly path: string | undefined;
})
An
AnyNode
that can derive
connect
with no protocol argument —
kind set, and either a url (Http/WebSocket) or a Unix path (IpcSocket).
AddressedNode<function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: AddressedNode<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, AddressedNode<HSelf>>HSelf>
>;
<function (type parameter) Self in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>S extends Spec, function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>HSelf>(
tag: | HyperlinkTag<Self, S>
| NodeBoundTag<Self, S, HSelf>
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, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>S> | interface NodeBoundTag<Self, S extends Spec, HSelf, 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; }>>A
HyperlinkTag
bound to a concrete
Node
— its [nodeSym] narrowed to that node's
NodeKey<HSelf>, which is how
Hyperlink.client
discriminates the node-aware path. Returned
by the node-bearing tag constructors. It's a named type (not an inline & { [nodeSym] }) so a
consumer can export a node-bearing tag without leaking the internal symbol (TS4020).
NodeBoundTag<function (type parameter) Self in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>S, function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>HSelf>,
node: NodeKey<HSelf>(parameter) node: {
key: string;
Service: {
protocol: Context.Service.Shape<typeof RpcClient.Protocol>;
ping: Effect.Effect<number, NodeUnreachable>;
status: { readonly get: Effect.Effect<NodeStatusSnapshot, NodeUnreachable>; readonly changes: Stream.Stream<NodeStatusSnapshot, NodeUnreachable> };
logs: { readonly stream: Stream.Stream<LogEntry, NodeUnreachable>; readonly query: (options: { readonly limit: number }) => Effect.Effect<ReadonlyArray<LogEntry>, NodeUnreachable> };
};
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;
}
node: type NodeKey<HSelf> = Context.Key<HSelf, NodeProtocol>The Context key of a
Node
(HSelf = its identity): a service whose value is the
transport
NodeProtocol
. Stored on a node-bearing tag under
nodeSym
; read by
Hyperlink.client
to resolve where to connect (its requirement channel).
NodeKey<function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>HSelf>,
): type AndNodeResult<T, N> = T extends {
readonly [nodesSym]: readonly [
AnyNode,
...ReadonlyArray<AnyNode>
]
}
? T
: T extends {
readonly [nodeSym]: NodeKey<any>
}
? T
: SoleNodeBind<T, N>
andNode
type result: sole-bind only from an empty/unbound tag. Appending onto a
non-empty set or a narrowed
nodeSym
keeps T (does not claim a fresh sole
bind). Prefer
nodes
([x]) to overwrite when you need a typed sole bind again.
AndNodeResult<
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, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>S> | interface NodeBoundTag<Self, S extends Spec, HSelf, 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; }>>A
HyperlinkTag
bound to a concrete
Node
— its [nodeSym] narrowed to that node's
NodeKey<HSelf>, which is how
Hyperlink.client
discriminates the node-aware path. Returned
by the node-bearing tag constructors. It's a named type (not an inline & { [nodeSym] }) so a
consumer can export a node-bearing tag without leaking the internal symbol (TS4020).
NodeBoundTag<function (type parameter) Self in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>S, function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>HSelf>,
type NodeKey<HSelf> = Context.Key<HSelf, NodeProtocol>The Context key of a
Node
(HSelf = its identity): a service whose value is the
transport
NodeProtocol
. Stored on a node-bearing tag under
nodeSym
; read by
Hyperlink.client
to resolve where to connect (its requirement channel).
NodeKey<function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, node: NodeKey<HSelf>): AndNodeResult<HyperlinkTag<Self, S> | NodeBoundTag<Self, S, HSelf>, NodeKey<HSelf>>HSelf>
>;
<function (type parameter) Self in <Self, S extends Spec, HSelf>(tag: NodeBoundTag<Self, S, HSelf>, node: AnyNode): NodeBoundTag<Self, S, HSelf>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: NodeBoundTag<Self, S, HSelf>, node: AnyNode): NodeBoundTag<Self, S, HSelf>S extends Spec, function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: NodeBoundTag<Self, S, HSelf>, node: AnyNode): NodeBoundTag<Self, S, HSelf>HSelf>(
tag: NodeBoundTag<Self, S, HSelf>(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 NodeBoundTag<Self, S extends Spec, HSelf, 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; }>>A
HyperlinkTag
bound to a concrete
Node
— its [nodeSym] narrowed to that node's
NodeKey<HSelf>, which is how
Hyperlink.client
discriminates the node-aware path. Returned
by the node-bearing tag constructors. It's a named type (not an inline & { [nodeSym] }) so a
consumer can export a node-bearing tag without leaking the internal symbol (TS4020).
NodeBoundTag<function (type parameter) Self in <Self, S extends Spec, HSelf>(tag: NodeBoundTag<Self, S, HSelf>, node: AnyNode): NodeBoundTag<Self, S, HSelf>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: NodeBoundTag<Self, S, HSelf>, node: AnyNode): NodeBoundTag<Self, S, HSelf>S, function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: NodeBoundTag<Self, S, HSelf>, node: AnyNode): NodeBoundTag<Self, S, HSelf>HSelf>,
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,
): interface NodeBoundTag<Self, S extends Spec, HSelf, 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; }>>A
HyperlinkTag
bound to a concrete
Node
— its [nodeSym] narrowed to that node's
NodeKey<HSelf>, which is how
Hyperlink.client
discriminates the node-aware path. Returned
by the node-bearing tag constructors. It's a named type (not an inline & { [nodeSym] }) so a
consumer can export a node-bearing tag without leaking the internal symbol (TS4020).
NodeBoundTag<function (type parameter) Self in <Self, S extends Spec, HSelf>(tag: NodeBoundTag<Self, S, HSelf>, node: AnyNode): NodeBoundTag<Self, S, HSelf>Self, function (type parameter) S in <Self, S extends Spec, HSelf>(tag: NodeBoundTag<Self, S, HSelf>, node: AnyNode): NodeBoundTag<Self, S, HSelf>S, function (type parameter) HSelf in <Self, S extends Spec, HSelf>(tag: NodeBoundTag<Self, S, HSelf>, node: AnyNode): NodeBoundTag<Self, S, HSelf>HSelf>;
<function (type parameter) Self in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, node: AnyNode): HyperlinkTag<Self, S>Self, function (type parameter) S in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, node: AnyNode): HyperlinkTag<Self, S>S extends Spec>(
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>(tag: HyperlinkTag<Self, S>, node: AnyNode): HyperlinkTag<Self, S>Self, function (type parameter) S in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, node: AnyNode): HyperlinkTag<Self, S>S>,
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,
): 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>(tag: HyperlinkTag<Self, S>, node: AnyNode): HyperlinkTag<Self, S>Self, function (type parameter) S in <Self, S extends Spec>(tag: HyperlinkTag<Self, S>, node: AnyNode): HyperlinkTag<Self, S>S>;
} = import FnFn.const dual: <(...args: Array<any>) => any, <T extends HyperlinkTag<any, any, any>>(tag: T, node: AnyNode) => T>(arity: 2, body: <T extends HyperlinkTag<any, any, any>>(tag: T, node: AnyNode) => T) => ((...args: Array<any>) => any) & (<T extends HyperlinkTag<any, any, any>>(tag: T, node: AnyNode) => T) (+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(
2,
<function (type parameter) T in <T extends HyperlinkTag<any, any, any>>(tag: T, node: AnyNode): TT extends 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<any, any, any>>(tag: T extends HyperlinkTag<any, any, any>tag: function (type parameter) T in <T extends HyperlinkTag<any, any, any>>(tag: T, node: AnyNode): TT, 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): function (type parameter) T in <T extends HyperlinkTag<any, any, any>>(tag: T, node: AnyNode): TT => {
const const current: ReadonlyArray<AnyNode>current = tag: T extends HyperlinkTag<any, any, any>tag[const nodesSym: typeof nodesSymHolds a tag's distributed set (the fleet).
nodesSym] ?? [];
return const nodes: {
<HSelf>(
nodeSet: readonly [AddressedNode<HSelf>]
): <T extends PipeableTag>(
tag: T
) => SoleNodeBind<T, AddressedNode<HSelf>>
<HSelf>(nodeSet: readonly [NodeKey<HSelf>]): <
T extends PipeableTag
>(
tag: T
) => SoleNodeBind<T, NodeKey<HSelf>>
<T extends PipeableTag>(
nodeSet: ReadonlyArray<AnyNode>
): (tag: T) => T
<Self, S extends Spec, HSelf>(
tag:
| HyperlinkTag<Self, S>
| NodeBoundTag<Self, S, HSelf>,
nodeSet: readonly [AddressedNode<HSelf>]
): SoleNodeBind<
NodeBoundTag<Self, S, HSelf>,
AddressedNode<HSelf>
>
<Self, S extends Spec, HSelf>(
tag:
| HyperlinkTag<Self, S>
| NodeBoundTag<Self, S, HSelf>,
nodeSet: readonly [NodeKey<HSelf>]
): SoleNodeBind<
NodeBoundTag<Self, S, HSelf>,
NodeKey<HSelf>
>
<Self, S extends Spec, HSelf>(
tag: NodeBoundTag<Self, S, HSelf>,
nodeSet: ReadonlyArray<AnyNode>
): NodeBoundTag<Self, S, HSelf>
<Self, S extends Spec>(
tag: HyperlinkTag<Self, S>,
nodeSet: ReadonlyArray<AnyNode>
): HyperlinkTag<Self, S>
}
nodes(tag: T extends HyperlinkTag<any, any, any>tag, [...const current: ReadonlyArray<AnyNode>current, node: AnyNodenode]) as function (type parameter) T in <T extends HyperlinkTag<any, any, any>>(tag: T, node: AnyNode): TT;
},
);