@hyperfrontend/nexus§

Two broker cards, host-app and cart-app, each with a shaped slot cut into its edge for the message type it accepts; three pulses cross a dashed wire and it turns solid; a triangle token slides into the cart's triangle slot, a circle token into the host's circle slot, and a diamond token for PRICE_SYNC finds no slot on the host, stops at its edge and dissolvesTwo broker cards, host-app and cart-app, each with a shaped slot cut into its edge for the message type it accepts; three pulses cross a dashed wire and it turns solid; a triangle token slides into the cart's triangle slot, a circle token into the host's circle slot, and a diamond token for PRICE_SYNC finds no slot on the host, stops at its edge and dissolves

Secure cross-window communication library for micro-frontends with contract-validated messaging, origin-based security policies, and connection lifecycle management.

What is @hyperfrontend/nexus?

Two windows talking over postMessage share a string and nothing else: no agreement on which message types exist, no way to tell whether anyone is listening, no signal when the other side goes away. Nexus puts a broker in front of that. One broker per app manages a channel per counterpart window or frame, and every channel carries a contract, the message types each side sends and accepts, exchanged during a three-way handshake. Types outside the contract are dropped, messages from an origin other than the pinned one are ignored, and the connection state is something you subscribe to instead of infer.

import { createBroker } from '@hyperfrontend/nexus'

const broker = createBroker({
  name: 'host-app',
  contract: { emitted: [{ type: 'THEME_CHANGED' }], accepted: [{ type: 'CART_UPDATED' }] },
  settings: { whitelist: ['https://cart.example.com'] },
})

const cart = broker.addChannel('cart', cartFrame.contentWindow)
cart.on('open', () => cart.send('THEME_CHANGED', { theme: 'dark' }))
cart.onMessage(({ type, data }) => console.log(type, data))
cart.connect()

Key Features

  • Contract-Validated Messaging

    define accepted and emitted message types, with optional JSON Schemas carried for consumers to validate payloads against

  • Broker-Channel Architecture

    a central broker manages multiple independent channels to different windows

  • Origin-Based Security

    whitelist/blacklist filtering plus custom security policy functions

  • Connection Lifecycle Management

    full state machine for connect, disconnect, cancel, deny, and destroy operations

  • Event Subscription System

    subscribe to lifecycle events (open, close, cancel, deny, invalid, connect-timeout, security events) and user messages

  • Message Queueing

    messages sent before a channel is active are queued, not lost

  • Contract Extension & Merging

    extend contracts at runtime or merge several into one

  • Functional API Design

    factory functions with closure-based encapsulation, no class hierarchy to subclass

Why Use @hyperfrontend/nexus?

Micro-frontend integrations fail where two teams assumed different message shapes. A contract makes the assumption a value both sides exchange and the runtime enforces:

const contract: IChannelContract = {
  emitted: [{ type: 'USER_UPDATED', schema: userJsonSchema }, { type: 'NAVIGATION_REQUEST' }],
  accepted: [{ type: 'USER_DATA' }, { type: 'NAVIGATION_COMPLETE' }],
}

Unknown inbound types are dropped and logged, and an accepted entry marked required: true denies the handshake outright when the counterpart cannot emit it. Adding actions stays backward compatible either way.

Origin checks come with it. A whitelist/blacklist pair on the broker settings, or broker.setSecurityPolicy((event) => event.origin.endsWith('.example.com')), vets requests before the channel opens, so no message handler has to remember to test event.origin itself.

One broker holds many channels, which is what a host coordinating several micro-apps needs: call addChannel per frame, then loop the handles to connect or broadcast. Each channel runs its own handshake and lifecycle, so a frame that never answers cannot stall the others, and messages sent before a channel goes active are queued rather than dropped.

Handlers stay small. Subscribe to a single lifecycle event with channel.on('open', handler), or replace a switch over message types with one filtered subscription per type:

import { byType, compose, createMessageFilter } from '@hyperfrontend/nexus'

channel.onMessage(byType('USER_LOGIN')(handleLogin))
channel.onMessage(byType('USER_LOGOUT')(handleLogout))
channel.onMessage(byType('DATA_SYNC')(handleSync))

// compose narrows a single subscription: a message must pass every filter
channel.onMessage(
  compose(
    byType('DATA_SYNC'),
    createMessageFilter((message) => message.data?.priority === 'high')
  )(handleUrgentSync)
)

Handshake states, denial reasons, queue behaviour, and the encrypted-envelope negotiation are worked through in the architecture documentation.

Protocol Overview

Nexus implements a three-way handshake protocol (REQUEST → ACCEPT → OPEN) for establishing connections, with graceful disconnection, cancellation, denial, and timeout handling. The summaries below map the territory; the Architecture Documentation covers every flow in depth.

Connection Handshake

Initiation is symmetric: either side may call connect() first, and simultaneous requests resolve deterministically via a broker-id tie-break. Pending handshake messages are re-sent every requestRetryMs (default 500 ms) until answered, and a handshake unanswered past connectTimeoutMs (default 10 000 ms) fires connect-timeout, leaving the channel inactive and reconnectable with its queued messages retained. Each side pins the counterpart's origin during the handshake, and inbound messages from any other origin are dropped. See Protocol Design.

Contract Compatibility

Contracts are exchanged during the handshake, but vocabulary differences never gate the connection: only accepted entries flagged required: true do (each must appear in the counterpart's emitted list), so additive contract evolution stays non-breaking in both directions. A contract may also carry an optional version string that nexus attaches no semantics to; a contractCompat rule in the channel settings can compare the two contracts and deny the pair before it opens. When the responder's rule rejects an incoming request, the deny event fires with the rule's reason and reason: 'incompatible-contract' on both the denying responder and the denied initiator. See Contract Compatibility.

Security Negotiation

Channels can negotiate a sealed envelope during the handshake: register a security provider on the broker (via broker.registerProtocol(version, provider) or the settings.security.protocols bag) and opt the channel in with security: { protocol: 'v3' } or security: { protocol: 'v4' }. The initiator's REQUEST advertises that protocol with plaintext as the fallback, the responder's ACCEPT answers with the outcome, and the initiator's OPEN confirms it; a channel that selected a protocol accepts that protocol or plaintext and nothing else.

Each side attaches its transport as it sends its own handshake answer (the responder with ACCEPT, the initiator with OPEN) and posts the session hello right behind that frame, retrying it every requestRetryMs until the counterpart confirms. Product traffic, including sends queued before the handshake, leaves as Uint8Array frames sealed under the session keys while the handshake actions themselves stay plaintext; once a transport is attached, any other plaintext action is dropped.

The first inbound frame that authenticates confirms the counterpart and fires security-ready; a session nothing confirms within connectTimeoutMs fires security-error with code security-unconfirmed and closes with reason: 'security-unconfirmed'. Negotiation fails open by default, falling back to plaintext with a warning when the counterpart cannot provide the protocol; mode: 'fail-closed' denies the connection instead with reason: 'security-unavailable'.

The transport seam is public: createSecurityTransport plus the SecurityTransport and SecurityProvider types define the boundary a security package implements, and @hyperfrontend/network-protocol (v3: ephemeral session keys agreed over the wire, defeating scripts that can only listen; v4: the same keys bound to a pre-shared key, defeating any script without the key) satisfies it directly. See Security Model.

Disconnection & Cancellation

An active channel closes gracefully through a CLOSE/CLOSE_ACKNOWLEDGED exchange, firing close on both sides; a pending connection can be abandoned by either party through CANCEL/CANCEL_ACKNOWLEDGED, firing cancel. Denials (DENY_CONNECTION) and protocol violations (INVALID_REQUEST) round out the failure verbs, and every connection attempt ends in exactly one of open, close, cancel, deny, or connect-timeout. See Protocol Design.

Security Policies

What these gates are worth, and which controls sit outside the protocol entirely (frame-ancestors, backend authorisation, the pre-shared key), is stated in the Security Model.

Connection-time access control runs before a channel opens: origin whitelist/blacklist settings filter every inbound message (a non-empty whitelist takes precedence), and a custom policy function, broker.setSecurityPolicy((event: MessageEvent) => boolean), vets requests during handshake handling, with rejected requests answered by DENY_CONNECTION. See Security Model.

Logging

All internal output routes through a Logger from @hyperfrontend/logging. Set verbosity with the logLevel setting ('error' | 'warn' | 'log' | 'info' | 'debug' | 'none') or inject a custom logger (Winston, Pino, etc.) via settings.logger; channels inherit the broker's logger, exposed as broker.logger. See Logging System.

Installation

npm install @hyperfrontend/nexus

Quick Start

import { createBroker } from '@hyperfrontend/nexus'

// Define communication contract
const contract = {
  emitted: [{ type: 'PING' }],
  accepted: [{ type: 'PONG' }],
}

// Create broker
const broker = createBroker({
  name: 'main-app',
  contract,
  settings: { logLevel: 'debug' },
})

// Add channel to iframe
const iframe = document.querySelector('iframe')
const channel = broker.addChannel('child-app', iframe.contentWindow)

// Subscribe to messages
channel.onMessage((message) => {
  console.log('Received:', message.type, message.data)
})

// Connect and send
channel.connect()
channel.send('PING', { timestamp: Date.now() })

Using the Default Broker

For quick prototyping, use the pre-configured singleton broker:

import { defaultBroker } from '@hyperfrontend/nexus'

const channel = defaultBroker.addChannel('my-channel', targetWindow)
channel.connect()
channel.send('MESSAGE', { hello: 'world' })

API Overview

Everything starts at createBroker. One broker per app: it owns the single message listener on your window, holds the contract every channel inherits, and carries the origin whitelist and security policy that apply to all of them. Channels are what you actually hold, one per counterpart window, handed out by addChannel(name, targetWindow, settings?) as a ChannelHandle. defaultBroker is a ready-made singleton for a prototype that only ever talks to one frame.

A channel does nothing until connect(), which starts the three-way handshake. That handshake is where the three things worth having get settled at once: the two IChannelContract values (an emitted list and an accepted list of action types) are exchanged, each side pins the counterpart's origin, and the broker's gates vet the request before anything opens. After that the day-to-day surface is two calls. send(type, data) throws at the call site for any type outside your own emitted list, so a typo never travels. onMessage(handler) delivers only the types in your own accepted list; anything else arrives, is logged, and stops there, which is not an event you can subscribe to.

Connection state is an event stream rather than a flag you poll. channel.on(event, handler) subscribes to one ChannelEvent and channel.on(handler) to all of them; both return an unsubscribe function. Every connection attempt ends in exactly one of open, close, cancel, deny or connect-timeout, and a denial (or a close neither side asked for) carries a machine-readable reason beside its message, so a failure is something you branch on rather than parse.

The rest is opt-in. byType and compose replace a switch over message types with one narrow subscription per type; mergeContracts folds several contracts into one; and createSecurityTransport with the SecurityProvider type is the seam a security package implements, which is how @hyperfrontend/network-protocol supplies the sealed v3 and v4 session envelope.

Every setting, event payload, deny reason and security type is in the API reference.

Compatibility

Runs on

  • Node.js>=18.0.0supported
  • Browserssupported
  • Web Workerssupported

Ships as

  • ESMTree-shakeable
  • CJSNode and older bundlers
  • IIFEHyperfrontendNexus
  • UMDHyperfrontendNexus

CDN Usage

<!-- unpkg -->
<script src="https://unpkg.com/@hyperfrontend/nexus"></script>

<!-- jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/@hyperfrontend/nexus"></script>

<script>
  const { createBroker, createChannel } = HyperfrontendNexus
</script>

Global variable: HyperfrontendNexus

Peer Dependencies

PackageVersionType
@hyperfrontend/network-protocol2.0.0Optional

API Reference§

Filter:

ƒFunctions

§function

byType<T>(messageType: string): (handler: MessageHandler<T>) => MessageHandler<T>

Creates a filter that only passes messages of a specific type
Parameters
NameTypeDescription
§messageType
stringThe message type to filter for
Returns
(handler: MessageHandler<T>) => MessageHandler<T>
A higher-order function that wraps a handler
Example

Filtering by message type

const pingFilter = byType('ping')
const handler = pingFilter((msg, channel) => {
  console.log('Received ping from', channel.name)
})
§function

cancelFilter(handler: CancelEventHandler): EventHandler

Creates a filter that only passes CANCEL events to the handler
Parameters
NameTypeDescription
§handler
CancelEventHandlerHandler that only receives CANCEL events
Returns
EventHandler
Wrapped handler that filters for CANCEL events
§function

closeFilter(handler: CloseEventHandler): EventHandler

Creates a filter that only passes CLOSE events to the handler
Parameters
NameTypeDescription
§handler
CloseEventHandlerHandler that only receives CLOSE events
Returns
EventHandler
Wrapped handler that filters for CLOSE events
§function

compose<T>(...filters: MessageFilter<T>[]): MessageFilter<T>

Composes multiple message filters into a single filter. Filters are applied right-to-left during execution (rightmost filter executes first).
Parameters
NameTypeDescription
§...filters
MessageFilter<T>[]Variable number of filter functions to compose
Returns
MessageFilter<T>
A single composed filter
Example

Composing message filters

const combinedFilter = compose(
  byType('notification'),
  create((msg) => msg.priority === 'high')
)
const handler = combinedFilter((msg) => console.log(msg))
§function

createBroker(config: CreateBrokerConfig): BrokerHandle

Creates a message broker instance
Parameters
NameTypeDescription
§config
CreateBrokerConfigBroker configuration
Returns
BrokerHandle
Broker handle with public API
Example

Creating a message broker

const broker = createBroker({
  name: 'app-broker',
  contract: {
    emitted: [{ type: 'PING' }],
    accepted: [{ type: 'PONG' }],
  },
  settings: { logLevel: 'warn' },
})
§function

createChannel(config: IChannelConfig, deps: ChannelDependencies): ChannelHandle

Creates a new message channel.
Uses functional programming with closures for encapsulation. Returns a public handle with methods while keeping state private.
Parameters
NameTypeDescription
§config
IChannelConfigChannel configuration (name, target, settings)
§deps
ChannelDependenciesDependencies (action creators, process manager, cleanup)
Returns
ChannelHandle
Channel handle with public API
Example

Creating and using a channel

const channel = createChannel(
  { name: 'my-channel', target: childWindow },
  { actions, processManager, cleanup }
)
channel.connect()
channel.send('greet', { message: 'Hello!' })
§function

createEventFilter(eventType: ChannelEvent): (handler: EventHandler) => EventHandler

Creates an event filter that only calls the handler for a specific event type
Parameters
NameTypeDescription
§eventType
ChannelEventThe event type to filter for
Returns
(handler: EventHandler) => EventHandler
A higher-order function that wraps a handler
Example

Filtering channel events

const openFilter = create('open')
const filteredHandler = openFilter((event, data, channel) => {
  console.log('Channel opened:', channel.name)
})
§function

createLogger(options: NexusLoggerOptions): Logger

Creates a logger instance configured for nexus.
If a custom logger is provided, it will be used directly. Otherwise, a new logger will be created using the logging library.
Parameters
NameTypeDescription
§options
NexusLoggerOptionsLogger configuration options(default: {})
Returns
Logger
Logger instance
Example

Configuring logger options

const logger = createLogger({ level: 'debug', prefix: '[my-channel]' })
logger.debug('Channel initialized')
§function

createMessageFilter<T>(predicate: MessagePredicate<T>): (handler: MessageHandler<T>) => MessageHandler<T>

Creates a message filter that only calls the handler when predicate returns true
Parameters
NameTypeDescription
§predicate
MessagePredicate<T>Function that tests if message should be handled
Returns
(handler: MessageHandler<T>) => MessageHandler<T>
A higher-order function that wraps a handler
Example

Creating custom message filters

const highPriorityFilter = create((msg) => msg.priority === 'high')
const filteredHandler = highPriorityFilter((msg, channel) => {
  console.log('High priority:', msg)
})
§function

createSecurityTransport(config: SecurityTransportConfig): SecurityTransport

Creates a security transport based on the configured protocol.
Routes to the appropriate transport implementation:
  • 'none': Creates a passthrough transport (no encryption)
  • Any other protocol: Creates a secure transport driving the provider's
pipeline
Parameters
NameTypeDescription
§config
SecurityTransportConfigTransport configuration
Returns
SecurityTransport
A security transport appropriate for the configured protocol
Example

Creating security transports

import { logger } from '@hyperfrontend/logging'
import { createChannel } from '@hyperfrontend/network-protocol/browser/channel'
import { createProtocol } from '@hyperfrontend/network-protocol/browser/v4'

const transport = createSecurityTransport({
  protocol: 'v4',
  provider: { createChannel, protocolProvider: createProtocol(logger, 'shared-key') },
  label: 'checkout-feature',
  target: iframe.contentWindow,
  getOrigin: () => 'https://feature.example.com',
  originId: hostId,
  targetId: featureId,
  role: 'initiator',
  onAction: (action) => handleAction(action),
})
§function

denyFilter(handler: DenyEventHandler): EventHandler

Creates a filter that only passes DENY events to the handler
Parameters
NameTypeDescription
§handler
DenyEventHandlerHandler that only receives DENY events
Returns
EventHandler
Wrapped handler that filters for DENY events
§function

invalidFilter(handler: InvalidEventHandler): EventHandler

Creates a filter that only passes INVALID events to the handler
Parameters
NameTypeDescription
§handler
InvalidEventHandlerHandler that only receives INVALID events
Returns
EventHandler
Wrapped handler that filters for INVALID events
§function

logAction(logger: Logger, action: IAction, direction: "sent" | "received"): void

Logs an action in a structured format.
Parameters
NameTypeDescription
§logger
LoggerLogger instance
§action
IActionAction to log
§direction
"sent" | "received"Direction of action ('sent' or 'received')
§function

logEvent(logger: Logger, event: ChannelEvent, data: unknown): void

Logs a channel event in a structured format.
Parameters
NameTypeDescription
§logger
LoggerLogger instance to use
§event
ChannelEventType of channel event that occurred
§data
unknownAdditional data associated with the event
§function

mergeContracts(...contracts: IChannelContract[]): IChannelContract

Merges multiple channel contracts into a single contract
Parameters
NameTypeDescription
§...contracts
IChannelContract[]The contracts to merge
Returns
IChannelContract
A single merged contract containing all accepted and provided actions
Example

Merging channel contracts

const contract1 = { accepted: [{ type: 'a' }], provided: [{ type: 'b' }] }
const contract2 = { accepted: [{ type: 'c' }], provided: [{ type: 'd' }] }
const merged = mergeContracts(contract1, contract2)
// merged = { accepted: [{ type: 'a' }, { type: 'c' }], emitted: [{ type: 'b' }, { type: 'd' }] }
§function

openFilter(handler: OpenEventHandler): EventHandler

Creates a filter that only passes OPEN events to the handler
Parameters
NameTypeDescription
§handler
OpenEventHandlerHandler that only receives OPEN events
Returns
EventHandler
Wrapped handler that filters for OPEN events

◈Interfaces

§interface

BrokerConfig

Broker configuration passed to factory
Properties
§readonly id:stringUnique broker identifier
§readonly name:stringBroker name
§readonly settings:BrokerSettingsBroker settings
§interface

BrokerHandle

Broker handle returned by factory
Properties
§readonly acceptedActionTypes:unknownAction types accepted by this broker
§readonly channels:unknownList of registered channels
§readonly contract:IChannelContractChannel contract for messaging
§readonly id:stringUnique broker identifier
§readonly logger:LoggerGet the broker's logger instance.
§readonly name:stringBroker name
§readonly settings:BrokerSettingsBroker configuration settings
§interface

BrokerSecurityConfig

Broker-level security configuration.
Registers protocol providers for all channels managed by the broker.
Properties
§readonly protocols?:SecurityProtocolProvidersPre-registered protocol providers keyed by version
§interface

BrokerSettings

Broker settings configuration
Properties
§readonly blacklist?:unknownList of blocked origins
§readonly contract:IChannelContractDefault contract for all channels
§readonly contractExtension?:booleanAllow contract extension
§readonly logger?:LoggerCustom logger instance to use
§readonly logLevel?:LogLevelMinimum log level to emit (default: 'error')
§readonly security?:BrokerSecurityConfigSecurity configuration for protocol negotiation and encryption
§readonly securityPolicy?:SecurityPolicyCustom security validation function
§readonly whitelist?:unknownList of allowed origins (takes precedence over blacklist)
§interface

BrokerState

Internal broker state
Properties
§readonly contract:IChannelContractChannel contract for messaging
§readonly id:stringUnique broker identifier
§readonly logger:LoggerLogger instance for debugging
§readonly name:stringBroker name
§readonly settings:BrokerSettingsBroker configuration settings
§readonly window:WindowWindow context for the broker
§interface

CancelEventData

Data payload for CANCEL event.
One cancelled attempt fires exactly one 'cancel' event on each side.
Properties
§notify:booleanWhether the counterpart is the side that cancelled: true only on the side that received a CANCEL frame. A cancellation this side initiated reports false, whether or not it sent a frame, so a subscriber can tell the two apart.
§interface

ChannelHandle

Channel handle returned by createChannel factory. Provides methods for interacting with the channel.
Properties
§readonly id:stringChannel unique identifier (for registry compatibility)
§readonly name:stringChannel name (for registry compatibility)
§readonly target:WindowTarget window (for registry compatibility)
§interface

ChannelJSON

Safe serializable representation of a channel for callbacks. Contains only data, no methods or internal references.
Properties
§active:booleanWhether channel is active
§connectTimestamp:numberWhen channel connected
§contract:IChannelContractChannel contract
§id:stringChannel unique identifier
§name:stringChannel name
§origin:stringOrigin of connected channel
§peerContract:IChannelContractContract declared by the connected counterpart
§peerId:stringBroker id of the connected counterpart
§queuedMessagesCount:numberNumber of queued messages
§interface

ChannelSecuritySettings

Channel-level security settings.
Properties
§readonly disabled?:booleanDisable security even if the broker registered providers
§readonly mode?:"fail-open" | "fail-closed"How the channel behaves when it selects a protocol but the handshake cannot deliver it (the counterpart predates security, offers no common protocol, selects another one, or the negotiated provider is missing).
  • 'fail-open' (default): fall back to plaintext with a warning
  • 'fail-closed': refuse the connection with reason 'security-unavailable'
§readonly protocol?:SecurityProtocolVersionProtocol the channel negotiates; the handshake accepts no other encrypted outcome
§interface

CloseEventData

Data payload for CLOSE event
Properties
§notify:booleanWhether remote end was notified
§reason?:CloseReasonWhy the session ended, when neither side asked for the close
§interface

ContractCompatible

Compatible outcome of a contract-compatibility check.
Properties
§compatible:trueDiscriminant marking the pair compatible.
§interface

ContractIncompatible

Incompatible outcome of a contract-compatibility check: the connection is denied before it opens.
Properties
§compatible:falseDiscriminant marking the pair incompatible.
§reason:stringHuman-readable reason delivered with the connection denial.
§interface

DenyEventData

Data payload for DENY event
Properties
§error?:stringHuman-readable error explaining the denial
§origin?:stringOrigin of the counterpart that denied the connection
§reason?:DenyReasonMachine-readable denial reason
§interface

IActionDescription

Describes an action that can be sent or received on a channel
Properties
§description?:stringHuman-readable description of the action
§required?:booleanMarks an accepted action as essential for correct operation: the connection is denied unless the counterpart emits this type. Only meaningful on accepted entries; ignored on emitted.
§schema?:objectJSON schema for validating action payload
§type:stringUnique identifier for the action type
§interface

IChannelConfig

Configuration for creating a new channel
Properties
§name:stringChannel identifier/name
§settings?:IChannelSettingsChannel behavior settings
§target:WindowTarget window for postMessage communication
§interface

IChannelContract

Contract defining the actions a broker or channel exchanges with its counterpart.
A contract is self-oriented: it always describes the side that owns it. emitted lists the message types this side sends, and accepted lists the message types this side is willing to receive. Outgoing messages are validated against emitted; incoming messages are validated against accepted and silently dropped (with a log entry) when not listed. Accepted entries flagged required additionally gate the connection: a counterpart that does not emit them is denied at handshake time.
Properties
§accepted:IActionDescription[]Message types this side accepts from its counterpart
§emitted:IActionDescription[]Message types this side sends to its counterpart
§version?:stringOptional version string announcing the contract cut this side holds. Crossed to the counterpart during the handshake and stored on peerContract; nexus itself attaches no semantics to it, though a channel-supplied compatibility rule may compare the two announcements.
§interface

IChannelSettings

Channel behavior settings
Properties
§brokerManaged?:booleanWhether the channel is managed by a broker
§closeTimeoutMs?:numberMilliseconds a polite close waits for the counterpart's acknowledgement before closing anyway (default: 2000)
§connectTimeoutMs?:numberMilliseconds a connection attempt may remain unanswered before firing 'connect-timeout' (default: 10000)
§contract?:IChannelContractExpected channel contract (if not set, inherited from broker)
§contractCompat?:ContractCompatRule deciding whether the local and counterpart contracts may interoperate; an incompatible pair is denied during the handshake
§logger?:LoggerCustom logger instance to use
§logLevel?:LogLevelMinimum log level to emit (default: 'error')
§origin?:stringExpected origin ('*' for any, or specific URL)
§queueMessages?:booleanQueue messages when channel is not yet active
§requestRetryMs?:numberMilliseconds between handshake re-sends while a connection attempt is pending (default: 500)
§security?:ChannelSecuritySettingsSecurity settings for protocol negotiation and encryption
§interface

IMessage

User message interface for application-level communication. Only 'type' is required; data and other properties are optional.
Properties
§data?:unknownOptional payload data (must be serializable via postMessage)
§timestamp?:numberOptional timestamp for when message was created
§type:stringMessage type identifier (e.g., 'user-logged-in', 'data-updated')
§interface

InvalidEventData

Data payload for INVALID event
Properties
§action?:IActionThe invalid action that was received (if available)
§error:stringError message describing what was invalid
§interface

Logger

Logger interface with level-specific methods and level control
Properties
§channel:ChannelFnReturns a sub-logger that prepends [prefix] to every message.
§debug:DebugLevelFnDebug-level output
§error:ErrorLevelFnError-level output
§getLogLevel:GetLogLevelGets the current log level
§info:InfoLevelFnInfo-level output
§log:LogLevelFnStandard log output
§setLogLevel:SetLogLevelSets the current log level
§timed:TimedFnWraps a sync call with timing. Logs completion or failure with elapsed ms.
§timedAsync:TimedAsyncFnWraps a promise-returning call with timing. Dumps stack trace on error to debug log.
§warn:WarnLevelFnWarning-level output
§interface

MessageEnvelope

Internal message envelope for routing and tracking. Wraps user messages with metadata for internal use.
Properties
§channelId:stringID of the channel handling this message
§direction:"inbound" | "outbound"Direction of message flow
§message:IMessageThe user message being transmitted
§interface

NexusLoggerOptions

Options for creating a nexus logger.
Properties
§readonly customLogger?:LoggerCustom logger instance to use instead of creating one
§readonly level?:LogLevelMinimum log level to emit (default: 'error')
§readonly prefix?:stringPrefix for log messages (default: '[nexus]')
§interface

OpenEventData

Data payload for OPEN event
Properties
§contract:IChannelContractNegotiated channel contract
§origin:stringOrigin of the connected channel
§interface

SecurityChannelOptions

What a SecurityChannelFactory needs to build one channel's pipeline.
Structural mirror of network-protocol's ChannelOptions shape.
Properties
§readonly onDrop?:(drop: SecurityPacketDrop) => voidReceives every packet either direction of the pipeline discards
§readonly protocolProvider:SecurityProtocolProviderCreates the protocol instance for the session
§readonly receive:SecurityReceivePacketReceives each opened packet
§readonly send:SecuritySendPacketTransmits each sealed frame
§readonly session:SecuritySessionThe session the pipeline protects
§interface

SecurityConfirmation

Security confirmation sent in the OPEN_CONNECTION action.
Confirms which protocol the initiator attached, or that it attached none.
Properties
§readonly active:booleanWhether an encrypted transport is attached
§readonly protocol:SecurityProtocolVersionThe protocol the transport runs, or 'none'
§interface

SecurityErrorEventData

Data payload for SECURITY_ERROR event
Properties
§cause?:unknownOriginal error (if available)
§code:SecurityErrorCodeError code for programmatic handling
§message:stringError message
§interface

SecurityNegotiationRequest

Security negotiation request sent by the initiator during handshake.
The initiator includes this in the REQUEST_CONNECTION action to advertise its security capabilities and preferences.
Properties
§readonly preferred:SecurityProtocolVersionPreferred protocol (first in supported list)
§readonly supported:unknownSupported protocols in order of preference (most preferred first)
§interface

SecurityNegotiationResponse

Security negotiation response sent by the responder during handshake.
The responder includes this in the ACCEPT_CONNECTION action to communicate the negotiated protocol.
Properties
§readonly negotiated:SecurityProtocolVersionNegotiated protocol (best match between initiator and responder)
§interface

SecurityPacket

A packet the wire pipeline opened and delivered.
Properties
§readonly data:SecurityPacketDataOpened data envelope; the transported action lives at data.message
§readonly origin:stringUUID of the packet sender
§readonly target:stringUUID of the intended recipient
§interface

SecurityPacketData

Data envelope carried inside each sealed frame.
The transported nexus action lives at SecurityPacketData.message; the remaining fields are wire-protocol bookkeeping.
Properties
§readonly id:stringUUID identifying this message
§readonly message:unknownThe transported message payload
§readonly pid:stringUUID identifying the sending process
§readonly schema:SchemaJSON schema describing the message
§readonly schemaHash:stringSHA-256 hash of the serialized schema
§readonly sequence:numberCounter incremented for each message of the sending process
§interface

SecurityPacketDrop

A packet the wire pipeline rejected and discarded.
Structural mirror of network-protocol's PacketDrop shape.
Properties
§readonly cause?:unknownThe error the stage raised, when it raised one
§readonly direction:"inbound" | "outbound"Whether the packet was leaving (outbound) or arriving (inbound)
§readonly packet:unknownThe packet as the stage received it
§readonly reason:stringWhy the stage rejected it
§readonly stage:"seal" | "open"The pipeline stage that rejected the packet
§interface

SecurityProtocolProviders

Bag of pre-registered security protocol providers indexed by protocol version.
Properties
§readonly v3?:SecurityProviderProtocol v3 provider
§readonly v4?:SecurityProviderProtocol v4 provider
§interface

SecurityProvider

Everything nexus needs from a security implementation to run one channel's session. This is the boundary a security package implements: network-protocol's createChannel and a protocol provider satisfy it directly.
Properties
§readonly createChannel:SecurityChannelFactoryBuilds the per-channel wire pipeline
§readonly protocolProvider:SecurityProtocolProviderCreates the protocol instance driving the pipeline
§interface

SecurityReadyEventData

Data payload for SECURITY_READY event
Properties
§protocol:SecurityProtocolVersionThe protocol the confirmed session runs on
§interface

SecuritySession

The session a wire protocol instance protects.
Structural mirror of network-protocol's ProtocolSession shape.
Properties
§readonly localId:stringBroker id of this endpoint
§readonly peerId:stringBroker id of the counterpart
§readonly protocol:SecurityProtocolVersionIdentifier of the negotiated protocol
§readonly role:SecuritySessionRoleThis endpoint's handshake role
§interface

SecurityTransport

Security transport adapter interface.
Wraps a security wire pipeline and provides a simple send/receive interface for nexus channels.
Properties
§interface

SecurityTransportConfig

Configuration for creating a security transport adapter.
Properties
§readonly confirmTimeoutMs?:numberHow long the counterpart has to confirm the session after the transport starts
§readonly getOrigin:() => stringReturns the origin currently pinned to the channel, or null before pinning
§readonly helloRetryMs?:numberInterval between hello retries until the counterpart confirms the session
§readonly label:stringHuman-readable label for the wire pipeline, surfaced in protocol diagnostics
§readonly onAction:(action: unknown) => voidReceives each action delivered by the transport
§readonly onConfirmed?:() => voidOptional handler invoked once, when the counterpart's first frame authenticates
§readonly onError?:(error: SecurityTransportError) => voidOptional handler for security failures
§readonly onFailed?:(error: SecurityTransportError) => voidOptional handler invoked when the session can no longer be confirmed
§readonly originId:stringUUID identifying the local endpoint, stamped as each packet's origin
§readonly protocol:SecurityProtocolVersionSecurity protocol to use
§readonly provider?:SecurityProviderSecurity implementation building the wire pipeline (required for protocols other than 'none')
§readonly role:SecuritySessionRoleThis endpoint's handshake role
§readonly target:WindowCounterpart window that receives outbound traffic
§readonly targetId:stringUUID identifying the counterpart endpoint, stamped as each packet's target
§interface

SecurityTransportError

Error payload delivered to a security transport's onError handler.
Properties
§readonly cause?:unknownOptional underlying cause
§readonly code:SecurityErrorCodeMachine-readable error code
§readonly message:stringHuman-readable error message
§interface

SecurityWireChannel

The per-channel wire pipeline created by a SecurityChannelFactory.
Structural mirror of the network-protocol channel surface nexus drives.
Properties
§readonly acceptHello:(frame: Uint8Array) => SecurityHelloOutcomeFeeds the counterpart's hello to the session
§readonly hello:() => Promise<Uint8Array<ArrayBufferLike>>Produces this endpoint's hello frame
§readonly isHello:(frame: Uint8Array) => booleanWhether a frame is a hello of the channel's protocol
§readonly label:stringHuman-readable pipeline label
§readonly receive:(frame: Uint8Array) => voidFeeds a sealed frame into the opening pipeline
§readonly resume:() => voidResumes packet processing
§readonly send:(origin: string, target: string, data: SecurityPacketData) => voidSeals and transmits a data envelope from origin to target
§readonly stop:() => voidPauses packet processing
§interface

SecurityWireProtocol

Wire-protocol instance driving one channel's session.
Structural mirror of network-protocol's Protocol shape.
Properties
§readonly acceptHello:(frame: Uint8Array) => SecurityHelloOutcomeFeeds the counterpart's hello to the session
§readonly getLogger:() => LoggerReturns the logger used by the protocol
§readonly hello:() => Promise<Uint8Array<ArrayBufferLike>>Produces this endpoint's hello frame
§readonly isHello:(frame: Uint8Array) => booleanWhether a frame is a hello of this protocol
§readonly open:(frame: Uint8Array) => Promise<SecurityPacket>Opens a frame into a packet under the session's receiving key
§readonly receive:SecurityReceivePacketReceives opened packets
§readonly seal:(packet: SecurityPacket) => Promise<Uint8Array<ArrayBufferLike>>Seals a packet into a frame under the session's sending key
§readonly send:SecuritySendPacketTransmits sealed frames

◆Types

§type

ActionType

Extract action type union from ACTION_TYPES
type ActionType = indexedAccess
§type

CancelEventHandler

Type-safe event handler for CANCEL events
type CancelEventHandler = (event: "cancel", data: CancelEventData, channel: ChannelJSON) => void
§type

ChannelEvent

Channel lifecycle event types
type ChannelEvent = "open" | "closing" | "close" | "cancel" | "deny" | "invalid" | "connect-timeout" | "security-ready" | "security-error"
§type

CloseEventHandler

Type-safe event handler for CLOSE events
type CloseEventHandler = (event: "close", data: CloseEventData, channel: ChannelJSON) => void
§type

CloseReason

Why a session ended, when the cause is something other than either side asking for it.
  • peer-reload: the counterpart window now hosts a different instance
(a reload or in-frame navigation), so the session it belonged to is over. The channel stays reconnectable and the new instance's handshake is already in flight.
  • security-unconfirmed: the counterpart never confirmed the session keys
before the connect timeout (or its session material could not key the session), so the connection closed silently rather than exchange anything under unconfirmed keys. The channel stays reconnectable.
type CloseReason = "peer-reload" | "security-unconfirmed"
§type

ContractCompat

Channel-supplied rule deciding whether the local contract and the counterpart's declared contract may interoperate.
Invoked during the connection handshake alongside the required-actions check, on whichever side holds the rule; an incompatible result denies the connection before it opens, surfacing the reason on the deny event.
type ContractCompat = (own: IChannelContract, peer: IChannelContract) => ContractCompatibility
§type

ContractCompatibility

Outcome of a contract-compatibility check between the two handshake sides.
type ContractCompatibility = ContractCompatible | ContractIncompatible
§type

DenyEventHandler

Type-safe event handler for DENY events
type DenyEventHandler = (event: "deny", data: DenyEventData, channel: ChannelJSON) => void
§type

DenyReason

Why a handshake gate refused the connection.
  • invalid-contract: the counterpart's contract failed structural
validation, so there is nothing to negotiate against.
  • missing-required-actions: the counterpart's contract does not emit an
action this side accepts as required: true.
  • policy-rejected: the broker's securityPolicy refused the request.
The refused counterpart is told only that it was not accepted, so this reason reaches the deciding side alone.
  • incompatible-contract: a contractCompat rule rejected the contract
pair.
  • security-unavailable: a fail-closed channel could not obtain an
encrypted transport.
Any other string is accepted so a counterpart running a newer protocol can report a reason this build does not know yet.
type DenyReason = "invalid-contract" | "missing-required-actions" | "policy-rejected" | "incompatible-contract" | "security-unavailable" | string & { }
§type

EventData

Discriminated union of all event data types
type EventData = EventEnvelope<"open", OpenEventData> | EventEnvelope<"closing", ClosingEventData> | EventEnvelope<"close", CloseEventData> | EventEnvelope<"cancel", CancelEventData> | EventEnvelope<"deny", DenyEventData> | EventEnvelope<"invalid", InvalidEventData> | EventEnvelope<"connect-timeout", ConnectTimeoutEventData> | EventEnvelope<"security-ready", SecurityReadyEventData> | EventEnvelope<"security-error", SecurityErrorEventData>
§type

EventHandler

Generic event handler that receives all events
type EventHandler = (event: ChannelEvent, data: OpenEventData | CloseEventData | CancelEventData | DenyEventData | InvalidEventData, channel: ChannelJSON) => void
§type

IAction

Union type representing all possible action structures
type IAction = IActionWithContract | IActionWithError | IActionWithData | IActionWithProcess | IActionBase
§type

InvalidEventHandler

Type-safe event handler for INVALID events
type InvalidEventHandler = (event: "invalid", data: InvalidEventData, channel: ChannelJSON) => void
§type

LogLevel

Valid log level values in order of verbosity
type LogLevel = "none" | "error" | "warn" | "log" | "info" | "debug"
§type

MessageFilter

Type for a filter function that transforms handlers
type MessageFilter = (handler: MessageHandler<T>) => MessageHandler<T>
§type

MessageHandler

Generic message handler that receives all messages
type MessageHandler = (message: T, channel: ChannelJSON) => void
§type

MessagePredicate

Predicate function to test if a message should be handled
type MessagePredicate = (message: T) => boolean
§type

OpenEventHandler

Type-safe event handler for OPEN events
type OpenEventHandler = (event: "open", data: OpenEventData, channel: ChannelJSON) => void
§type

SecurityChannelFactory

Builds the wire pipeline for one channel.
Structural mirror of network-protocol's createChannel signature.
type SecurityChannelFactory = (label: string, options: SecurityChannelOptions) => SecurityWireChannel
§type

SecurityErrorCode

Codes carried by security-error events and transport error handlers.
The first six are the wire protocol's verdicts on a single frame; the remaining codes describe the transport around the protocol.
  • 'unsupported-version': the frame carries another protocol's version byte
  • 'replayed': the frame's counter is not newer than the last accepted one
  • 'authentication-failed': the frame was not sealed under the session keys
  • 'malformed': the frame or the envelope it carried is not well-formed
  • 'counter-exhausted': the session sealed its last frame
  • 'invalid-session': the session keys cannot be derived
  • 'hello-rejected': a hello arrived that differs from the one keying the session
  • 'security-unconfirmed': the counterpart did not confirm the session before the deadline
  • 'transport-error': a packet could not be sealed or handed to the wire
  • 'unknown': an error without a recognised code
type SecurityErrorCode = "unsupported-version" | "replayed" | "authentication-failed" | "malformed" | "counter-exhausted" | "invalid-session" | "hello-rejected" | "security-unconfirmed" | "transport-error" | "unknown"
§type

SecurityHelloOutcome

What a protocol instance made of a counterpart's hello.
  • 'accepted': the hello keyed the session
  • 'duplicate': the hello repeats the one that keyed the session
  • 'rejected': the hello differs from the one that keyed the session
type SecurityHelloOutcome = "accepted" | "duplicate" | "rejected"
§type

SecurityPolicy

Security policy function type Validates whether a connection request should be allowed
type SecurityPolicy = (event: MessageEvent) => boolean
§type

SecurityProtocolProvider

Creates a SecurityWireProtocol for one session.
Structural mirror of network-protocol's ProtocolProvider shape.
type SecurityProtocolProvider = (send: SecuritySendPacket, receive: SecurityReceivePacket, session: SecuritySession) => SecurityWireProtocol
§type

SecurityProtocolVersion

Security protocol identifiers.
  • 'v3': Ephemeral session keys agreed over the wire; defeats passive listeners
  • 'v4': Ephemeral session keys bound to a pre-shared key; defeats any script without the key
  • 'none': No security, plaintext passthrough
Any other string is accepted so external protocol packages can introduce their own identifiers.
type SecurityProtocolVersion = "none" | "v3" | "v4" | string & { }
§type

SecurityReceivePacket

Callback invoked with each opened inbound packet.
type SecurityReceivePacket = (packet: SecurityPacket) => void
§type

SecuritySendPacket

Callback that transmits a sealed frame over the wire.
type SecuritySendPacket = (frame: Uint8Array) => void
§type

SecuritySessionRole

Which side of the handshake a session endpoint is.
The initiator sent the connection request; the responder accepted it. The roles order the session's key material, so both endpoints must agree.
type SecuritySessionRole = "initiator" | "responder"

●Variables

§const

DEFAULT_CONTRACT

Value: ...
§const

defaultBroker

Value: ...

Browse guides filtered to this packageSuggest a guide