@hyperfrontend/network-protocol/browser/channel

channel

Browser-side channel factories pre-wired with the browser sender and receiver implementations.

Overview

A channel is a named, bidirectional, queue-backed conduit that binds one protocol instance to one negotiated session. This entry point composes the runtime-agnostic channel logic from lib/channel with the browser sender (/browser/sender) and receiver (/browser/receiver), so createChannel needs a label and an options object: the transport callbacks, a ProtocolProvider from /browser/v3 or /browser/v4, the ProtocolSession, and an optional onDrop handler. The channel exposes the protocol's hello exchange (hello, isHello, acceptHello) so the session can be keyed over the same transport.

Usage

import { createChannel, createChannelStore } from '@hyperfrontend/network-protocol/browser/channel'
import { createProtocol } from '@hyperfrontend/network-protocol/browser/v3'
import { createLogger } from '@hyperfrontend/logging'

const channel = createChannel('app-to-widget', {
  send: (frame) => otherWindow.postMessage(frame, origin, [frame.buffer]),
  receive: (packet) => handle(packet.data.message),
  protocolProvider: createProtocol(createLogger({ level: 'info' })),
  session: { protocol: 'v3', role: 'initiator', localId, peerId },
  onDrop: (drop) => report(drop),
})
otherWindow.postMessage(await channel.hello(), origin)
window.addEventListener('message', ({ data }) => (channel.isHello(data) ? channel.acceptHello(data) : channel.receive(data)))

const store = createChannelStore()
store.add(channel)

Notes

API Reference§

ƒ Functions

§function

getFirstInvalidProtocolProperty(protocol: unknown): string

Identifies the first invalid property in a protocol object.
Parameters
NameTypeDescription
§protocol
unknownThe protocol object to inspect
Returns
string
The name of the first property that is not a function, or an empty string when every property is valid
Example

Reporting a protocol missing its opener

getFirstInvalidProtocolProperty({ seal, send, receive, getLogger })
// => 'open'
§function

isValidChannel(channel: unknown): boolean

Checks that a value has the shape of a channel: send, receive, and hello-exchange functions and an outbound and inbound pipeline each exposing a queue with a size and stop/resume controls.
Parameters
NameTypeDescription
§channel
unknownThe value to check
Returns
boolean
True when the value has the shape of a Channel
Example

Guarding a channel before storing it

isValidChannel(createChannel('comms', options))
// => true
§function

isValidLabel(label: string): boolean

Validates whether a label meets the required criteria of being a non-empty string.
Parameters
NameTypeDescription
§label
stringThe label string to validate
Returns
boolean
True if the label is valid, false otherwise
Example

Validating channel labels

isValidLabel('channel-1') // => true
isValidLabel('') // => false
§function

isValidReceiver(receiver: unknown): boolean

Validates whether a receiver meets the required criteria of being a function.
Parameters
NameTypeDescription
§receiver
unknownThe receiver to validate
Returns
boolean
True if the receiver is valid, false otherwise
Example

Validating receiver functions

isValidReceiver((packet) => handlePacket(packet)) // => true
isValidReceiver('not-a-function') // => false
§function

isValidSender(sender: unknown): boolean

Validates whether a sender meets the required criteria of being a function.
Parameters
NameTypeDescription
§sender
unknownThe sender to validate
Returns
boolean
True if the sender is valid, false otherwise
Example

Validating sender functions

isValidSender((packet) => transmit(packet)) // => true
isValidSender(null) // => false
§function

isValidSession(session: unknown): unknown

Checks that a value has the shape of a protocol session: a protocol id, a role, and both identities.
Parameters
NameTypeDescription
§session
unknownThe value to check
Returns
unknown
True when the value has the shape of a ProtocolSession
Example

Guarding a session before binding a protocol to it

isValidSession({ protocol: 'v3', role: 'initiator', localId, peerId })
// => true

◈ Interfaces

§interface

Channel

Secure communication channel with an outbound and an inbound pipeline
Properties
§stop:() => voidStops the operation
§resume:() => voidResumes the operation
§readonly label:stringChannel label for identification
§readonly send:SendFn<T>Sends a message through the channel
§readonly receive:ReceiveFnReceives sealed frames from the channel; hello frames go to acceptHello instead
§readonly outbound:OutboundPipelineOutbound pipeline
§readonly inbound:InboundPipelineInbound pipeline
Methods
§acceptHello(frame: WirePacket): HelloOutcome
Feeds the peer's hello frame.

Parameters

NameTypeDescription
§frame
WirePacketThe peer's hello

Returns

HelloOutcome
Whether the material was accepted, already known, or rejected
This side's hello frame: the public material the peer needs to derive the session keys.

Returns

Promise<WirePacket>
The frame to transmit, the same bytes on every call
§isHello(frame: WirePacket): boolean
Tells a hello frame apart from a sealed frame.

Parameters

NameTypeDescription
§frame
WirePacketBytes received from the peer

Returns

boolean
True when the bytes are a hello frame of this protocol
§interface

ChannelEntry

Entry in a channel store with metadata
Properties
§readonly id:stringUnique channel identifier
§readonly name:stringChannel name
§readonly channel:Channel<T>The channel instance
§interface

ChannelOptions

Everything a channel needs beyond its label
Properties
§readonly send:SendPacketFnTransmits each sealed frame to the peer
§readonly receive:ReceivePacketFn<T>Receives each opened packet
§readonly protocolProvider:ProtocolProvider<T>Creates the protocol instance for the session
§readonly session:ProtocolSessionThe negotiated session the protocol instance is bound to
§readonly onDrop?:PacketDropHandlerOptional; receives every packet either pipeline discards
§interface

ChannelStore

Store for managing multiple channels
Properties
§readonly create:(label: string, options: ChannelOptions<T>) => Channel<T>Creates and returns a new channel
§readonly add:(topic: Channel<T>[]) => voidAdds channels to the store
§readonly existsByName:(name: string) => booleanChecks if a channel exists by name
§readonly existsById:(id: string) => booleanChecks if a channel exists by ID
§readonly removeByName:(name: string[]) => voidRemoves channels by name
§readonly removeById:(id: string[]) => voidRemoves channels by ID
§readonly clear:() => voidRemoves all channels
§readonly getByName:(name: string) => Channel<T>Gets a channel by name
§readonly getById:(id: string) => Channel<T>Gets a channel by ID
§readonly list:unknownList of all channel entries
§interface

HelloExchange

The hello exchange that keys a session: each side sends its public material in the clear and accepts the peer's before any frame can be sealed or opened.
Methods
§acceptHello(frame: WirePacket): HelloOutcome
Feeds the peer's hello frame.

Parameters

NameTypeDescription
§frame
WirePacketThe peer's hello

Returns

HelloOutcome
Whether the material was accepted, already known, or rejected
This side's hello frame: the public material the peer needs to derive the session keys.

Returns

Promise<WirePacket>
The frame to transmit, the same bytes on every call
§isHello(frame: WirePacket): boolean
Tells a hello frame apart from a sealed frame.

Parameters

NameTypeDescription
§frame
WirePacketBytes received from the peer

Returns

boolean
True when the bytes are a hello frame of this protocol
§interface

InboundPipeline

The inbound side of a channel: its open queue and its controls
Properties
§stop:() => voidStops the operation
§resume:() => voidResumes the operation
§readonly queue:InboundQueueThe frames waiting to be opened
§interface

OutboundPipeline

The outbound side of a channel: its seal queue and its controls
Properties
§stop:() => voidStops the operation
§resume:() => voidResumes the operation
§readonly queue:OutboundQueueThe packets waiting to be sealed
§interface

PacketDrop

A packet a pipeline stage rejected and the pipeline discarded
Properties
§readonly direction:"inbound" | "outbound"Whether the packet was leaving (outbound) or arriving (inbound)
§readonly stage:PacketDropStageThe stage that rejected the packet
§readonly reason:stringWhy the stage rejected it
§readonly cause?:unknownThe error the stage threw, when it threw one
§readonly packet:unknownThe packet as the stage received it
§interface

Protocol

Protocol instance: the session's seal and open operations, its hello exchange, and the transport callbacks
Properties
§seal:PacketSealer<T>Seals outgoing packets under the session's sending key
§open:PacketOpener<T>Opens incoming frames under the session's receiving key
§send:SendPacketFnTransmits a sealed frame
§receive:ReceivePacketFn<T>Receives an opened packet
§getLogger:() => LoggerReturns the logger instance
Methods
§acceptHello(frame: WirePacket): HelloOutcome
Feeds the peer's hello frame.

Parameters

NameTypeDescription
§frame
WirePacketThe peer's hello

Returns

HelloOutcome
Whether the material was accepted, already known, or rejected
This side's hello frame: the public material the peer needs to derive the session keys.

Returns

Promise<WirePacket>
The frame to transmit, the same bytes on every call
§isHello(frame: WirePacket): boolean
Tells a hello frame apart from a sealed frame.

Parameters

NameTypeDescription
§frame
WirePacketBytes received from the peer

Returns

boolean
True when the bytes are a hello frame of this protocol
§interface

ProtocolSession

What a protocol needs to key one session: the negotiated protocol, this side's role, and both identities. The key material itself is minted by the protocol and exchanged through hello frames once the session exists.
Properties
§readonly protocol:stringThe negotiated protocol identifier
§readonly role:SessionRoleWhether this endpoint initiated or answered the handshake
§readonly localId:stringThis endpoint's identity as stamped on packets
§readonly peerId:stringThe peer's identity as stamped on packets
§interface

StopResumeControl

Interface for stopping and resuming operations
Properties
§stop:() => voidStops the operation
§resume:() => voidResumes the operation

◆ Types

§type

ChannelCreater

Factory function for creating channels
type ChannelCreater = (label: string, options: ChannelOptions<T>) => Channel<T>
§type

HelloOutcome

What accepting a hello frame did.
  • accepted: the peer's material is now known and the session can be keyed
  • duplicate: the same material was already accepted; a retry, ignored
  • rejected: the frame is not a hello this session can use
type HelloOutcome = "accepted" | "duplicate" | "rejected"
§type

PacketDropHandler

Receives each packet a pipeline discards
type PacketDropHandler = (drop: PacketDrop) => void
§type

PacketDropStage

The pipeline stage that rejected a packet
type PacketDropStage = "seal" | "open"
§type

ProtocolProvider

Factory function that creates a protocol instance for one session from send/receive functions
type ProtocolProvider = (send: SendPacketFn, receive: ReceivePacketFn<T>, session: ProtocolSession) => Protocol<T>
§type

SessionRole

Which side of the handshake this endpoint played
type SessionRole = "initiator" | "responder"

● Variables

§type

createChannel

§type

createChannelStore