@hyperfrontend/nexus

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

Architecture Highlights

Nexus uses a functional programming approach with factory functions (createBroker, createChannel) that return handle objects. Internal state is encapsulated via closures, making the system highly testable and avoiding the complexity of class-based inheritance. The routing layer uses a handler registry pattern, allowing protocol actions (REQUEST_CONNECTION, ACCEPT_CONNECTION, etc.) to be processed by dedicated handlers.

For a comprehensive deep dive into the library's internals, see the Architecture Documentation.

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 an encrypted 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: ... }. Both ends attach the security transport before queued messages flush, so product traffic (including sends queued before the handshake) leaves as Uint8Array ciphertext while the handshake actions themselves stay plaintext. Negotiation fails open by default, falling back to plaintext with a warning; 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 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

Core Factory Functions

ExportDescription
createBroker(config)Creates a message broker that manages multiple channels
createChannel(config, deps)Creates a single channel (typically called via broker.addChannel)
mergeContracts(...contracts)Combines multiple contracts into one, deduplicating action types
createSecurityTransport(config)Wraps a security provider's wire pipeline for one channel (the security seam)

Broker Handle

Property/MethodDescription
idUnique broker identifier
nameBroker name
contractCurrent communication contract
channelsList of active channels
addChannel(name, target, settings?)Creates and registers a new channel
getChannel(ref)Retrieves channel by name, id, or window reference
removeChannel(ref)Removes a channel from the broker
setSecurityPolicy(fn)Sets custom origin validation function
extendContract(contract)Extends broker contract (if enabled)
registerProtocol(version, provider)Registers a security provider for negotiation
unregisterProtocol(version)Removes a registered security provider

Channel Handle

Property/MethodDescription
idUnique channel identifier
nameChannel name
isActive()Returns connection status
connect()Initiates connection handshake
disconnect(notify?)Gracefully closes connection
cancel(notify?)Cancels pending connection
destroy(notify?)Forcefully terminates channel
send(type, data)Sends a user message
on(handler)Subscribes to lifecycle events
onMessage(handler)Subscribes to user messages
toJSON()Returns serializable channel state

Lifecycle Events

Events delivered to channel.on(...) subscribers:

EventFired whenPayload
openConnection successfully established (both sides){ origin, contract }
closeGraceful disconnection completed{ notify }
cancelConnection attempt cancelled before completion{ notify }
denyConnection request denied by a handshake gate{ error?, reason?, origin? }
invalidProtocol violation or unexpected-origin drop{ error, action? }
connect-timeoutHandshake deadline expired with no answer{ elapsedMs }
security-readyEncrypted security transport attached & confirmed{ protocol, active }
security-errorSecurity transport operation failed{ message, code, cause? }

Deny Reasons

The deny payload's machine-readable reason (DenyReason, an open union, so a counterpart on a newer protocol can report a reason this build does not know yet):

ReasonMeaning
'invalid-contract'The counterpart's contract failed structural validation
'missing-required-actions'The counterpart does not emit an action this side accepts as required: true
'policy-rejected'The broker's securityPolicy refused the exchange
'incompatible-contract'A contractCompat rule rejected the contract pair
'security-unavailable'A fail-closed channel could not obtain an encrypted transport

Every gate fires deny on the side that decided, so a denying host is never left waiting on a channel it refused. The DENY frame the counterpart receives carries the same error and reason, except for a policy rejection: the refused requester is told only 'Not accepted.', with no reason.

Filter Utilities

ExportDescription
openFilter, closeFilter, cancelFilter, denyFilter, invalidFilterEvent-specific filter creators
byType(type)Message type filter, returns a handler wrapper
compose(...filters)Combines message filters, a message must pass every filter

Types

TypeDescription
IChannelContractContract with accepted and emitted action arrays and optional version
IActionDescriptionAction type definition with optional schema and required flag
ContractCompatChannel-settings rule deciding whether two contracts may interoperate
BrokerHandleBroker instance interface
ChannelHandleChannel instance interface
ChannelEventLifecycle and security event types (see Lifecycle Events above)
DenyReasonMachine-readable denial reason on the deny payload (open union)
IMessageUser message with type and optional data
SecurityProviderSecurity implementation a broker registers for negotiation
SecurityTransportPer-channel encrypted transport attached after negotiation

Compatibility

PlatformSupport
Browser
Node.js

Output Formats

FormatFileTree-Shakeable
ESMindex.esm.js
CJSindex.cjs.js
IIFEbundle/index.iife.min.js
UMDbundle/index.umd.min.js

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

PackageType
@hyperfrontend/network-protocolOptional

Part of hyperfrontend

This library is part of the hyperfrontend monorepo.

📖 Full documentation

License

MIT

Guides & tutorials for @hyperfrontend/nexus

Browse them filtered to this packageSuggest a guide

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
string
The 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
CancelEventHandler
Handler 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
CloseEventHandler
Handler 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
CreateBrokerConfig
Broker 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
IChannelConfig
Channel configuration (name, target, settings)
§deps
ChannelDependencies
Dependencies (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
ChannelEvent
The 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
NexusLoggerOptions
Logger 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
encryption pipeline

Parameters

NameTypeDescription
§config
SecurityTransportConfig
Transport 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/v2'

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

denyFilter(handler: DenyEventHandler): EventHandler

Creates a filter that only passes DENY events to the handler

Parameters

NameTypeDescription
§handler
DenyEventHandler
Handler 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
InvalidEventHandler
Handler 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
Logger
Logger instance
§action
IAction
Action 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
Logger
Logger instance to use
§event
ChannelEvent
Type of channel event that occurred
§data
unknown
Additional 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
OpenEventHandler
Handler 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:string
Unique broker identifier
§readonly name:string
Broker name
§readonly settings:BrokerSettings
Broker settings
§interface

BrokerHandle

Broker handle returned by factory

Properties

§readonly acceptedActionTypes:unknown
Action types accepted by this broker
§readonly channels:unknown
List of registered channels
§readonly contract:IChannelContract
Channel contract for messaging
§readonly id:string
Unique broker identifier
§readonly logger:Logger
Get the broker's logger instance.
§readonly name:string
Broker name
§readonly settings:BrokerSettings
Broker configuration settings
§interface

BrokerSettings

Broker settings configuration

Properties

§readonly blacklist?:unknown
List of blocked origins
§readonly contract:IChannelContract
Default contract for all channels
§readonly contractExtension?:boolean
Allow contract extension
§readonly logger?:Logger
Custom logger instance to use
§readonly logLevel?:LogLevel
Minimum log level to emit (default: 'error')
§readonly security?:BrokerSecurityConfig
Security configuration for protocol negotiation and encryption
§readonly securityPolicy?:SecurityPolicy
Custom security validation function
§readonly whitelist?:unknown
List of allowed origins (takes precedence over blacklist)
§interface

BrokerState

Internal broker state

Properties

§readonly contract:IChannelContract
Channel contract for messaging
§readonly id:string
Unique broker identifier
§readonly logger:Logger
Logger instance for debugging
§readonly name:string
Broker name
§readonly settings:BrokerSettings
Broker configuration settings
§readonly window:Window
Window context for the broker
§interface

CancelEventData

Data payload for CANCEL event

Properties

§notify:boolean
Whether remote end was notified
§interface

ChannelHandle

Channel handle returned by createChannel factory. Provides methods for interacting with the channel.

Properties

§readonly id:string
Channel unique identifier (for registry compatibility)
§readonly name:string
Channel name (for registry compatibility)
§readonly target:Window
Target window (for registry compatibility)
§interface

ChannelJSON

Safe serializable representation of a channel for callbacks. Contains only data, no methods or internal references.

Properties

§active:boolean
Whether channel is active
§connectTimestamp:number
When channel connected
§contract:IChannelContract
Channel contract
§id:string
Channel unique identifier
§name:string
Channel name
§origin:string
Origin of connected channel
§peerContract:IChannelContract
Contract declared by the connected counterpart
§peerId:string
Broker id of the connected counterpart
§queuedMessagesCount:number
Number of queued messages
§interface

CloseEventData

Data payload for CLOSE event

Properties

§notify:boolean
Whether remote end was notified
§reason?:"peer-reload"
Why the session ended, when neither side asked for the close
§interface

ContractCompatible

Compatible outcome of a contract-compatibility check.

Properties

§compatible:true
Discriminant marking the pair compatible.
§interface

ContractIncompatible

Incompatible outcome of a contract-compatibility check: the connection is denied before it opens.

Properties

§compatible:false
Discriminant marking the pair incompatible.
§reason:string
Human-readable reason delivered with the connection denial.
§interface

DenyEventData

Data payload for DENY event

Properties

§error?:string
Human-readable error explaining the denial
§origin?:string
Origin of the counterpart that denied the connection
§reason?:DenyReason
Machine-readable denial reason
§interface

IActionDescription

Describes an action that can be sent or received on a channel

Properties

§description?:string
Human-readable description of the action
§required?:boolean
Marks 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?:object
JSON schema for validating action payload
§type:string
Unique identifier for the action type
§interface

IChannelConfig

Configuration for creating a new channel

Properties

§name:string
Channel identifier/name
§settings?:IChannelSettings
Channel behavior settings
§target:Window
Target 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?:string
Optional 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?:boolean
Whether the channel is managed by a broker
§closeTimeoutMs?:number
Milliseconds a polite close waits for the counterpart's acknowledgement before closing anyway (default: 2000)
§connectTimeoutMs?:number
Milliseconds a connection attempt may remain unanswered before firing 'connect-timeout' (default: 10000)
§contract?:IChannelContract
Expected channel contract (if not set, inherited from broker)
§contractCompat?:ContractCompat
Rule deciding whether the local and counterpart contracts may interoperate; an incompatible pair is denied during the handshake
§logger?:Logger
Custom logger instance to use
§logLevel?:LogLevel
Minimum log level to emit (default: 'error')
§origin?:string
Expected origin ('*' for any, or specific URL)
§queueMessages?:boolean
Queue messages when channel is not yet active
§requestRetryMs?:number
Milliseconds between handshake re-sends while a connection attempt is pending (default: 500)
§security?:ChannelSecuritySettings
Security 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?:unknown
Optional payload data (must be serializable via postMessage)
§timestamp?:number
Optional timestamp for when message was created
§type:string
Message type identifier (e.g., 'user-logged-in', 'data-updated')
§interface

InvalidEventData

Data payload for INVALID event

Properties

§action?:IAction
The invalid action that was received (if available)
§error:string
Error message describing what was invalid
§interface

Logger

Logger interface with level-specific methods and level control

Properties

§channel:ChannelFn
Returns a sub-logger that prepends [prefix] to every message.
§debug:DebugLevelFn
Debug-level output
§error:ErrorLevelFn
Error-level output
§getLogLevel:GetLogLevel
Gets the current log level
§info:InfoLevelFn
Info-level output
§log:LogLevelFn
Standard log output
§setLogLevel:SetLogLevel
Sets the current log level
§timed:TimedFn
Wraps a sync call with timing. Logs completion or failure with elapsed ms.
§timedAsync:TimedAsyncFn
Wraps a promise-returning call with timing. Dumps stack trace on error to debug log.
§warn:WarnLevelFn
Warning-level output
§interface

MessageEnvelope

Internal message envelope for routing and tracking. Wraps user messages with metadata for internal use.

Properties

§channelId:string
ID of the channel handling this message
§direction:"inbound" | "outbound"
Direction of message flow
§message:IMessage
The user message being transmitted
§interface

NexusLoggerOptions

Options for creating a nexus logger.

Properties

§readonly customLogger?:Logger
Custom logger instance to use instead of creating one
§readonly level?:LogLevel
Minimum log level to emit (default: 'error')
§readonly prefix?:string
Prefix for log messages (default: '[nexus]')
§interface

OpenEventData

Data payload for OPEN event

Properties

§contract:IChannelContract
Negotiated channel contract
§origin:string
Origin of the connected channel
§interface

SecurityEncryptedPacket

A packet whose data has been encrypted to binary form.

Properties

§readonly data:Uint8Array
Encrypted data bytes
§readonly origin:string
UUID of the packet sender
§readonly target:string
UUID of the intended recipient
§interface

SecurityPacket

A decrypted packet delivered by the wire pipeline.

Properties

§readonly data:SecurityPacketData
Decrypted data envelope; the transported action lives at data.message
§readonly origin:string
UUID of the packet sender
§readonly target:string
UUID of the intended recipient
§interface

SecurityPacketData

Data envelope carried inside each wire packet.
The transported nexus action lives at SecurityPacketData.message; the remaining fields are wire-protocol bookkeeping.

Properties

§readonly id:string
UUID identifying this message
§readonly key:string
Key offered for encrypting subsequent traffic (empty to keep the base key)
§readonly message:unknown
The transported message payload
§readonly pid:string
UUID identifying the sending process
§readonly schema:Schema
JSON schema describing the message
§readonly schemaHash:string
SHA-256 hash of the serialized schema
§readonly sequence:number
Counter incremented for each message of the sending process
§interface

SecurityProvider

Everything nexus needs from a security implementation to run one channel's envelope. This is the boundary a security package implements: network-protocol's createChannel and a protocol provider satisfy it directly.

Properties

§readonly createChannel:SecurityChannelFactory
Builds the per-channel wire pipeline
§readonly protocolProvider:SecurityProtocolProvider
Creates the protocol instance driving the pipeline
§interface

SecuritySerializedPacket

A packet whose encrypted data has been serialized to a string.

Properties

§readonly data:string
Serialized encrypted data
§readonly origin:string
UUID of the packet sender
§readonly target:string
UUID of the intended recipient
§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 getOrigin:() => string
Returns the origin currently pinned to the channel, or null before pinning
§readonly label:string
Human-readable label for the wire pipeline, surfaced in protocol diagnostics
§readonly onAction:(action: unknown) => void
Receives each action delivered by the transport
§readonly onError?:(error: SecurityTransportError) => void
Optional handler for transport failures (e.g., unencryptable payloads)
§readonly originId:string
UUID identifying the local endpoint, stamped as each packet's origin
§readonly protocol:SecurityProtocolVersion
Security protocol to use
§readonly provider?:SecurityProvider
Security implementation building the wire pipeline (required for protocols other than 'none')
§readonly target:Window
Counterpart window that receives outbound traffic
§readonly targetId:string
UUID identifying the counterpart endpoint, stamped as each packet's target
§interface

SecurityTransportError

Error payload delivered to a security transport's onError handler.

Properties

§cause?:Error
Optional underlying cause
§code:string
Machine-readable error code
§message:string
Human-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 label:string
Human-readable pipeline label
§readonly receive:(packet: Uint8Array) => void
Feeds raw wire bytes into the decryption pipeline
§readonly resume:() => void
Resumes packet processing
§readonly send:(origin: string, target: string, data: SecurityPacketData) => void
Encrypts and transmits a data envelope from origin to target
§readonly stop:() => void
Pauses packet processing
§interface

SecurityWireProtocol

Wire-protocol instance driving one channel's encryption pipeline.
Structural mirror of network-protocol's Protocol shape.

Properties

§readonly getLogger:() => Logger
Returns the logger used by the protocol
§readonly packetDecryption:(packet: SecurityEncryptedPacket) => Promise<SecurityPacket>
Decrypts a packet's data envelope
§readonly packetDeobfuscation:(packet: Uint8Array) => Promise<SecuritySerializedPacket>
Deobfuscates wire bytes into a serialized packet
§readonly packetEncryption:(packet: SecurityPacket) => Promise<SecurityEncryptedPacket>
Encrypts a packet's data envelope
§readonly packetObfuscation:(packet: SecuritySerializedPacket) => Promise<Uint8Array<ArrayBufferLike>>
Obfuscates a serialized packet into wire bytes
§readonly receive:SecurityReceivePacket
Receives fully decrypted packets
§readonly send:SecuritySendPacket
Transmits fully processed wire bytes

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-negotiated" | "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.
type CloseReason = "peer-reload"
§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-negotiated", SecurityNegotiatedEventData> | 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, sendPacket: SecuritySendPacket, receivePacket: SecurityReceivePacket, protocolProvider: SecurityProtocolProvider) => SecurityWireChannel
§type

SecurityPolicy

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

SecurityProtocolProvider

Creates a SecurityWireProtocol bound to the given packet callbacks.
Structural mirror of network-protocol's ProtocolProvider shape.
type SecurityProtocolProvider = (sendPacket: SecuritySendPacket, receivePacket: SecurityReceivePacket) => SecurityWireProtocol
§type

SecurityProtocolVersion

Security protocol identifiers.
  • 'v1': Time-interval obfuscation; peers remain on the protocol's base key
  • 'v2': Pre-shared key (PSK) handshake; encrypted from the first message
  • 'none': No security, plaintext passthrough
Any other string is accepted so external protocol packages can introduce their own identifiers.
type SecurityProtocolVersion = "none" | "v1" | "v2" | string & { }
§type

SecurityReceivePacket

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

SecuritySendPacket

Callback that transmits obfuscated ciphertext bytes over the wire.
type SecuritySendPacket = (packet: Uint8Array) => void

Variables

§constDEFAULT_CONTRACT
Value: ...
§constdefaultBroker
Value: ...

Related