# Aruba Central API Node for n8n: Development & Troubleshooting Guide

You're working on an n8n integration node for Aruba Central API. This comprehensive guide will help you continue development, implement new features, and troubleshoot issues with the codebase.

## Project Structure

The project follows a domain-driven design with the following structure:

```
.
├── ArubaCentral.node.ts           # Main node definition
├── api/                           # API implementation by domain
│   ├── aiops/                    # AI Operations domain
│   ├── configuration/           # Configuration domain
│   ├── firmware/               # Firmware domain
│   ├── inventory/             # Inventory domain
|   ├── monitoring/                # Monitoring domain
|   |   ├── monitoring.descriptions.ts  # Combines all domain descriptions
|   |   ├── monitoring.methods.ts  # Combines all domain methods
|   |   ├── monitoring.resources.ts  # Combines all domain resources
|   |   └── site/                  # Site resource
|   |       ├── site.descriptions.ts    # Combines all site operation descriptions
|   |       ├── site.methods.ts         # Exports all site operations
|   |       ├── site.types.ts           # Type definitions for site operations
|   |       └── operations/             # Individual operations
|   |           ├── getSites.descriptions.ts  # UI descriptions for operation
|   |           └── getSites.methods.ts       # Implementation of operation
│   └── topology/             # Topology domain
├── credentials/               # Authentication credentials
├── helpers/                  # Shared utilities
└── shared/                   # Shared constants and interfaces
```


Each domain directory (e.g., api/monitoring/) follows this structure:
```
.
├── resource/                 # e.g., ap, client, switch
│   ├── resource.common.ts    # Shared utilities for the resource
│   ├── resource.descriptions.ts   # Resource Description File
│   ├── resource.methods.ts   # API method implementations
│   ├── resource.types.ts     # Resource-specific types
│   └── operations/           # Individual operation implementations
│       ├── operation.methods.ts
│       └── operation.descriptions.ts
```

## Architecture & Design Pattern

The node follows a domain-driven design pattern that separates:

1. **Domain Logic**: Each API domain (monitoring, firmware, etc.) has its own directory in `api/`
2. **Resource Implementation**: Each resource within a domain has its own directory with dedicated files
3. **Operation Handlers**: Individual operations are implemented in separate files for clarity
4. **UI Descriptions**: Individual resource definitions are implemented in separate files for clarity
5. **Shared Components**: Common utilities and types are organized in `shared/` and `helpers/`

### Operation Flow

1. User selects Domain → Resource → Operation in n8n UI
2. `ArubaCentral.node.ts` routes to appropriate domain handler
3. Domain handler delegates to resource implementation
4. Resource implementation executes specific operation
5. Response is formatted and returned to n8n

## Adding New API Operations

### Step 1: Create Operation Method File

Create the implementation file for your operation in the appropriate resource folder:

```typescript
// api/monitoring/site/operations/myNewOperation.methods.ts
import { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { apiRequest } from '../../../../helpers/apiRequest';
import { formatResponse } from '../../../../helpers/formatter';
import { logger } from '../../../../helpers/logger';
import { handleApiError } from '../../../../helpers/errorHandler';

/**
 * My new operation description
 * 
 * @param this The n8n execution context
 * @returns Formatted response
 */
export async function myNewOperation(this: IExecuteFunctions): Promise<INodeExecutionData[]> {
  try {
    // Get parameters
    const param1 = this.getNodeParameter('param1', 0) as string;
    
    // Construct API endpoint and parameters
    const endpoint = `/api/v2/endpoint/${param1}`;
    
    // Make API request
    const response = await apiRequest.call(this, 'GET', endpoint);
    
    // Format and return response
    return formatResponse(response);
  } catch (error) {
    logger.error('domain:resource:operation:error', { message: error.message });
    return handleApiError.call(this, error, 'Failed to execute operation');
  }
}
```

### Step 2: Create Operation Description File

Create the UI description file for your operation:

```typescript
// api/monitoring/site/operations/myNewOperation.descriptions.ts
import { INodeProperties } from 'n8n-workflow';

// IMPORTANT: Export as an array named [operationName]Description
export const myNewOperationDescription: INodeProperties[] = [
  {
    displayName: 'Parameter 1',
    name: 'param1',
    type: 'string',
    required: true,
    displayOptions: {
      show: {
        resource: ['site'],  // Match the resource name
        domain: ['monitoring'],  // Match the domain name
        operation: ['myNewOperation'],  // Match the operation name
      },
    },
    default: '',
    description: 'Description of parameter 1',
  },
  {
    displayName: 'Additional Fields',
    name: 'additionalFields',
    type: 'collection',
    placeholder: 'Add Field',
    default: {},
    displayOptions: {
      show: {
        resource: ['site'],
        domain: ['monitoring'],
        operation: ['myNewOperation'],
      },
    },
    options: [
      {
        displayName: 'Option 1',
        name: 'option1',
        type: 'string',
        default: '',
        description: 'Description of option 1',
      },
      // More options as needed
    ],
  },
  // More parameters as needed
];
```

### Step 3: Update Resource Description File

Add your operation to the resource's description file:

```typescript
// api/monitoring/site/site.descriptions.ts
import { INodeProperties } from 'n8n-workflow';
import { getSitesDescription } from './operations/getSites.descriptions';
// Import your new operation description
import { myNewOperationDescription } from './operations/myNewOperation.descriptions';
// ... other imports

// Define the operation selector
const siteOperationSelector: INodeProperties = {
  displayName: 'Operation',
  name: 'operation',
  type: 'options',
  noDataExpression: true,
  displayOptions: {
    show: {
      resource: ['site'],
      domain: ['monitoring'],
    },
  },
  options: [
    {
      name: 'Get Sites',
      value: 'getSites',
      description: 'Get a list of sites',
      action: 'Get sites',
    },
    // Add your new operation
    {
      name: 'My New Operation',
      value: 'myNewOperation',
      description: 'Description of my new operation',
      action: 'Action text for my operation',
    },
    // ... other operations
  ],
  default: 'getSites',
};

// Export all site descriptions (CRITICAL: This is how parameters appear in the UI)
export const siteDescriptions: INodeProperties[] = [
  siteOperationSelector,
  ...getSitesDescription,
  // Add your new operation's descriptions
  ...myNewOperationDescription,
  // ... other operation descriptions
];
```

### Step 4: Update Resource Methods File

Add your operation to the resource's methods file:

```typescript
// api/monitoring/site/site.methods.ts
import { IExecuteFunctions } from 'n8n-workflow';
import { getSites } from './operations/getSites.methods';
// Import your new operation method
import { myNewOperation } from './operations/myNewOperation.methods';
// ... other imports
import { logger } from '../../../helpers/logger';

/**
 * All operations available for the Site resource
 */
export const siteOperations = {
  getSites,
  // Add your new operation
  myNewOperation,
  // ... other operations
};

/**
 * Check if a site operation exists
 * 
 * @param operation Operation name to check
 * @returns boolean indicating if the operation exists
 */
export function hasSiteOperation(operation: string): boolean {
  const exists = !!siteOperations[operation as keyof typeof siteOperations];
  logger.debug('monitoring:site:check', `Operation "${operation}" ${exists ? 'exists' : 'does not exist'}`);
  return exists;
}
```

### Step 5: Update Types File (If Needed)

If your operation uses specific types, add them to the resource's types file:

```typescript
// api/monitoring/site/site.types.ts
// Add any new types or interfaces needed for your operation
export interface MyNewOperationRequest {
  param1: string;
  option1?: string;
}

export interface MyNewOperationResponse {
  result: string;
  // ... other response fields
}
```

## Troubleshooting

### Common Issues

1. **Type Errors**
   - Check interfaces in resource's `.types.ts` file
   - Verify type imports are correct
   - Ensure API response matches type definitions

2. **Authentication Issues**
   - Check credentials implementation in `credentials/`
   - Verify token refresh logic
   - Monitor API request headers

3. **Operation Not Found**
   - Verify operation is exported in resource's `.common.ts`
   - Check domain operation registration
   - Confirm UI description is properly registered

4. **Response Formatting Errors**
   - Check response type matches expected format
   - Verify formatResponse helper is handling the type
   - Log raw response for debugging

### Debugging Tips

1. Use domain-specific logging:
```typescript
import { logger } from '../../../helpers/logger';

logger.debug('monitoring:ap:getStatus', { params, response });
```

2. Test operations in isolation:
```typescript
// tests/monitoring/ap/getStatus.test.ts
describe('AP Status Operation', () => {
  it('should retrieve device status', async () => {
    const result = await getStatus.call(mockExecuteFunctions);
    expect(result).toBeDefined();
  });
});
```

3. Validate API responses against types:
```typescript
import { StatusResponse } from './ap.types';

const validateResponse = (data: unknown): data is StatusResponse => {
  // Implementation
};
```

## OAuth2 Authentication

Authentication is handled centrally through:
- `credentials/ArubaCentralOAuth2Api.credentials.ts` - Credential definition
- `helpers/apiRequest.ts` - Request handling with auth

## Best Practices

1. **Domain Organization**
   - Keep related operations in same resource directory
   - Use common.ts for shared resource code
   - Maintain clear separation between domains

2. **Type Safety**
   - Define interfaces for all API responses
   - Use type guards for validation
   - Keep types synchronized with API spec

3. **Error Handling**
   - Use domain-specific error types
   - Implement consistent error formatting
   - Provide clear error messages

4. **Documentation**
   - Document complex operations
   - Keep API references updated
   - Include examples in descriptions

5. **Testing**
   - Write tests for each operation
   - Test error conditions
   - Validate response formatting

## Development Workflow

1. **Planning**
   - Identify domain and resource
   - Review API documentation
   - Plan type structures

2. **Implementation**
   - Create operation files
   - Implement method logic
   - Add UI descriptions

3. **Integration**
   - Register with resource
   - Update domain operations
   - Test end-to-end flow

4. **Documentation**
   - Update operation docs
   - Add usage examples
   - Document error cases

5. **Testing**
   - Unit test operation
   - Integration test with API
   - Verify UI functionality

## API Documentation References

For more details on available endpoints and parameters, refer to:
- API documentation in vector store
- Domain-specific documentation in `docs/api/`
- Operation descriptions in code

## Next Steps

Your task is to: {{ task }}

Fix Current Issues

    - Standardize error handling across all operations using the handleApiError helper
    - Enhance response formatting to handle all possible response structures
    - Improve parameter validation before making API requests

Documentation

    - Add JSDoc comments to all functions
    - Create usage examples for common operations
    - Document error cases and handling


Remember to:
1. Follow the domain-driven structure
2. Implement proper error handling
3. Add comprehensive types
4. Include operation documentation
5. Write tests for new functionality