0.2.0 • Published 1 month ago
@synet/net v0.2.0
@synet/net
A robust network abstraction library for WireGuard management with strong error handling, supporting both local wireguard-tools and the synetd API.
Installation
npm install @synet/net
Usage
Basic Usage with Result Pattern
import { createWireguardService, AdapterType, Result } from '@synet/net';
// Create a WireGuard service using the synetd adapter (default)
const wireguardService = createWireguardService();
// Or use wireguard-tools adapter
const wireguardService = createWireguardService(AdapterType.WIREGUARD_TOOLS);
async function setupConnection() {
// Generate keys with Result pattern
const keysResult = await wireguardService.generateKeys();
if (keysResult.isFailure) {
console.error(`Error generating keys: ${keysResult.error?.message}`);
return;
}
const keys = keysResult.value;
// Configure interface
const interfaceResult = await wireguardService.setInterface({
privateKey: keys.privateKey,
address: '10.0.0.2/32'
});
if (interfaceResult.isFailure) {
console.error(`Error configuring interface: ${interfaceResult.error?.message}`);
return;
}
// Add peer
const peerResult = await wireguardService.addPeer({
publicKey: 'PEER_PUBLIC_KEY',
endpoint: 'peer.example.com:51820',
allowedIPs: ['10.0.0.0/24'],
persistentKeepalive: 25
});
if (peerResult.isFailure) {
console.error(`Error adding peer: ${peerResult.error?.message}`);
return;
}
// Bring up interface
const upResult = await wireguardService.bringUp();
if (upResult.isFailure) {
console.error(`Error bringing up interface: ${upResult.error?.message}`);
return;
}
console.log('Successfully connected to WireGuard network');
}
// Later, to disconnect
async function disconnect() {
const result = await wireguardService.bringDown();
if (result.isFailure) {
console.error(`Error bringing down interface: ${result.error?.message}`);
} else {
console.log('Successfully disconnected');
}
}
Complete Connection Example
Complete Connection Example with Error Handling
import { createWireguardService, AdapterType, NetworkError } from '@synet/net';
async function connect() {
try {
const wireguardService = createWireguardService();
// Get existing keys or generate new ones
const keysResult = await wireguardService.getKeys();
let keys;
if (keysResult.isSuccess && keysResult.value) {
keys = keysResult.value;
} else {
const newKeysResult = await wireguardService.generateKeys();
if (newKeysResult.isFailure) {
throw new Error(`Failed to generate keys: ${newKeysResult.error?.message}`);
}
keys = newKeysResult.value;
}
// Connect in one go
const connectResult = await wireguardService.connect({
privateKey: keys.privateKey,
address: '10.0.0.2/32',
peer: {
publicKey: 'GATEWAY_PUBLIC_KEY',
endpoint: 'gateway.example.com:51820',
allowedIPs: ['10.0.0.0/24'],
persistentKeepalive: 25
}
});
if (connectResult.isFailure) {
throw connectResult.error;
}
console.log('Connected to WireGuard network');
} catch (error) {
if (error instanceof NetworkError) {
console.error(`Network error: ${error.message}`);
} else {
console.error(`Unexpected error: ${error.message}`);
}
}
}
connect();
With Custom Logger
import { createWireguardService, AdapterType, ConsoleLogger } from '@synet/net';
// Create a custom logger
const logger = new ConsoleLogger('MyWireguardService');
// Pass the logger to the service factory
const wireguardService = createWireguardService(AdapterType.WIREGUARD_TOOLS, {}, logger);
Architecture
This package follows clean architecture principles with additional improvements:
Domain Layer:
- Entities and interfaces with immutable properties
- Well-defined error types for better error handling
- Result pattern to handle operation outcomes
- Repository interfaces for data access
Application Layer:
- Use cases and business logic
- WireguardService with proper error handling
Infrastructure Layer:
- Implementations of interfaces (adapters)
- File system and command execution abstractions
- Repository implementations
- Logging capabilities
Error Handling
The package uses a simplified Result pattern with enum-based error types for improved error handling:
Basic Error Handling
const result = await wireguardService.addPeer(peerConfig);
if (result.isSuccess) {
// Operation succeeded
console.log("Peer added successfully");
} else {
// Operation failed with typed errors
console.error(`Failed to add peer: ${result.errorMessage}`);
// You can check the error type
if (result.errorType === ErrorType.PEER) {
console.error("There was an issue with the peer configuration");
} else if (result.errorType === ErrorType.CONNECTION) {
console.error("There was a connection problem");
}
}
Using Helper Methods
await wireguardService.connect(config)
.onSuccess(() => {
console.log("Connected successfully!");
})
.onFailure((type, message, cause) => {
switch (type) {
case ErrorType.INTERFACE:
console.error(`Interface error: ${message}`);
break;
case ErrorType.PEER:
console.error(`Peer error: ${message}`);
break;
default:
console.error(`Error: ${message}`);
}
// The cause parameter provides the original error (if available)
if (cause) {
console.debug("Original error:", cause);
}
});
Functional Transformation
You can transform successful results using the map method:
const keysResult = await wireguardService.generateKeys();
const publicKeyResult = keysResult.map(keys => keys.publicKey);
if (publicKeyResult.isSuccess) {
console.log(`Generated public key: ${publicKeyResult.value}`);
}
Available Error Types
The package provides these error types for better categorization:
enum ErrorType {
KEYS = 'keys', // Key generation or management issues
INTERFACE = 'interface', // Interface configuration problems
PEER = 'peer', // Peer-related issues
CONNECTION = 'connection', // Network connection problems
UNKNOWN = 'unknown' // Unspecified errors
}
License
MIT