npm package: @synet/net
Description: Network abstraction layer for Synet. visit https://syntehtism.ai for more information.
Author: Synet Team
Latest version: 0.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

```bash
npm install @synet/net
```

## Usage

### Basic Usage with Result Pattern

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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:

```typescript
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:

```typescript
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