Routing

Purpose

The Routing module provides topic-based message routing across channels, enabling publish-subscribe patterns where channels subscribe to topics and receive messages routed to those topics.


Key Interfaces

RoutedPacket

Base interface for routed packets with topic association.

interface RoutedPacket {
  topicId: string // Topic this packet is routed to
  packet: unknown // The packet content
}

RoutedObfuscatedPacket

Routed packet containing obfuscated data (wire format).

interface RoutedObfuscatedPacket extends RoutedPacket {
  packet: Uint8Array // Obfuscated packet bytes
}

RoutedUnencryptedPacket<T>

Routed packet containing decrypted data (application format).

interface RoutedUnencryptedPacket<T = any> extends RoutedPacket {
  packet: UnencryptedPacket<T> // Decrypted packet
}

RoutingOptions

Configuration for routing behavior.

interface RoutingOptions {
  isDynamic: boolean // Subscription fetching mode
  subscriptions: Subscriptions // Channel-to-topic mappings
}

isDynamic Options:

  • true: Fetches subscriptions anew for each message (dynamic subscriptions)
  • false: Fetches subscriptions once and caches them (static subscriptions)

Subscriptions

WeakMap linking channels to their subscribed topics.

type Subscriptions = WeakMap<Channel, Topic[]>

Router

Function type that configures routing based on available channels and topics.

type Router = (channels: Channel[], topics: Topic[]) => RoutingOptions

Routing Flow


Dynamic vs Static Routing

Static Routing (isDynamic: false)

  • Subscriptions are resolved once when routing is configured
  • More efficient for stable subscription patterns
  • Use when channels don't change subscriptions at runtime
const router: Router = (channels, topics) => {
  const subscriptions = new WeakMap<Channel, Topic[]>()

  // Set up subscriptions once
  const userTopic = topics.find((t) => t.name === 'user-events')
  channels.forEach((channel) => {
    subscriptions.set(channel, [userTopic])
  })

  return {
    isDynamic: false, // Cached subscriptions
    subscriptions,
  }
}

Dynamic Routing (isDynamic: true)

  • Subscriptions are re-evaluated for each message
  • Enables runtime subscription changes
  • Use when channels need to subscribe/unsubscribe dynamically
const router: Router = (channels, topics) => {
  const subscriptions = new WeakMap<Channel, Topic[]>()

  // Subscriptions are evaluated per-message
  // External state can modify subscription patterns

  return {
    isDynamic: true, // Fresh lookup each time
    subscriptions,
  }
}

Usage Example

import { createTopicStore } from '@hyperfrontend/network-protocol/lib/topic'
import { createChannelStore } from '@hyperfrontend/network-protocol/lib/channel'

// Create stores
const topicStore = createTopicStore()
const channelStore = createChannelStore()

// Create topics
topicStore.create('user-events', 'system-events', 'notifications')

// Create channels
const channel1 = channelStore.create('client-1', sendFn, receiveFn, protocolProvider)
const channel2 = channelStore.create('client-2', sendFn, receiveFn, protocolProvider)

// Define router
const router: Router = (channels, topics) => {
  const subscriptions = new WeakMap<Channel, Topic[]>()

  const userEvents = topics.find((t) => t.name === 'user-events')
  const notifications = topics.find((t) => t.name === 'notifications')

  // Channel 1 subscribes to user events and notifications
  subscriptions.set(channel1, [userEvents, notifications])

  // Channel 2 subscribes only to notifications
  subscriptions.set(channel2, [notifications])

  return { isDynamic: false, subscriptions }
}

// Get routing configuration
const routingOptions = router(
  channelStore.list.map((e) => e.channel),
  topicStore.list
)

Relationship to Other Modules


See Also

Related Modules

Module Relationship
topic/ Topics used for subscription
channel/ Channels that receive routed messages
packet/ RoutedPacket types