# Environment Manager

Technical reference for the EnvironmentManager component that powers multi-instance routing.

---

## Architecture

### Component Overview

```
EnvironmentManager (singleton)
├── ConfigLoader - Load .config.json
├── N8NApiWrapper[] - One per environment
└── Instance Cache - Connection pooling
```

### Singleton Pattern

```typescript
// Get singleton instance
const manager = EnvironmentManager.getInstance()

// Always returns same instance
const manager2 = EnvironmentManager.getInstance()
// manager === manager2 (true)
```

**Benefits:**
- Single source of truth for all environments
- Shared connection pool
- Centralized routing logic
- Memory efficient

---

## Core Functionality

### Instance Resolution

```typescript
class EnvironmentManager {
  // Get API wrapper for specific instance
  getApiWrapper(instanceSlug?: string): N8NApiWrapper {
    // 1. If no instance specified, use default
    const env = instanceSlug || this.config.defaultEnv

    // 2. Validate instance exists
    if (!this.config.environments[env]) {
      throw new Error(`Instance '${env}' not found`)
    }

    // 3. Return or create API wrapper
    return this.getOrCreateWrapper(env)
  }
}
```

### Connection Pooling

```typescript
// First call - creates wrapper
manager.getApiWrapper("production")
→ Creates new N8NApiWrapper
→ Stores in cache

// Subsequent calls - reuses wrapper
manager.getApiWrapper("production")
→ Returns cached wrapper
→ No new connection created
```

**Performance Benefits:**
- Faster subsequent requests
- Reduced memory usage
- Connection reuse
- Lower latency

---

## API Wrapper Management

### N8NApiWrapper Per Instance

Each environment gets its own API wrapper:

```typescript
{
  "production": N8NApiWrapper {
    baseUrl: "https://prod.n8n.example.com/api/v1",
    apiKey: "prod_key",
    axiosInstance: AxiosInstance
  },
  "staging": N8NApiWrapper {
    baseUrl: "https://staging.n8n.example.com/api/v1",
    apiKey: "staging_key",
    axiosInstance: AxiosInstance
  }
}
```

### Request Routing

```typescript
// User request
list_workflows({ instance: "production" })

// Environment Manager flow
1. Resolve instance: "production"
2. Get API wrapper for production
3. Execute: productionWrapper.listWorkflows()
4. Return: workflows from production
```

---

## Configuration Loading

### Load Sequence

```
1. Check for .config.json
   ↓ Found
2. Parse JSON
   ↓
3. Validate structure
   ↓
4. Create EnvironmentManager
   ↓
5. Ready for requests

1. Check for .config.json
   ↓ Not Found
2. Check for .env
   ↓ Found
3. Load as single instance
   ↓
4. Create EnvironmentManager (single)
   ↓
5. Ready for requests
```

### Validation Rules

**Required Fields:**
```typescript
// Must have
✅ environments (object)
✅ defaultEnv (string)
✅ environments[name].n8n_host (string)
✅ environments[name].n8n_api_key (string)

// Must validate
✅ defaultEnv exists in environments
✅ n8n_host is valid URL
✅ n8n_api_key is non-empty
```

---

## Error Handling

### Instance Not Found

```typescript
Error: Instance 'staging' not found
Available instances: production, development

Suggestion: Check .config.json for typo in instance name
```

### Invalid Configuration

```typescript
Error: Invalid .config.json: Missing required field 'defaultEnv'

Required structure:
{
  "environments": { ... },
  "defaultEnv": "environment-name"
}
```

### Connection Failure

```typescript
Error: Failed to connect to instance 'production'
URL: https://prod.n8n.example.com/api/v1
Status: Connection refused

Suggestions:
1. Verify n8n is running at that URL
2. Check firewall settings
3. Test with: curl https://prod.n8n.example.com
```

---

## Performance Optimization

### Connection Caching

```typescript
// First request to production
list_workflows({ instance: "production" })
→ Creates wrapper (100ms)
→ Makes API call (200ms)
→ Total: 300ms

// Second request to production
list_workflows({ instance: "production" })
→ Reuses wrapper (0ms)
→ Makes API call (200ms)
→ Total: 200ms (33% faster)
```

### Lazy Initialization

```typescript
// Wrappers created only when needed
config.json has 5 environments
→ EnvironmentManager created
→ 0 wrappers initially

First request to "production"
→ Create production wrapper

First request to "staging"
→ Create staging wrapper

// Only 2 wrappers created (not all 5)
```

---

## Implementation Details

### Source Files

**ConfigLoader:**
- File: `src/config/configLoader.ts`
- Loads and validates .config.json
- Singleton pattern
- Fallback to .env

**EnvironmentManager:**
- File: `src/services/environmentManager.ts`
- Manages API wrappers
- Instance routing
- Connection pooling

**N8NApiWrapper:**
- File: `src/services/n8nApiWrapper.ts`
- Per-instance API client
- Axios-based HTTP client
- Method implementations

---

## Advanced Usage

### Dynamic Instance Selection

Claude can intelligently select instances:

```
User: "List production workflows"
→ Extracts "production" from context
→ Uses instance: "production"

User: "Show staging executions"
→ Extracts "staging" from context
→ Uses instance: "staging"

User: "List workflows"
→ No instance specified
→ Uses defaultEnv
```

### Instance Context Persistence

```
User: "List workflows from production"
Claude: [Lists production workflows]

User: "Show recent executions"
Claude: [Shows production executions]
        (remembers "production" from context)
```

---

## Next Steps

- [Configuration Guide](configuration.md) - Setup instructions
- [Instance Routing](instance-routing.md) - Routing details
- [Testing](testing.md) - Validation testing
- [Examples](examples.md) - Real-world scenarios

---

!!! info "Technical Deep Dive"
    See [API Overview](../api/overview.md) for implementation details.
