API Reference
November 30, 2025 · View on GitHub
Complete API documentation for Zeronode.
Node Class
The primary interface for creating network nodes.
Constructor
import { Node } from 'zeronode'
const node = new Node(options)
Parameters:
options(Object)id(string, optional): Node identifier (auto-generated if not provided)options(Object, optional): Node metadata for routingbind(string, optional): Address to auto-bind toconfig(Object, optional): System configuration
Example:
const node = new Node({
id: 'api-server-1',
options: {
role: 'api-server',
region: 'us-east-1',
version: '2.0.0'
},
bind: 'tcp://0.0.0.0:5000',
config: {
PING_INTERVAL: 2000,
CLIENT_GHOST_TIMEOUT: 10000
}
})
Router Class
The Router is a specialized Node subclass designed for service discovery and message forwarding in distributed systems.
Constructor
import { Router } from 'zeronode'
const router = new Router(options)
Parameters: Same as Node constructor (automatically sets options.router = true)
Example:
const router = new Router({
id: 'main-router',
bind: 'tcp://0.0.0.0:8080',
config: {
DEBUG: false
}
})
How Routers Work
When a node cannot find a matching peer locally:
- Node attempts local
requestAny/tickAny - If no match found, checks for connected routers (
router: trueoption) - Forwards request to router via system proxy message
- Router performs its own
requestAny/tickAnyacross its connections - Router returns result back to original requesting node
Architecture:
Client Node → (no local match) → Router → Worker Nodes
↓ ↓
Receives ←──────────────────────────────── Response
Router-Specific Methods
getRoutingStats()
Get routing statistics for monitoring router performance.
Returns: Object - Statistics object
Example:
const stats = router.getRoutingStats()
console.log(stats)
// {
// proxyRequests: { total: 150, successful: 145, failed: 5 },
// proxyTicks: { total: 300 },
// uptime: 3600.5,
// averageResponseTime: 23.4
// }
resetRoutingStats()
Reset routing statistics to zero.
Returns: void
Example:
router.resetRoutingStats()
Router Example
import { Router, Node } from 'zeronode'
// Start router
const router = new Router({
id: 'main-router',
bind: 'tcp://0.0.0.0:8080'
})
// Service node registers with router
const service = new Node({
id: 'auth-service',
options: { role: 'auth' },
bind: 'tcp://0.0.0.0:9000'
})
await service.connect({ address: 'tcp://127.0.0.1:8080' })
service.onRequest('auth:login', async ({ data }) => {
return { token: 'abc123', userId: data.username }
})
// Client node connects to router
const client = new Node({ id: 'api-client' })
await client.connect({ address: 'tcp://127.0.0.1:8080' })
// Client requests auth service through router
const result = await client.requestAny({
event: 'auth:login',
data: { username: 'john', password: 'secret' },
filter: { role: 'auth' }
})
// Router automatically forwards to auth-service and returns response
console.log(result) // { token: 'abc123', userId: 'john' }
See Router-Based Discovery for more details.
Server Methods
bind(address)
Bind server to an address (makes this node accept connections).
Parameters:
address(string): Bind address (e.g.,'tcp://0.0.0.0:5000')
Returns: Promise<void>
Example:
await node.bind('tcp://0.0.0.0:5000')
Supported protocols:
tcp://host:port- TCP transportipc:///path/to/socket- IPC transport (Unix sockets)inproc://name- In-process transport
unbind()
Unbind server (stop accepting connections).
Returns: Promise<void>
Example:
await node.unbind()
getAddress()
Get the current bind address.
Returns: string | null
Example:
const address = node.getAddress()
console.log(`Bound to: ${address}`)
Client Methods
connect(options)
Connect to a remote node.
Parameters:
options(Object)address(string): Remote address (e.g.,'tcp://127.0.0.1:5000')timeout(number, optional): Connection timeout in millisecondsreconnectionTimeout(number, optional): Reconnection timeout
Returns: Promise<Object> - Remote node info { id, options }
Example:
const remote = await node.connect({
address: 'tcp://127.0.0.1:5000',
timeout: 10000
})
console.log(`Connected to: ${remote.id}`)
console.log(`Server options:`, remote.options)
disconnect(peerId)
Disconnect from a specific peer.
Parameters:
peerId(string): Peer node ID
Returns: Promise<void>
Example:
await node.disconnect('server-node-1')
Messaging Methods
request(options)
Send request to specific node, wait for response.
Parameters:
options(Object)to(string): Target node IDevent(string): Event namedata(any): Request datatimeout(number, optional): Request timeout in milliseconds (default: 10000)metadata(Object, optional): Additional routing metadata
Returns: Promise<any> - Response data
Example:
const response = await node.request({
to: 'api-server',
event: 'user:get',
data: { userId: 123 },
timeout: 5000
})
console.log(response) // { id: 123, name: 'John' }
Throws:
NodeErrorwith codeNODE_NOT_FOUNDif peer not foundNodeErrorwith codeREQUEST_TIMEOUTif timeout exceededNodeErrorwith codeROUTING_FAILEDif routing fails
tick(options)
Send one-way message to specific node (no response).
Parameters:
options(Object)to(string): Target node IDevent(string): Event namedata(any): Message datametadata(Object, optional): Additional routing metadata
Returns: void
Example:
node.tick({
to: 'logger-node',
event: 'log:info',
data: { message: 'User logged in', userId: 123 }
})
requestAny(options)
Send request to any node matching filter (automatic load balancing).
Parameters:
options(Object)event(string): Event namedata(any): Request datafilter(Object, optional): Filter criteriapredicate(Function, optional): Custom filter functiondown(boolean, optional): Include downstream peers (default: true)up(boolean, optional): Include upstream peers (default: true)timeout(number, optional): Request timeoutmetadata(Object, optional): Additional routing metadata
Returns: Promise<any> - Response data
Example:
const response = await node.requestAny({
event: 'job:process',
data: { jobId: 456 },
filter: {
role: 'worker',
status: 'idle',
capacity: { $gte: 50 }
},
timeout: 30000
})
Filter operators:
$gte,$lte,$gt,$lt- Comparison$in,$nin- Array membership$regex- Regular expression$contains- String/Array contains$containsAny,$containsNone- Array operations
tickAny(options)
Send one-way message to any node matching filter.
Parameters:
options(Object)event(string): Event namedata(any): Message datafilter(Object, optional): Filter criteriapredicate(Function, optional): Custom filter functiondown(boolean, optional): Include downstream peers (default: true)up(boolean, optional): Include upstream peers (default: true)metadata(Object, optional): Additional routing metadata
Returns: void
Example:
node.tickAny({
event: 'cache:invalidate',
data: { key: 'user:123' },
filter: { role: 'cache' }
})
requestAll(options)
Send request to all nodes matching filter.
Parameters: Same as requestAny
Returns: Promise<Array<{ nodeId, response, error }>> - Results from all peers
Example:
const results = await node.requestAll({
event: 'status:get',
data: {},
filter: { role: 'worker' }
})
results.forEach(({ nodeId, response, error }) => {
if (error) {
console.error(`${nodeId} error:`, error)
} else {
console.log(`${nodeId} status:`, response)
}
})
tickAll(options)
Send one-way message to all nodes matching filter (broadcast).
Parameters: Same as requestAll (without timeout)
Returns: void
Example:
node.tickAll({
event: 'config:reload',
data: { version: '2.0', config: newConfig },
filter: { role: 'worker' }
})
requestDownAny(options)
Send request to any downstream node matching filter.
Parameters: Same as requestAny (automatically sets down: true, up: false)
Returns: Promise<any> - Response data
Example:
// Request only downstream clients
const response = await node.requestDownAny({
event: 'task:process',
data: { taskId: 789 },
filter: { role: 'worker' }
})
requestUpAny(options)
Send request to any upstream node matching filter.
Parameters: Same as requestAny (automatically sets down: false, up: true)
Returns: Promise<any> - Response data
Example:
// Request only upstream servers
const response = await node.requestUpAny({
event: 'auth:verify',
data: { token: 'abc123' },
filter: { role: 'auth-server' }
})
tickDownAny(options)
Send one-way message to any downstream node matching filter.
Parameters: Same as tickAny (automatically sets down: true, up: false)
Returns: void
Example:
node.tickDownAny({
event: 'cache:invalidate',
data: { key: 'user:123' },
filter: { role: 'cache' }
})
tickUpAny(options)
Send one-way message to any upstream node matching filter.
Parameters: Same as tickAny (automatically sets down: false, up: true)
Returns: void
Example:
node.tickUpAny({
event: 'metrics:report',
data: { cpu: 80, memory: 60 },
filter: { role: 'monitor' }
})
tickDownAll(options)
Send one-way message to all downstream nodes matching filter.
Parameters: Same as tickAll (automatically sets down: true, up: false)
Returns: void
Example:
node.tickDownAll({
event: 'config:reload',
data: { newConfig },
filter: { role: 'worker' }
})
tickUpAll(options)
Send one-way message to all upstream nodes matching filter.
Parameters: Same as tickAll (automatically sets down: false, up: true)
Returns: void
Example:
node.tickUpAll({
event: 'health:report',
data: { status: 'healthy', uptime: 3600 },
filter: { role: 'monitor' }
})
Handler Methods
onRequest(pattern, handler)
Register handler for incoming requests.
Parameters:
pattern(string | RegExp): Event pattern to matchhandler(Function): Handler function
Handler signatures:
(envelope, reply)- Auto-continue (2 parameters)(envelope, reply, next)- Manual control (3 parameters)(error, envelope, reply, next)- Error handler (4 parameters)
Returns: void
Example:
// Simple handler
node.onRequest('user:get', async ({ data }) => {
return await database.users.findOne({ id: data.userId })
})
// With reply
node.onRequest('user:get', ({ data }, reply) => {
const user = database.users.findOne({ id: data.userId })
reply(user)
})
// Pattern matching
node.onRequest(/^api:user:/, ({ event, data }, reply) => {
const action = event.split(':')[2] // 'get', 'create', 'update'
switch (action) {
case 'get':
return getUser(data)
case 'create':
return createUser(data)
}
})
// Middleware
node.onRequest(/^api:/, ({ data }, reply, next) => {
if (!data.token) {
return reply.error('Unauthorized')
}
next()
})
onTick(pattern, handler)
Register handler for incoming one-way messages.
Parameters:
pattern(string | RegExp): Event pattern to matchhandler(Function): Handler function
Returns: void
Example:
node.onTick('log:info', ({ data }) => {
console.log(`[INFO] ${data.message}`)
logToDatabase(data)
})
offRequest(pattern, handler)
Unregister request handler.
Parameters:
pattern(string | RegExp): Event patternhandler(Function, optional): Specific handler to remove (if not provided, removes all)
Returns: void
offTick(pattern, handler)
Unregister tick handler.
Parameters: Same as offRequest
Returns: void
Event Methods
on(event, listener)
Register event listener.
Parameters:
event(string): Event name (see Events Reference)listener(Function): Event listener
Returns: void
Example:
import { NodeEvent } from 'zeronode'
node.on(NodeEvent.PEER_JOINED, ({ peerId, direction, peerOptions }) => {
console.log(`Peer ${peerId} joined (${direction})`)
})
node.on(NodeEvent.PEER_LEFT, ({ peerId, direction, reason }) => {
console.log(`Peer ${peerId} left: ${reason}`)
})
node.on(NodeEvent.ERROR, ({ source, error }) => {
console.error(`Error from ${source}:`, error.message)
})
once(event, listener)
Register one-time event listener.
Parameters: Same as on
Returns: void
off(event, listener)
Unregister event listener.
Parameters: Same as on
Returns: void
Info Methods
getId()
Get this node's ID.
Returns: string
Example:
const id = node.getId()
console.log(`My ID: ${id}`)
getOptions()
Get this node's options/metadata.
Returns: Object
Example:
const options = node.getOptions()
console.log(`My options:`, options)
setOptions(options)
Update this node's options/metadata (propagates to connected peers).
Parameters:
options(Object): New options (merged with existing)
Returns: Promise<void>
Example:
// Update status
await node.setOptions({ status: 'busy' })
// Update multiple fields
await node.setOptions({
status: 'ready',
capacity: 80,
lastUpdate: Date.now()
})
getPeers(options)
Get all connected peers with optional filtering by direction.
Parameters:
options(Object, optional)direction(string, optional): Filter by direction ('upstream'or'downstream')
Returns: Array<Object> - Array of peer info objects { id, options, direction }
Example:
// Get all peers
const peers = node.getPeers()
console.log(peers)
// [
// { id: 'server-node-1', options: { role: 'api' }, direction: 'upstream' },
// { id: 'worker-node-2', options: { role: 'worker' }, direction: 'downstream' }
// ]
// Get only downstream peers
const downstreamPeers = node.getPeers({ direction: 'downstream' })
// Get only upstream peers
const upstreamPeers = node.getPeers({ direction: 'upstream' })
getNodesDownstream()
Get IDs of all downstream peers (clients connected to this node).
Returns: Array<string> - Array of peer IDs
Example:
const downstream = node.getNodesDownstream()
console.log(`Downstream peers:`, downstream)
// ['worker-node-1', 'worker-node-2', 'worker-node-3']
getNodesUpstream()
Get IDs of all upstream peers (servers this node is connected to).
Returns: Array<string> - Array of peer IDs
Example:
const upstream = node.getNodesUpstream()
console.log(`Upstream peers:`, upstream)
// ['router-1', 'router-2']
getPeerOptions(peerId)
Get a specific peer's options/metadata.
Parameters:
peerId(string): Peer node ID
Returns: Object | null
Example:
const peerOptions = node.getPeerOptions('worker-node-1')
console.log(`Worker options:`, peerOptions)
// { role: 'worker', status: 'idle', capacity: 100 }
getFilteredNodes(filter)
Get IDs of all nodes matching a filter criteria.
Parameters:
filter(Object): Filter criteria (same format asrequestAnyfilter)
Returns: Array<string> - Array of matching peer IDs
Example:
const workers = node.getFilteredNodes({ role: 'worker', status: 'idle' })
console.log(`Available workers:`, workers)
// ['worker-1', 'worker-3']
getServerIdByAddress(address)
Get the peer ID of a server at a specific address.
Parameters:
address(string): Server address
Returns: string | null - Peer ID or null if not found
Example:
const serverId = node.getServerIdByAddress('tcp://127.0.0.1:5000')
console.log(`Server ID:`, serverId)
// 'router-1'
getLogger()
Get the node's Winston logger instance.
Returns: winston.Logger
Example:
const logger = node.getLogger()
logger.info('Custom log message')
logger.error('Error occurred', { details: errorData })
Lifecycle Methods
close()
Stop the node (unbind server, disconnect all clients, cleanup).
Returns: Promise<void>
Example:
await node.close()
console.log('Node stopped')
Constants
NodeEvent
Node-level events (application layer).
import { NodeEvent } from 'zeronode'
NodeEvent.PEER_JOINED // 'node:peer_joined'
NodeEvent.PEER_LEFT // 'node:peer_left'
NodeEvent.STOPPED // 'node:stopped'
NodeEvent.ERROR // 'node:error'
See Events Reference for complete documentation.
ReconnectPolicy
Auto-reconnection policy for upstream peers.
import { ReconnectPolicy } from 'zeronode'
ReconnectPolicy.ALWAYS // 'always' - Always reconnect (graceful or crash)
ReconnectPolicy.ON_FAILURE // 'on_failure' - Only reconnect on unexpected failures
ReconnectPolicy.DISABLED // 'disabled' - No automatic reconnection
Example:
const node = new Node({
id: 'my-node',
config: {
reconnect: ReconnectPolicy.ALWAYS // Default behavior
}
})
ServerEvent
Server-level events (internal, advanced use).
import { ServerEvent } from 'zeronode'
ServerEvent.READY // 'server:ready'
ServerEvent.NOT_READY // 'server:not_ready'
ServerEvent.CLOSED // 'server:closed'
ServerEvent.CLIENT_JOINED // 'server:client_joined'
ServerEvent.CLIENT_LEFT // 'server:client_left'
ClientEvent
Client-level events (internal, advanced use).
import { ClientEvent } from 'zeronode'
ClientEvent.READY // 'client:ready'
ClientEvent.NOT_READY // 'client:not_ready'
ClientEvent.CLOSED // 'client:closed'
ClientEvent.SERVER_JOINED // 'client:server_joined'
ClientEvent.SERVER_LEFT // 'client:server_left'
ClientEvent.ERROR // 'client:error'
Error Codes
NodeErrorCode
import { NodeErrorCode } from 'zeronode'
NodeErrorCode.NO_NODES_MATCH_FILTER // No peers match routing criteria
NodeErrorCode.ROUTING_FAILED // Message routing failed
NodeErrorCode.NODE_NOT_FOUND // Target node not found
NodeErrorCode.REQUEST_TIMEOUT // Request timed out
Example:
try {
await node.request({ to: 'unknown-node', event: 'ping' })
} catch (err) {
if (err.code === NodeErrorCode.NODE_NOT_FOUND) {
console.log('Peer is offline')
}
}
TypeScript Support
Zeronode includes full TypeScript definitions.
import { Node, NodeEvent, NodeErrorCode } from 'zeronode'
interface UserData {
userId: number
name: string
}
const node = new Node({ id: 'api-server' })
node.onRequest<UserData>('user:get', async ({ data }) => {
const user: UserData = await database.users.findOne({ id: data.userId })
return user
})
const response = await node.request<UserData>({
to: 'api-server',
event: 'user:get',
data: { userId: 123 }
})
console.log(response.name) // TypeScript knows response is UserData
See Also
- Architecture Guide - Deep dive into internals
- Events Reference - All events and lifecycle hooks
- Configuration - All configuration options
- Routing Guide - Smart routing and filtering
- Middleware Guide - Middleware patterns
- Examples - Real-world examples