Files
suaveplan/docs/old-network-planning/PHASE_0_IMPLEMENTATION_PLAN.md
2026-05-27 23:29:53 +01:00

28 KiB

Network Library Phase 0 Implementation Plan

This document outlines the implementation plan for Phase 0 of the network library, focusing on core components and event system integration.

Implementation Goals

  1. Create utils directory with @suaveplan/events integration
  2. Implement core NetworkNode methods
  3. Implement NetworkSystem core methods
  4. Add API versioning infrastructure
  5. Establish testing patterns

Architectural Overview

Phase 0 will establish the foundation for the modular network library. The core components and their relationships are illustrated in the following diagram:

classDiagram
    class EventEmitter {
        <<@suaveplan/events>>
        +on(event, listener, context?)
        +once(event, listener, context?)
        +off(event, listener, context?)
        +emit(event, ...args)
    }
    
    class NetworkEventEmitter {
        -_emitter: EventEmitter
        +on(event, listener, context?)
        +once(event, listener, context?)
        +off(event, listener, context?)
        +emit(event, ...args)
        +onNodeConnected(handler)
        +onNodeDisconnected(handler)
        +onMessageSent(handler)
    }
    
    class NetworkNode {
        -_id: string
        -_level: number
        -_parent: NetworkNode | null
        -_children: Map~string, NetworkNode~
        -_siblings: Map~string, NetworkNode~
        -_events: NetworkEventEmitter
        +connect()
        +disconnect()
        +addChild(node)
        +removeChild(nodeId)
        +sendMessage(message)
    }
    
    class NetworkSystem {
        -_nodes: Map~string, NetworkNode~
        -_config: NetworkSystemConfig
        -_events: NetworkEventEmitter
        +createNode(id, capabilities)
        +getNode(id)
        +removeNode(id)
        +placeNodeInHierarchy(node)
    }
    
    class VersionInfo {
        +major: number
        +minor: number
        +patch: number
        +isCompatibleWith(version)
    }
    
    class IPlugin {
        <<interface>>
        +id: string
        +onRegister(entity)
        +onUnregister(entity)
    }
    
    class PluginRegistry {
        -_plugins: Map~string, IPlugin~
        +register(plugin)
        +unregister(pluginId)
        +getPlugin(pluginId)
    }
    
    NetworkNode --> NetworkEventEmitter : uses
    NetworkSystem --> NetworkEventEmitter : uses
    NetworkSystem --> NetworkNode : manages
    NetworkNode --> PluginRegistry : has
    NetworkEventEmitter --> EventEmitter : wraps
    NetworkNode ..> IPlugin : supports
    PluginRegistry o-- IPlugin : contains

Implementation Steps

1. Create Utils Directory with Event Integration

1.1 Create Event Constants

File: src/utils/event-constants.ts

/**
 * Standard event names used throughout the network library
 */
export enum NetworkEvents {
  // Node lifecycle events
  NODE_CREATED = 'node:created',
  NODE_CONNECTED = 'node:connected',
  NODE_DISCONNECTED = 'node:disconnected',
  NODE_UPDATED = 'node:updated',
  NODE_REMOVED = 'node:removed',
  
  // Message events
  MESSAGE_SENT = 'message:sent',
  MESSAGE_RECEIVED = 'message:received',
  MESSAGE_ROUTED = 'message:routed',
  MESSAGE_DROPPED = 'message:dropped',
  
  // Hierarchy events
  HIERARCHY_CHANGED = 'hierarchy:changed',
  PARENT_CHANGED = 'hierarchy:parent-changed',
  CHILD_ADDED = 'hierarchy:child-added',
  CHILD_REMOVED = 'hierarchy:child-removed',
  SIBLING_ADDED = 'hierarchy:sibling-added',
  SIBLING_REMOVED = 'hierarchy:sibling-removed',
  LEVEL_CHANGED = 'hierarchy:level-changed',
  
  // Plugin events
  PLUGIN_REGISTERED = 'plugin:registered',
  PLUGIN_UNREGISTERED = 'plugin:unregistered',
  
  // System events
  SYSTEM_ERROR = 'system:error',
  SYSTEM_WARNING = 'system:warning',
  SYSTEM_INFO = 'system:info'
}

1.2 Create Network Event Emitter

File: src/utils/network-event-emitter.ts

import { EventEmitter } from '@suaveplan/events';
import { NetworkEvents } from './event-constants';

/**
 * NetworkEventEmitter provides a standardized event handling system for the network library.
 * It wraps the @suaveplan/events EventEmitter with network-specific features.
 */
export class NetworkEventEmitter {
  private _emitter: EventEmitter;
  
  constructor(emitter?: EventEmitter) {
    this._emitter = emitter || new EventEmitter();
  }
  
  /**
   * Registers a listener for the specified event
   */
  on(event: string, listener: Function, context?: any): this {
    this._emitter.on(event, listener, context);
    return this;
  }
  
  /**
   * Registers a one-time listener for the specified event
   */
  once(event: string, listener: Function, context?: any): this {
    this._emitter.once(event, listener, context);
    return this;
  }
  
  /**
   * Removes a listener for the specified event
   */
  off(event: string, listener?: Function, context?: any): this {
    this._emitter.off(event, listener, context);
    return this;
  }
  
  /**
   * Emits an event with the provided arguments
   */
  emit(event: string, ...args: any[]): boolean {
    return this._emitter.emit(event, ...args);
  }
  
  /**
   * Returns all registered event names
   */
  eventNames(): string[] {
    return this._emitter.eventNames();
  }
  
  /**
   * Returns the number of listeners for a given event
   */
  listenerCount(event: string): number {
    return this._emitter.listenerCount(event);
  }
  
  // Convenience methods for common events
  
  /**
   * Registers a listener for the NODE_CONNECTED event
   */
  onNodeConnected(listener: Function, context?: any): this {
    return this.on(NetworkEvents.NODE_CONNECTED, listener, context);
  }
  
  /**
   * Registers a listener for the NODE_DISCONNECTED event
   */
  onNodeDisconnected(listener: Function, context?: any): this {
    return this.on(NetworkEvents.NODE_DISCONNECTED, listener, context);
  }
  
  /**
   * Registers a listener for the MESSAGE_SENT event
   */
  onMessageSent(listener: Function, context?: any): this {
    return this.on(NetworkEvents.MESSAGE_SENT, listener, context);
  }
  
  /**
   * Registers a listener for the MESSAGE_RECEIVED event
   */
  onMessageReceived(listener: Function, context?: any): this {
    return this.on(NetworkEvents.MESSAGE_RECEIVED, listener, context);
  }
}

1.3 Create Utils Index

File: src/utils/index.ts

export * from './event-constants';
export * from './network-event-emitter';

2. Update Types for Event System Integration

File: src/types.ts (additions)

// Add these interfaces to the existing types.ts file

/**
 * Interface for event emitters, matching the core functionality of @suaveplan/events
 */
export interface IEventEmitter {
  on(event: string, listener: Function, context?: any): any;
  once(event: string, listener: Function, context?: any): any;
  off(event: string, listener?: Function, context?: any): any;
  emit(event: string, ...args: any[]): boolean;
  eventNames?(): string[];
  listenerCount?(event: string): number;
}

/**
 * Interface for NetworkEventEmitter, extending the base IEventEmitter
 */
export interface INetworkEventEmitter extends IEventEmitter {
  onNodeConnected(listener: Function, context?: any): any;
  onNodeDisconnected(listener: Function, context?: any): any;
  onMessageSent(listener: Function, context?: any): any;
  onMessageReceived(listener: Function, context?: any): any;
}

// Add to NodeState enum if it doesn't already exist
export enum NodeState {
  CREATED = 'created',
  CONNECTING = 'connecting',
  CONNECTED = 'connected',
  DISCONNECTING = 'disconnecting',
  DISCONNECTED = 'disconnected',
  ERROR = 'error'
}

// Add API version interface
export interface APIVersion {
  major: number;
  minor: number;
  patch: number;
}

3. Implement Basic Plugin System Interfaces

File: src/plugins/plugin-registry.ts

import { IPlugin } from '../types';

/**
 * PluginRegistry manages the registration and lifecycle of plugins.
 */
export class PluginRegistry {
  private _plugins: Map<string, IPlugin>;
  private _entity: any; // The entity (node or system) this registry belongs to
  
  constructor(entity: any) {
    this._plugins = new Map();
    this._entity = entity;
  }
  
  /**
   * Registers a plugin with the entity
   */
  register(plugin: IPlugin): boolean {
    if (this._plugins.has(plugin.id)) {
      return false;
    }
    
    this._plugins.set(plugin.id, plugin);
    plugin.onRegister(this._entity);
    return true;
  }
  
  /**
   * Unregisters a plugin from the entity
   */
  unregister(pluginId: string): boolean {
    const plugin = this._plugins.get(pluginId);
    if (!plugin) {
      return false;
    }
    
    plugin.onUnregister(this._entity);
    this._plugins.delete(pluginId);
    return true;
  }
  
  /**
   * Returns a plugin by ID
   */
  getPlugin<T extends IPlugin>(pluginId: string): T | undefined {
    return this._plugins.get(pluginId) as T | undefined;
  }
  
  /**
   * Checks if a plugin is registered
   */
  hasPlugin(pluginId: string): boolean {
    return this._plugins.has(pluginId);
  }
  
  /**
   * Returns all registered plugins
   */
  getAllPlugins(): IPlugin[] {
    return Array.from(this._plugins.values());
  }
}

4. Implement API Versioning Infrastructure

4.1 Create Version Info Class

File: src/versioning/version-info.ts

import { APIVersion } from '../types';

/**
 * VersionInfo represents a semantic version and provides
 * compatibility checking functionality.
 */
export class VersionInfo implements APIVersion {
  readonly major: number;
  readonly minor: number;
  readonly patch: number;
  
  constructor(major: number, minor: number, patch: number) {
    this.major = major;
    this.minor = minor;
    this.patch = patch;
  }
  
  /**
   * Creates a VersionInfo from a version string (e.g., "1.2.3")
   */
  static fromString(version: string): VersionInfo {
    const parts = version.split('.').map(p => parseInt(p, 10));
    return new VersionInfo(
      parts[0] || 0,
      parts[1] || 0,
      parts[2] || 0
    );
  }
  
  /**
   * Converts the version to a string representation
   */
  toString(): string {
    return `${this.major}.${this.minor}.${this.patch}`;
  }
  
  /**
   * Checks if this version is compatible with another version
   * Compatible means same major version and minor version >= required
   */
  isCompatibleWith(other: VersionInfo): boolean {
    // Major version must match for compatibility
    if (this.major !== other.major) {
      return false;
    }
    
    // Minor version must be >= the required version
    return this.minor >= other.minor;
  }
  
  /**
   * Checks if this version is newer than another version
   */
  isNewerThan(other: VersionInfo): boolean {
    if (this.major > other.major) return true;
    if (this.major < other.major) return false;
    
    if (this.minor > other.minor) return true;
    if (this.minor < other.minor) return false;
    
    return this.patch > other.patch;
  }
}

4.2 Create Version Manager

File: src/versioning/version-manager.ts

import { VersionInfo } from './version-info';

/**
 * VersionManager handles API versioning and compatibility checking
 */
export class VersionManager {
  static readonly CURRENT_VERSION = new VersionInfo(0, 1, 0);
  
  /**
   * Checks if a version is compatible with the current library version
   */
  static isCompatible(version: VersionInfo): boolean {
    return VersionManager.CURRENT_VERSION.isCompatibleWith(version);
  }
  
  /**
   * Returns a list of versions between from and to (inclusive)
   * This can be used for migration paths
   */
  static getMigrationPath(fromVersion: VersionInfo, toVersion: VersionInfo): VersionInfo[] {
    const result: VersionInfo[] = [];
    
    // If versions are incompatible (different major), return empty path
    if (fromVersion.major !== toVersion.major) {
      return result;
    }
    
    // Add all minor versions between from and to
    for (let minor = fromVersion.minor; minor <= toVersion.minor; minor++) {
      result.push(new VersionInfo(fromVersion.major, minor, 0));
    }
    
    return result;
  }
  
  /**
   * Returns the stability classification for the current version
   */
  static getStabilityClassification(): 'experimental' | 'stable' | 'deprecated' {
    // Phase 0 is experimental
    return 'experimental';
  }
}

4.3 Create Versioning Index

File: src/versioning/index.ts

export * from './version-info';
export * from './version-manager';

5. Implement Core NetworkNode Methods

File: src/node/node.ts (update)

import {
  NodeState,
  NodeCapabilities,
  NodePerformance,
  NetworkMessage,
  MessagePriority,
  LevelConfig,
  MessageRoutingConfig,
  NetworkSystemConfig,
  INetworkEventEmitter
} from '../types';
import { NetworkEventEmitter, NetworkEvents } from '../utils';
import { PluginRegistry } from '../plugins/plugin-registry';
import { IPlugin } from '../types';

export class NetworkNode {
  private _id: string;
  private _state: NodeState = NodeState.CREATED;
  private _level: number;
  private _parent: NetworkNode | null = null;
  private _children: Map<string, NetworkNode> = new Map();
  private _siblings: Map<string, NetworkNode> = new Map();
  private _capabilities: NodeCapabilities;
  private _events: INetworkEventEmitter;
  private _plugins: PluginRegistry;
  
  constructor(
    id: string,
    level: number,
    capabilities: NodeCapabilities,
    eventEmitter?: INetworkEventEmitter
  ) {
    this._id = id;
    this._level = level;
    this._capabilities = capabilities;
    this._events = eventEmitter || new NetworkEventEmitter();
    this._plugins = new PluginRegistry(this);
    
    // Emit node created event
    this._events.emit(NetworkEvents.NODE_CREATED, this);
  }
  
  /**
   * Returns the node's ID
   */
  get id(): string {
    return this._id;
  }
  
  /**
   * Returns the node's hierarchy level
   */
  get level(): number {
    return this._level;
  }
  
  /**
   * Returns the node's parent node, or null if it has no parent
   */
  get parent(): NetworkNode | null {
    return this._parent;
  }
  
  /**
   * Returns the node's children as an array
   */
  get children(): NetworkNode[] {
    return Array.from(this._children.values());
  }
  
  /**
   * Returns the node's siblings as an array
   */
  get siblings(): NetworkNode[] {
    return Array.from(this._siblings.values());
  }
  
  /**
   * Returns the node's capabilities
   */
  get capabilities(): NodeCapabilities {
    return this._capabilities;
  }
  
  /**
   * Returns the node's current state
   */
  get state(): NodeState {
    return this._state;
  }
  
  /**
   * Returns the number of children
   */
  get childCount(): number {
    return this._children.size;
  }
  
  /**
   * Connects the node to the network
   */
  connect(): boolean {
    if (this._state !== NodeState.CREATED && this._state !== NodeState.DISCONNECTED) {
      return false;
    }
    
    this._state = NodeState.CONNECTING;
    this._events.emit(NetworkEvents.NODE_UPDATED, this);
    
    // Simulate successful connection for Phase 0
    this._state = NodeState.CONNECTED;
    this._events.emit(NetworkEvents.NODE_CONNECTED, this);
    
    return true;
  }
  
  /**
   * Disconnects the node from the network
   */
  disconnect(): boolean {
    if (this._state !== NodeState.CONNECTED && this._state !== NodeState.CONNECTING) {
      return false;
    }
    
    this._state = NodeState.DISCONNECTING;
    this._events.emit(NetworkEvents.NODE_UPDATED, this);
    
    // Simulate successful disconnection for Phase 0
    this._state = NodeState.DISCONNECTED;
    this._events.emit(NetworkEvents.NODE_DISCONNECTED, this);
    
    return true;
  }
  
  /**
   * Checks if the node can accept more children
   */
  canAcceptChildren(): boolean {
    // For Phase 0, just check if level > 0 (clients can't have children)
    return this._level > 0;
  }
  
  /**
   * Adds a child node to this node
   */
  addChild(node: NetworkNode): boolean {
    if (!this.canAcceptChildren() || this._children.has(node.id) || node.id === this._id) {
      return false;
    }
    
    // Remove from previous parent if exists
    if (node.parent) {
      node.parent.removeChild(node.id);
    }
    
    // Add as child
    this._children.set(node.id, node);
    this._setParentForNode(node);
    
    // Emit events
    this._events.emit(NetworkEvents.CHILD_ADDED, this, node);
    this._events.emit(NetworkEvents.HIERARCHY_CHANGED, this);
    
    return true;
  }
  
  /**
   * Removes a child node from this node
   */
  removeChild(nodeId: string): boolean {
    const node = this._children.get(nodeId);
    if (!node) {
      return false;
    }
    
    // Remove child reference
    this._children.delete(nodeId);
    
    // Clear parent reference
    this._clearParentForNode(node);
    
    // Emit events
    this._events.emit(NetworkEvents.CHILD_REMOVED, this, node);
    this._events.emit(NetworkEvents.HIERARCHY_CHANGED, this);
    
    return true;
  }
  
  /**
   * Adds a sibling node to this node
   */
  addSibling(node: NetworkNode): boolean {
    if (node.id === this._id || this._siblings.has(node.id)) {
      return false;
    }
    
    // Add sibling relationship (bidirectional)
    this._siblings.set(node.id, node);
    node._siblings.set(this._id, this);
    
    // Emit events
    this._events.emit(NetworkEvents.SIBLING_ADDED, this, node);
    this._events.emit(NetworkEvents.HIERARCHY_CHANGED, this);
    
    return true;
  }
  
  /**
   * Removes a sibling node from this node
   */
  removeSibling(nodeId: string): boolean {
    const node = this._siblings.get(nodeId);
    if (!node) {
      return false;
    }
    
    // Remove sibling relationship (bidirectional)
    this._siblings.delete(nodeId);
    node._siblings.delete(this._id);
    
    // Emit events
    this._events.emit(NetworkEvents.SIBLING_REMOVED, this, node);
    this._events.emit(NetworkEvents.HIERARCHY_CHANGED, this);
    
    return true;
  }
  
  /**
   * Sends a message from this node
   * Phase 0 implementation just emits an event
   */
  async sendMessage(message: NetworkMessage): Promise<void> {
    // For Phase 0, just emit the event
    this._events.emit(NetworkEvents.MESSAGE_SENT, message, this);
  }
  
  /**
   * Updates the node's level
   */
  updateLevel(newLevel: number): boolean {
    if (newLevel === this._level) {
      return false;
    }
    
    const oldLevel = this._level;
    this._level = newLevel;
    
    // Emit events
    this._events.emit(NetworkEvents.LEVEL_CHANGED, this, oldLevel, newLevel);
    this._events.emit(NetworkEvents.NODE_UPDATED, this);
    
    return true;
  }
  
  /**
   * Registers a plugin with this node
   */
  registerPlugin(plugin: IPlugin): boolean {
    const result = this._plugins.register(plugin);
    if (result) {
      this._events.emit(NetworkEvents.PLUGIN_REGISTERED, this, plugin);
    }
    return result;
  }
  
  /**
   * Removes a plugin from this node
   */
  removePlugin(pluginId: string): boolean {
    const plugin = this._plugins.getPlugin(pluginId);
    const result = this._plugins.unregister(pluginId);
    if (result && plugin) {
      this._events.emit(NetworkEvents.PLUGIN_UNREGISTERED, this, plugin);
    }
    return result;
  }
  
  /**
   * Gets a plugin by ID
   */
  getPlugin<T extends IPlugin>(pluginId: string): T | undefined {
    return this._plugins.getPlugin<T>(pluginId);
  }
  
  /**
   * Sets the parent for a node
   */
  private _setParentForNode(node: NetworkNode): void {
    node._parent = this;
    node._events.emit(NetworkEvents.PARENT_CHANGED, node, null, this);
  }
  
  /**
   * Clears the parent for a node
   */
  private _clearParentForNode(node: NetworkNode): void {
    const oldParent = node._parent;
    node._parent = null;
    node._events.emit(NetworkEvents.PARENT_CHANGED, node, oldParent, null);
  }
}

6. Implement NetworkSystem Core Methods

File: src/network/network.ts (update)

import { NetworkSystemConfig, NodeCapabilities, INetworkEventEmitter, NodeState } from '../types';
import { NetworkNode } from '../node/node';
import { NetworkEventEmitter, NetworkEvents } from '../utils';
import { PluginRegistry } from '../plugins/plugin-registry';
import { IPlugin } from '../types';
import { VersionManager } from '../versioning';

export class NetworkSystem {
  private _nodes: Map<string, NetworkNode> = new Map();
  private _config: NetworkSystemConfig;
  private _events: INetworkEventEmitter;
  private _plugins: PluginRegistry;
  
  constructor(config: Partial<NetworkSystemConfig> = {}, eventEmitter?: INetworkEventEmitter) {
    this._config = this._createDefaultConfig(config);
    this._events = eventEmitter || new NetworkEventEmitter();
    this._plugins = new PluginRegistry(this);
  }
  
  /**
   * Creates a new node and adds it to the system
   */
  createNode(
    id: string,
    capabilities: NodeCapabilities
  ): NetworkNode {
    // Determine initial level based on capabilities
    const level = this._determineInitialLevel(capabilities);
    
    // Create the node
    const node = new NetworkNode(id, level, capabilities, this._events);
    
    // Add to nodes map
    this._nodes.set(id, node);
    
    // Setup event handlers
    this._setupNodeEventHandlers(node);
    
    // Emit event
    this._events.emit(NetworkEvents.NODE_CREATED, node);
    
    return node;
  }
  
  /**
   * Gets a node by ID
   */
  getNode(id: string): NetworkNode | undefined {
    return this._nodes.get(id);
  }
  
  /**
   * Removes a node from the system
   */
  removeNode(id: string): boolean {
    const node = this._nodes.get(id);
    if (!node) {
      return false;
    }
    
    // Disconnect the node if connected
    if (node.state === NodeState.CONNECTED) {
      node.disconnect();
    }
    
    // Remove parent-child relationships
    if (node.parent) {
      node.parent.removeChild(node.id);
    }
    
    // Remove child-parent relationships
    for (const child of node.children) {
      node.removeChild(child.id);
    }
    
    // Remove sibling relationships
    for (const sibling of node.siblings) {
      node.removeSibling(sibling.id);
    }
    
    // Remove from nodes map
    this._nodes.delete(id);
    
    // Emit event
    this._events.emit(NetworkEvents.NODE_REMOVED, node);
    
    return true;
  }
  
  /**
   * Gets all nodes in the system
   */
  getAllNodes(): NetworkNode[] {
    return Array.from(this._nodes.values());
  }
  
  /**
   * Gets all nodes at a specific level
   */
  getNodesByLevel(level: number): NetworkNode[] {
    return this.getAllNodes().filter(node => node.level === level);
  }
  
  /**
   * Finds the best parent for a node based on hierarchy
   */
  findBestParent(node: NetworkNode): NetworkNode | null {
    // For Phase 0, just find a node at the next higher level with available capacity
    const potentialParents = this.getNodesByLevel(node.level + 1)
      .filter(parent => parent.canAcceptChildren());
    
    if (potentialParents.length === 0) {
      return null;
    }
    
    // For now, just return the first available parent
    // In future phases, this will use metrics to find optimal parent
    return potentialParents[0];
  }
  
  /**
   * Places a node in the hierarchy by finding an appropriate parent
   */
  placeNodeInHierarchy(node: NetworkNode): boolean {
    // Find best parent
    const parent = this.findBestParent(node);
    
    // If no parent available and not at top level, cannot place in hierarchy
    if (!parent && node.level < this._config.maxLevels - 1) {
      return false;
    }
    
    // If parent found, add as child
    if (parent) {
      return parent.addChild(node);
    }
    
    // If no parent and at top level, node is at top of hierarchy
    return true;
  }
  
  /**
   * Registers a plugin with the system
   */
  registerPlugin(plugin: IPlugin): boolean {
    const result = this._plugins.register(plugin);
    if (result) {
      this._events.emit(NetworkEvents.PLUGIN_REGISTERED, this, plugin);
    }
    return result;
  }
  
  /**
   * Removes a plugin from the system
   */
  removePlugin(pluginId: string): boolean {
    const plugin = this._plugins.getPlugin(pluginId);
    const result = this._plugins.unregister(pluginId);
    if (result && plugin) {
      this._events.emit(NetworkEvents.PLUGIN_UNREGISTERED, this, plugin);
    }
    return result;
  }
  
  /**
   * Gets a plugin by ID
   */
  getPlugin<T extends IPlugin>(pluginId: string): T | undefined {
    return this._plugins.getPlugin<T>(pluginId);
  }
  
  /**
   * Returns the current library version
   */
  getVersion() {
    return VersionManager.CURRENT_VERSION;
  }
  
  /**
   * Creates a default configuration
   */
  private _createDefaultConfig(partial: Partial<NetworkSystemConfig>): NetworkSystemConfig {
    return {
      maxLevels: partial.maxLevels || 5,
      defaultLevel: partial.defaultLevel || 0,
      levelConfigs: partial.levelConfigs || DEFAULT_LEVEL_CONFIGS,
      enableVoting: partial.enableVoting ?? false,
      enableStateSync: partial.enableStateSync ?? false,
      enableMetrics: partial.enableMetrics ?? false,
      enableFailover: partial.enableFailover ?? false,
      transportFallbackOrder: partial.transportFallbackOrder || [],
      connectionTimeout: partial.connectionTimeout || 30000,
      connectionRetries: partial.connectionRetries || 3,
      heartbeatInterval: partial.heartbeatInterval || 5000
    };
  }
  
  /**
   * Determines the initial level for a node based on capabilities
   */
  private _determineInitialLevel(capabilities: NodeCapabilities): number {
    // For Phase 0, just use default level
    // In future phases, this will examine capabilities
    return this._config.defaultLevel;
  }
  
  /**
   * Sets up event handlers for a node
   */
  private _setupNodeEventHandlers(node: NetworkNode): void {
    // For Phase 0, just listen for basic events
    // In future phases, this will be more comprehensive
  }
}

export const DEFAULT_LEVEL_CONFIGS = [
  {
    level: 0,
    name: "Client",
    maxChildren: 0,
    maxSiblings: Infinity,
    minPromotionScore: 0.7,
    demotionThreshold: 0
  },
  {
    level: 1,
    name: "Host",
    maxChildren: 20,
    maxSiblings: 10,
    minPromotionScore: 0.8,
    demotionThreshold: 0.4
  },
  {
    level: 2,
    name: "Tier Host",
    maxChildren: 10,
    maxSiblings: 5,
    minPromotionScore: 0.9,
    demotionThreshold: 0.5
  },
  {
    level: 3,
    name: "Region Host",
    maxChildren: 5,
    maxSiblings: 10,
    minPromotionScore: 0.95,
    demotionThreshold: 0.6
  },
  {
    level: 4,
    name: "Country Host",
    maxChildren: 10,
    maxSiblings: 0,
    minPromotionScore: 1.0,
    demotionThreshold: 0.7
  }
];

7. Update Index File with Exports

File: src/index.ts (update)

// Core components
export * from './node';
export * from './network';
export * from './utils';
export * from './versioning';
export * from './plugins/plugin-registry';

// Types
export * from './types';

Testing Strategy

For Phase 0, we'll implement the following tests:

  1. Unit Tests:

    • NetworkNode class tests
    • NetworkSystem class tests
    • NetworkEventEmitter tests
    • VersionInfo and VersionManager tests
    • PluginRegistry tests
  2. Integration Tests:

    • Event propagation through hierarchy
    • Plugin registration and interaction with nodes
    • System configuration and node placement
  3. Edge Cases:

    • Node removal and hierarchy reorganization
    • Version compatibility checking
    • Plugin dependency resolution

Next Steps

After implementing Phase 0, we'll proceed to Phase 1, which will focus on:

  1. Implementing the transport layer
  2. Enhancing the relay capabilities
  3. Building out the message routing system
  4. Adding metrics and host selection

Conclusion

This implementation plan establishes the foundational components of the network library with a focus on modularity, event handling, and plugin support. By following this plan, we'll create a solid base that supports all future phases of development while maintaining compatibility and extensibility.