Hyperlinkv0.8.0-beta.28

Node

Node.connectconstsrc/internal/node.ts:216
<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.

connectNodeProtocolKindAddressedNode
export const 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.
  <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>;
  /** Derived transport — only {@link AddressedNode}; error channel is empty (address proven). */
  <Self>(node: AddressedNode<Self>): Layer.Layer<Self>;
} = Fn.dual(
  // data-first when there are two args, or when the single arg is a node (not a protocol layer).
  (args: IArguments) => args.length >= 2 || !Layer.isLayer(args[0]),
  (
    node: AnyNode,
    protocol?: Layer.Layer<RpcClient.Protocol, never, never>,
  ): Layer.Layer<never, UnaddressedNode | InvalidHttpTarget, never> => {
    if (protocol !== undefined) {
      return connectLayer(node, protocol);
    }
    // Addressed path — canonical memoized Layer (same object Hyperlink.client auto-connect uses).
    if (
      (node.kind === "IpcSocket" && typeof node.path === "string") ||
      ((node.kind === "Http" || node.kind === "WebSocket") &&
        typeof node.url === "string")
    ) {
      return connectAddressed(node as AddressedNode<unknown>);
    }
    return connectLayer(node, protocolForNode(node));
  },
);