<const T extends ShorthandTarget>(transports: T): <
Self,
ROut,
K extends ProtocolKind
>(
node: NodeTagClass<
Self,
ROut,
{
readonly kind: K
readonly url?: string
readonly path?: string
readonly endpoints?: Endpoints
}
>
) => NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>Add transports to a node — piped on to derive a same-identity handle that speaks more
protocols: class DropletWs extends Droplet.pipe(Node.withProtocol({ ws: "/rpc" })) {}. Takes the
same { http, ws, ipc } record as the declaration; keeps the node's key and served resources,
merges the transports into its endpoints, and widens its ProtocolKind set in the type.
Accepts single- or multi-protocol nodes alike.
export const const withProtocol: <
T extends ShorthandTarget
>(
transports: T
) => <Self, ROut, K extends ProtocolKind>(
node: NodeTagClass<
Self,
ROut,
{
readonly kind: K
readonly url?: string
readonly path?: string
readonly endpoints?: Endpoints
}
>
) => NodeTagClass<
Self,
ROut,
MultiAddress<K | KindsOf<T>>
>
Add transports to a node — piped on to derive a same-identity handle that speaks more
protocols: class DropletWs extends Droplet.pipe(Node.withProtocol({ ws: "/rpc" })) {}. Takes the
same { http, ws, ipc } record as the declaration; keeps the node's key and served resources,
merges the transports into its endpoints, and widens its
ProtocolKind
set in the type.
Accepts single- or multi-protocol nodes alike.
withProtocol =
<const function (type parameter) T in <const T extends ShorthandTarget>(transports: T): <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>) => NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
T extends type ShorthandTarget = {
readonly http?: string
readonly ws?: string
readonly ipc?: string
readonly onConflict?: OnConflict
readonly url?: never
readonly path?: never
readonly kind?: never
}
The { http, ws, ipc } multi-protocol shorthand target. url/path/kind are pinned to never
so it stays disjoint from the single-address { url, kind } / { path } forms.
ShorthandTarget>(transports: const T extends ShorthandTargettransports: function (type parameter) T in <const T extends ShorthandTarget>(transports: T): <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>) => NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
T) =>
<function (type parameter) Self in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
Self, function (type parameter) ROut in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
ROut, function (type parameter) K in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
K extends 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>(
node: NodeTagClass<
Self,
ROut,
{
readonly kind: K
readonly url?: string
readonly path?: string
readonly endpoints?: Endpoints
}
>
node: type NodeTagClass<Self, ROut, Address> =
Context.ServiceClass<
Self,
string,
NodeProtocol
> &
Address & {
readonly logs: unknown
readonly onConflict: OnConflict
readonly [catalogSym]?: ROut
}
Constructable
Tag
result — Context.ServiceClass plus address fields.
NodeTagClass<
function (type parameter) Self in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
Self,
function (type parameter) ROut in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
ROut,
{
readonly kind: K extends ProtocolKindkind: function (type parameter) K in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
K;
readonly url?: string | undefinedurl?: string;
readonly path?: string | undefinedpath?: string;
readonly endpoints?: Endpoints | undefinedendpoints?: Endpoints;
}
>,
): type NodeTagClass<Self, ROut, Address> =
Context.ServiceClass<
Self,
string,
NodeProtocol
> &
Address & {
readonly logs: unknown
readonly onConflict: OnConflict
readonly [catalogSym]?: ROut
}
Constructable
Tag
result — Context.ServiceClass plus address fields.
NodeTagClass<function (type parameter) Self in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
Self, function (type parameter) ROut in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
ROut, type MultiAddress<
Kinds extends ProtocolKind
> = {
readonly url: string | undefined
readonly path: string | undefined
readonly kind: Kinds
readonly endpoints: Endpoints
}
A multi-protocol node's fields — its transport endpoints set, kind the union of the set
(the primary at runtime), plus the primary url/path. Single object type (not a union) so
class extends Tag()(…) stays constructable.
MultiAddress<function (type parameter) K in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
K | type KindsOf<T> =
| (T extends {
readonly http: string
}
? "Http"
: never)
| (T extends {
readonly ws: string
}
? "WebSocket"
: never)
| (T extends {
readonly ipc: string
}
? "IpcSocket"
: never)
The
ProtocolKind
s present in a { http, ws, ipc } shorthand target.
KindsOf<function (type parameter) T in <const T extends ShorthandTarget>(transports: T): <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>) => NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
T>>> => {
const const add: Endpointsconst add: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
add: Endpoints = {
...(transports: const T extends ShorthandTargettransports.http?: string | undefinedhttp !== var undefinedundefined ? { Endpoints.Http?: {
readonly url: string;
} | undefined
Http: { url: stringurl: transports: const T extends ShorthandTargettransports.http?: stringhttp } } : {}),
...(transports: const T extends ShorthandTargettransports.ws?: string | undefinedws !== var undefinedundefined ? { Endpoints.WebSocket?: {
readonly url: string;
} | undefined
WebSocket: { url: stringurl: transports: const T extends ShorthandTargettransports.ws?: stringws } } : {}),
...(transports: const T extends ShorthandTargettransports.ipc?: string | undefinedipc !== var undefinedundefined
? { Endpoints.IpcSocket?: {
readonly path: string;
} | undefined
IpcSocket: { path: stringpath: transports: const T extends ShorthandTargettransports.ipc?: stringipc } }
: {}),
};
const const endpoints: Endpointsconst endpoints: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
endpoints: Endpoints = { ...node: NodeTagClass<
Self,
ROut,
{
readonly kind: K
readonly url?: string
readonly path?: string
readonly endpoints?: Endpoints
}
>
node.endpoints?: Endpoints | undefinedendpoints, ...const add: Endpointsconst add: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
add };
// Keep the base node's primary if it had one, else the first of the merged set (http > ws > ipc).
const const kind: ProtocolKind | undefinedkind: 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 | undefined =
node: NodeTagClass<
Self,
ROut,
{
readonly kind: K
readonly url?: string
readonly path?: string
readonly endpoints?: Endpoints
}
>
node.kind: ProtocolKindkind ??
(const endpoints: Endpointsconst endpoints: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
endpoints.Endpoints.Http?: {
readonly url: string;
} | undefined
Http !== var undefinedundefined
? "Http"
: const endpoints: Endpointsconst endpoints: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
endpoints.Endpoints.WebSocket?: {
readonly url: string;
} | undefined
WebSocket !== var undefinedundefined
? "WebSocket"
: const endpoints: Endpointsconst endpoints: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
endpoints.Endpoints.IpcSocket?: {
readonly path: string;
} | undefined
IpcSocket !== var undefinedundefined
? "IpcSocket"
: var undefinedundefined);
return const assembleNode: <Self, ROut, Addr>(
key: string,
fields: {
readonly url: string | undefined
readonly path: string | undefined
readonly kind: ProtocolKind | undefined
readonly endpoints: Endpoints
readonly onConflict: OnConflict
readonly httpPort?: number
readonly invalidTarget?: InvalidHttpTarget
}
) => NodeTagClass<Self, ROut, Addr>
Assemble a node tag value from resolved address fields — a Context.Service class stamped with the
transport fields, the logs accessor, and the catalog brand. The single place the runtime →
NodeTagClass impedance is bridged: a node's runtime kind is always looser (ProtocolKind |
undefined) than any precise address form Addr, so exactly one construction cast lives here and
every caller (
Tag
,
withProtocol
) stays cast-free.
assembleNode<function (type parameter) Self in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
Self, function (type parameter) ROut in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
ROut, type MultiAddress<
Kinds extends ProtocolKind
> = {
readonly url: string | undefined
readonly path: string | undefined
readonly kind: Kinds
readonly endpoints: Endpoints
}
A multi-protocol node's fields — its transport endpoints set, kind the union of the set
(the primary at runtime), plus the primary url/path. Single object type (not a union) so
class extends Tag()(…) stays constructable.
MultiAddress<function (type parameter) K in <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>): NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
K | type KindsOf<T> =
| (T extends {
readonly http: string
}
? "Http"
: never)
| (T extends {
readonly ws: string
}
? "WebSocket"
: never)
| (T extends {
readonly ipc: string
}
? "IpcSocket"
: never)
The
ProtocolKind
s present in a { http, ws, ipc } shorthand target.
KindsOf<function (type parameter) T in <const T extends ShorthandTarget>(transports: T): <Self, ROut, K extends ProtocolKind>(node: NodeTagClass<Self, ROut, {
readonly kind: K;
readonly url?: string;
readonly path?: string;
readonly endpoints?: Endpoints;
}>) => NodeTagClass<Self, ROut, MultiAddress<K | KindsOf<T>>>
T>>>(node: NodeTagClass<
Self,
ROut,
{
readonly kind: K
readonly url?: string
readonly path?: string
readonly endpoints?: Endpoints
}
>
node.ServiceClass<Self, string, NodeProtocol>.key: stringkey, {
url: string | undefinedurl: node: NodeTagClass<
Self,
ROut,
{
readonly kind: K
readonly url?: string
readonly path?: string
readonly endpoints?: Endpoints
}
>
node.url?: string | undefinedurl ?? const endpoints: Endpointsconst endpoints: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
endpoints.Endpoints.Http?: {
readonly url: string;
} | undefined
Http?.url: string | undefinedurl ?? const endpoints: Endpointsconst endpoints: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
endpoints.Endpoints.WebSocket?: {
readonly url: string;
} | undefined
WebSocket?.url: string | undefinedurl,
path: string | undefinedpath: node: NodeTagClass<
Self,
ROut,
{
readonly kind: K
readonly url?: string
readonly path?: string
readonly endpoints?: Endpoints
}
>
node.path?: string | undefinedpath ?? const endpoints: Endpointsconst endpoints: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
endpoints.Endpoints.IpcSocket?: {
readonly path: string;
} | undefined
IpcSocket?.path: string | undefinedpath,
kind: ProtocolKindkind,
endpoints: Endpoints(property) endpoints: {
Http: { readonly url: string };
WebSocket: { readonly url: string };
IpcSocket: { readonly path: string };
}
endpoints,
// Same-identity derived handle keeps the base node's advertise policy.
onConflict: OnConflictonConflict: node: NodeTagClass<
Self,
ROut,
{
readonly kind: K
readonly url?: string
readonly path?: string
readonly endpoints?: Endpoints
}
>
node.onConflict: OnConflictonConflict,
});
};