UNPKG

n8n-nodes-arubacentral

Version:

n8n community node for Aruba Central API integration with comprehensive monitoring, configuration, and management capabilities

408 lines (335 loc) 12.5 kB
# 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