Network Package
The @pact-toolbox/network
package provides comprehensive network management capabilities for Pact development environments, including lifecycle management, health monitoring, discovery, and registry services.
Overview
The network package is the core infrastructure for managing local Pact networks in development. It provides:
- Docker-Based Networks: Container orchestration for DevNet and services
- Unified Network Management: Consistent API across all environments
- Health Monitoring: Continuous network health checks and statistics
- Network Discovery: Automatic detection of running networks
- Service Management: Coordinate multiple services (Pact, mining, wallet)
- Port Management: Thread-safe port allocation and conflict resolution
- Graceful Shutdown: Proper cleanup of containers and processes
Architecture
Core Components
graph TB
A[NetworkManager] --> B[PactToolboxNetwork]
A --> C[HealthMonitor]
A --> D[NetworkRegistry]
A --> E[PortManager]
B --> F[PactServerNetwork]
B --> G[LocalDevNetNetwork]
C --> H[HealthStatus]
C --> I[NetworkStats]
D --> J[ProcessTracking]
D --> K[OrphanCleanup]
E --> L[PortAllocation]
E --> M[ConflictResolution]
Network Types
- DevNet: Full Kadena blockchain simulation with Docker
- 10 chains (configurable)
- Automatic mining
- Coin contract pre-deployed
- Gas station support
- Minimal: Lightweight single-chain setup
- Fast startup
- Ideal for unit testing
- Compact: 5-chain balanced configuration
Quick Start
Basic Usage
import { NetworkManager } from "@pact-toolbox/network";
import { resolveConfig } from "@pact-toolbox/config";
// Create network manager for your bundler
const config = await resolveConfig();
const manager = NetworkManager.forBundler("vite", {
config,
mode: "development",
autoStart: true,
});
// Start the network
await manager.start();
// Check health
const isHealthy = await manager.isHealthy();
console.log("Network healthy:", isHealthy);
// Stop when done
await manager.stop();
Bundler Integration
The network package integrates seamlessly with all major bundlers:
// Vite Plugin
import { pactToolbox } from "@pact-toolbox/unplugin/vite";
export default {
plugins: [
pactToolbox({
// Network automatically managed
}),
],
};
API Reference
NetworkManager
The main interface for network lifecycle management.
Constructor Options
interface NetworkManagerOptions {
config: PactToolboxConfigObj;
logger?: Logger;
spinner?: Spinner;
mode?: "development" | "production";
autoStart?: boolean;
setupSignalHandlers?: boolean;
conflictStrategy?: "error" | "ignore" | "replace";
shutdownTimeout?: number;
}
Methods
start(): Promise<void>
- Start the network
stop(): Promise<void>
- Stop the network with cleanup
restart(): Promise<void>
- Restart the network
getState(): NetworkManagerState
- Get current state
isHealthy(): Promise<boolean>
- Check network health
getHealthStatus(): HealthStatus | null
- Get detailed health info
getNetworkStats(): NetworkStats | null
- Get network statistics
Factory Method
NetworkManager.forBundler(
bundler: "vite" | "webpack" | "next" | "rsbuild" | "rollup" | "esbuild",
options: NetworkManagerOptions
): NetworkManager
Network Discovery
Find running networks across different sources:
import { discoverNetworks } from "@pact-toolbox/network";
const networks = await discoverNetworks({
includeStopped: false,
scanPorts: true,
portRange: { start: 8080, end: 8090 },
});
console.log("Found networks:", networks);
Health Monitoring
Monitor network health continuously:
import { getHealthMonitor } from "@pact-toolbox/network";
const monitor = getHealthMonitor({
enableContinuousMonitoring: true,
checkInterval: 5000,
onHealthChange: (networkId, status) => {
console.log(`Network ${networkId}: ${status.status}`);
},
});
// Add network to monitoring
monitor.addNetwork(networkConfig);
monitor.startMonitoring(networkConfig);
Docker Integration
The network package uses Docker for reliable, isolated development environments:
import { DockerNetwork } from "@pact-toolbox/network";
// Create Docker-based DevNet
const network = new DockerNetwork({
preset: "devnet", // or "minimal", "compact"
chainIds: ["0", "1", "2", "3", "4"], // Custom chains
miningDelay: 5, // Seconds between blocks
persist: true, // Keep data between restarts
services: {
pact: true,
mining: true,
wallet: true // Enable dev wallet
}
});
// Start network
await network.start();
// Check container status
const status = await network.getContainerStatus();
console.log("Containers:", status);
// Stop and clean up
await network.stop({ removeVolumes: true });
Docker Configuration
interface DockerNetworkConfig {
// Network preset
preset?: "devnet" | "minimal" | "compact" | "custom";
// Custom configuration
chainIds?: string[];
miningDelay?: number;
// Container settings
image?: string; // Custom Pact image
volumes?: boolean; // Persist data
network?: string; // Docker network name
// Services
services?: {
pact?: boolean;
mining?: boolean;
wallet?: boolean;
gasStation?: boolean;
};
// Resource limits
resources?: {
cpuLimit?: string; // e.g., "0.5"
memoryLimit?: string; // e.g., "512m"
};
}
Port Management
Thread-safe port allocation:
import { portManager } from "@pact-toolbox/network";
// Allocate single port
const port = await portManager.allocatePort();
// Allocate multiple sequential ports
const ports = await portManager.allocateMultiplePorts(3);
// Release when done
portManager.releasePort(port);
portManager.releaseMultiplePorts(ports);
Registry Management
Persistent process tracking:
import { networkRegistry } from "@pact-toolbox/network";
// Get running networks
const running = await networkRegistry.getRunning();
// Clean up orphaned processes
await networkRegistry.cleanupOrphaned();
// Perform full cleanup
import { performFullCleanup } from "@pact-toolbox/network";
await performFullCleanup({ force: true });
Configuration
Network Configuration
// pact-toolbox.config.ts
export default {
defaultNetwork: "local",
networks: {
local: {
type: "pact-server",
networkId: "my-local-network",
name: "Local Development",
serverConfig: {
port: 8080,
verbose: true,
},
},
devnet: {
type: "devnet",
networkId: "my-devnet",
name: "DevNet",
containerConfig: {
rpcPort: 8545,
p2pPort: 30303,
},
},
},
};
Health Monitoring Configuration
const monitor = getHealthMonitor({
enableContinuousMonitoring: true,
checkInterval: 5000, // 5 seconds
timeout: 10000, // 10 seconds
maxConsecutiveFailures: 3,
retryInterval: 1000,
onHealthChange: (networkId, status) => {
// Handle health changes
},
onUnhealthy: (networkId, result) => {
// Handle unhealthy networks
},
});
Bundler-Specific Behavior
Next.js
- Uses process.env flags for persistence across hot reloads
- Automatically sets up signal handlers
- Uses "ignore" conflict strategy to prevent multiple instances
Vite
- Hot reload integration with network preservation
- Development mode optimizations
- Fast restart capabilities
Webpack/Rsbuild
- Build lifecycle integration
- Production mode compatibility
- Bundle optimization considerations
Troubleshooting
Common Issues
Port Conflicts
// Check for port conflicts
const conflicts = await portManager.findConflicts([8080, 8081]);
if (conflicts.length > 0) {
console.log("Port conflicts:", conflicts);
}
Orphaned Processes
// Clean up orphaned networks
await networkRegistry.cleanupOrphaned();
// Force cleanup with retries
await performFullCleanup({
force: true,
maxRetries: 3,
});
Health Check Failures
// Check detailed health status
const status = manager.getHealthStatus();
if (status?.status === "unhealthy") {
console.log("Network issue:", status.error);
console.log("Last successful check:", status.lastCheckTime);
}
Debug Mode
Enable debug logging for detailed network information:
LOG_LEVEL=debug pact-toolbox dev
Network Inspector
Use the discovery API to inspect network state:
import { discoverNetworks, getServerIdentifier } from "@pact-toolbox/network";
// Discover all networks
const networks = await discoverNetworks({
scanPorts: true,
portRange: { start: 8000, end: 9000 },
});
// Identify server types
const identifier = getServerIdentifier();
for (const network of networks) {
const info = await identifier.identifyServer(network.port);
console.log(`Port ${network.port}: ${info.type} (${info.confidence})`);
}
Best Practices
Development Workflow
- Single Network: Use one network per project in development
- Health Monitoring: Enable continuous monitoring in dev mode
- Graceful Shutdown: Always use proper cleanup mechanisms
- Port Management: Let the system allocate ports automatically
Production Considerations
- No Auto-Start: Disable auto-start in production builds
- External Networks: Use external network configurations
- Monitoring: Implement external health checks
- Security: Never expose development networks publicly
Error Handling
try {
await manager.start();
} catch (error) {
if (error.message.includes("port conflict")) {
// Handle port conflicts
await manager.stop();
await manager.start();
} else {
// Handle other errors
console.error("Network error:", error);
}
}
Integration Examples
With Testing
import { createTestEnv } from "@pact-toolbox/test";
const testEnv = await createTestEnv({
network: "local",
autoCleanup: true,
});
// Network automatically managed for tests
With CI/CD
// ci-test.ts
import { NetworkManager } from "@pact-toolbox/network";
// Disable signal handlers in CI
const manager = NetworkManager.forBundler("vite", {
config,
setupSignalHandlers: false,
conflictStrategy: "replace",
});
For more examples and advanced usage, see the tutorials section and package examples.