# Nano Framework IPC System

The Nano Framework IPC (Inter-Process Communication) system provides a clean, Tauri-like interface for communication between the Rust backend and frontend applications. It's designed to be simple, type-safe, and efficient.

## Architecture Overview

The IPC system consists of three main components:

```
┌─────────────────────────────────────────────────────────────────┐
│                        Frontend (JavaScript/TypeScript)         │
├─────────────────────────────────────────────────────────────────┤
│  invoke("command_name", { arg1: "value", arg2: 123 })           │
│                            │                                     │
│                            ▼                                     │
│                     HTTP POST /ipc                               │
└─────────────────────────────────────────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────────┐
│                    Axum HTTP Server (Rust)                      │
├─────────────────────────────────────────────────────────────────┤
│  dispatcher.rs → handle_ipc_request()                           │
│                            │                                     │
│                            ▼                                     │
│  simple_registry.rs → NANO_REGISTRY.get(command)               │
│                            │                                     │
│                            ▼                                     │
│  CommandHandler → execute function                               │
│                            │                                     │
│                            ▼                                     │
│  Return JSON response                                            │
└─────────────────────────────────────────────────────────────────┘
```

## Core Components

### 1. `mod.rs` - Module Declaration
- Exports the main IPC types and functions
- Initializes tracing for debugging
- Sets up the global registry

### 2. `dispatcher.rs` - Request Handler
Handles incoming IPC requests and dispatches them to registered functions.

**Key Types:**
```rust
// Request from frontend
#[derive(Debug, Deserialize)]
pub struct IpcRequest {
    pub cmd: String,        // Function name to call
    pub args: Value,        // Arguments as JSON
    pub id: Option<String>, // Optional request ID
}

// Response to frontend  
#[derive(Debug, Serialize)]
pub struct IpcResponse {
    pub result: Option<Value>,  // Success result
    pub error: Option<String>,  // Error message
    pub code: Option<String>,   // Error code
    pub id: Option<String>,     // Request ID
}
```

**Error Handling:**
- `CommandNotFound` - Function not registered
- `InvalidArguments` - Deserialization failed
- `ExecutionError` - Function execution failed
- `SecurityViolation` - Security check failed
- `SerializationError` - Response serialization failed

### 3. `simple_registry.rs` - Function Registry
A thread-safe registry system for registering and executing commands.

**Key Features:**
- **Thread-Safe**: Uses `Arc<RwLock<HashMap>>` for concurrent access
- **Type-Safe**: Automatic serialization/deserialization of arguments and results
- **Flexible**: Supports any function signature matching the pattern
- **Global**: Single static registry instance accessible everywhere

## Function Registration System

### Registration Pattern

All functions must follow this signature pattern:
```rust
pub async fn function_name(args: ArgsType) -> Result<ReturnType, String>
```

### Registration Process

1. **Define Types** (in `nano_types.rs`):
```rust
#[derive(Debug, Deserialize)]
pub struct GreetArgs {
    pub name: String,
}

#[derive(Debug, Serialize)]
pub struct GreetResponse {
    pub message: String,
}
```

2. **Implement Function** (in `nano_impl.rs` or external modules):
```rust
pub async fn greet(args: GreetArgs) -> Result<String, String> {
    if args.name.is_empty() {
        return Err("Name cannot be empty".to_string());
    }
    Ok(format!("Hello, {}!", args.name))
}
```

3. **Register Function** (in `nano_registry.rs`):
```rust
pub fn register_all_nano_functions() {
    register_nano_command!("greet", greet);
}
```

### The `register_nano_command!` Macro

This macro creates a type-safe handler that:
- Deserializes JSON arguments to the expected type
- Calls your function with typed arguments
- Serializes the result back to JSON
- Handles errors gracefully

```rust
#[macro_export]
macro_rules! register_nano_command {
    ($name:expr, $func:expr) => {
        NANO_REGISTRY.register($name, create_handler($func));
    };
}
```

## Advanced Features

### 1. Empty Arguments Handling
Functions can accept no arguments by using unit types:
```rust
pub async fn get_timestamp() -> Result<String, String> {
    Ok(chrono::Utc::now().to_rfc3339())
}

// Frontend: await invoke("get_timestamp")
```

### 2. Complex Argument Types
Support for nested structures and arrays:
```rust
#[derive(Debug, Deserialize)]
pub struct CalculationArgs {
    pub operation: String,
    pub values: Vec<f64>,
    pub options: Option<CalculationOptions>,
}

#[derive(Debug, Deserialize)]
pub struct CalculationOptions {
    pub precision: u8,
    pub round_result: bool,
}
```

### 3. External System Integration
Functions from external modules can be registered seamlessly:
```rust
// In nano_registry.rs
register_nano_command!("read_file", file_manager::read_file);
register_nano_command!("calculate", calculator::calculate_expression);
```

## HTTP Integration

The IPC system integrates with the Axum web server through a single endpoint:

```rust
// In server.rs
Router::new()
    .route("/ipc", post(handle_ipc_request))
```

**Request Flow:**
1. Frontend sends POST to `/ipc` with JSON body
2. `handle_ipc_request` deserializes to `IpcRequest`
3. `dispatch_request` looks up function in registry
4. Function executes with type-safe arguments
5. Result serialized to `IpcResponse` and returned

## Frontend Usage

### Using `nano-invoke` Package (Recommended)
```typescript
import { invoke, configure } from 'nano-invoke';

// Configure once at startup
configure({
    debug: true,
    timeout: 5000
});

// Call any registered function
const greeting = await invoke('greet', { name: 'Alice' });
const result = await invoke('calculate', { 
    operation: 'add', 
    values: [1, 2, 3, 4, 5] 
});
```

### Direct HTTP Calls
```typescript
async function invoke(cmd: string, args: any) {
    const response = await fetch('/ipc', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ cmd, args })
    });
    
    const result = await response.json();
    if (result.error) {
        throw new Error(result.error);
    }
    
    return result.result;
}
```

## Error Handling

### Backend Error Handling
Functions should return descriptive error messages:
```rust
pub async fn divide(args: DivideArgs) -> Result<f64, String> {
    if args.b == 0.0 {
        return Err("Division by zero is not allowed".to_string());
    }
    Ok(args.a / args.b)
}
```

### Frontend Error Handling
```typescript
try {
    const result = await invoke('divide', { a: 10, b: 0 });
} catch (error) {
    console.error('Division failed:', error.message);
    // Handle error appropriately
}
```

## Debugging and Logging

### Backend Logging
The system uses the `tracing` crate for structured logging:
```rust
tracing::info!("IPC request [{}]: cmd='{}'", request_id, request.cmd);
tracing::error!("Nano command '{}' failed: {}", cmd, error);
```

### Frontend Debugging
Enable debug mode to see detailed logs:
```typescript
configure({ debug: true });
// Now all IPC calls will be logged to console
```

## Security Considerations

### Input Validation
Always validate inputs in your functions:
```rust
pub async fn create_user(args: CreateUserArgs) -> Result<UserInfo, String> {
    // Validate email format
    if !args.email.contains('@') {
        return Err("Invalid email format".to_string());
    }
    
    // Validate age range
    if args.age == 0 || args.age > 150 {
        return Err("Invalid age".to_string());
    }
    
    // Create user...
}
```

### Rate Limiting
Consider implementing rate limiting for resource-intensive operations:
```rust
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};

static LAST_CALL: AtomicU64 = AtomicU64::new(0);

pub async fn expensive_operation(args: Args) -> Result<Data, String> {
    let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
    let last = LAST_CALL.load(Ordering::Relaxed);
    
    if now - last < 1 {  // 1 second rate limit
        return Err("Rate limit exceeded".to_string());
    }
    
    LAST_CALL.store(now, Ordering::Relaxed);
    // Continue with operation...
}
```

## Performance Optimization

### 1. Lazy Initialization
Use lazy initialization for expensive resources:
```rust
use once_cell::sync::Lazy;

static DATABASE: Lazy<Database> = Lazy::new(|| {
    Database::connect("sqlite://app.db").expect("Failed to connect to database")
});
```

### 2. Connection Pooling
For database operations, use connection pooling:
```rust
use sqlx::SqlitePool;
use once_cell::sync::Lazy;

static DB_POOL: Lazy<SqlitePool> = Lazy::new(|| {
    SqlitePool::connect("sqlite://app.db").await.expect("Failed to create pool")
});
```

### 3. Async Best Practices
- Use `tokio::spawn` for CPU-intensive tasks
- Use `tokio::time::timeout` for operations with time limits
- Prefer streaming for large data transfers

## Testing

### Unit Testing Functions
```rust
#[cfg(test)]
mod tests {
    use super::*;
    
    #[tokio::test]
    async fn test_greet_function() {
        let args = GreetArgs {
            name: "Test User".to_string(),
        };
        
        let result = greet(args).await;
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), "Hello, Test User!");
    }
    
    #[tokio::test]
    async fn test_greet_empty_name() {
        let args = GreetArgs {
            name: "".to_string(),
        };
        
        let result = greet(args).await;
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), "Name cannot be empty");
    }
}
```

### Integration Testing
```rust
#[cfg(test)]
mod integration_tests {
    use super::*;
    use axum::http::StatusCode;
    use axum::test::TestRequest;
    
    #[tokio::test]
    async fn test_ipc_endpoint() {
        // Register functions
        register_all_nano_functions();
        
        let app = create_test_app();
        
        let request = TestRequest::post("/ipc")
            .json(&IpcRequest {
                cmd: "greet".to_string(),
                args: serde_json::json!({"name": "Test"}),
                id: None,
            })
            .build();
        
        let response = app.oneshot(request).await.unwrap();
        assert_eq!(response.status(), StatusCode::OK);
    }
}
```

## Best Practices

### 1. Function Organization
- Keep simple functions in `nano_impl.rs`
- Put complex domain logic in separate modules
- Use `external_systems/` for third-party integrations

### 2. Type Design
- Use descriptive type names
- Add validation in the deserialize step when possible
- Prefer `Option<T>` over nullable types

### 3. Error Messages
- Provide user-friendly error messages
- Include context about what went wrong
- Use error codes for programmatic handling

### 4. Documentation
- Document all public functions with `///` comments
- Include usage examples in function docs
- Maintain type definitions with clear field descriptions

## Extending the System

### Adding New Commands
1. Define argument and return types in `nano_types.rs`
2. Implement function in appropriate module
3. Register in `nano_registry.rs`
4. Test with frontend

### Creating Custom Command Types
```rust
// For functions that need special handling
pub type SpecialCommandHandler = Arc<dyn Fn(Value) -> Pin<Box<dyn Future<Output = Result<Value, IpcError>> + Send>> + Send + Sync>;

impl SimpleRegistry {
    pub fn register_special(&self, name: &str, handler: SpecialCommandHandler) {
        // Custom registration logic
    }
}
```

## Future Enhancements

### WebSocket Support
The system is designed to support WebSocket communication for real-time features:
- Bidirectional communication
- Server-initiated events
- Real-time data streaming

### Command Discovery
Automatic command discovery and documentation generation:
- List available commands
- Generate API documentation
- Runtime introspection

### Middleware System
Pluggable middleware for:
- Authentication
- Rate limiting  
- Request/response transformation
- Caching

This IPC system provides a solid foundation for building complex desktop applications with the Nano Framework while maintaining simplicity and type safety.