SaaS/backend/src/services/n8nService.ts
Aimpress Team bda23a773f 🚀 Initial commit: Aimpress AutomationHub
 Features:
- Modern SaaS automation platform
- Next.js 15 + TypeScript frontend
- Node.js + Express backend
- PostgreSQL database with full schema
- Docker Compose setup
- Admin panel with analytics
- Template marketplace (6 templates)
- Integrations hub (10+ services)
- Authentication & role-based access
- Responsive n8n-style design

🎯 Ready for demo and deployment

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-28 21:58:33 +01:00

226 lines
No EOL
6.8 KiB
TypeScript

import axios, { AxiosInstance } from 'axios';
interface N8nConfig {
baseUrl: string;
apiToken: string;
}
interface WorkflowData {
name: string;
active: boolean;
nodes: any[];
connections: any;
settings?: any;
staticData?: any;
}
interface N8nWorkflow {
id: string;
name: string;
active: boolean;
nodes: any[];
connections: any;
createdAt: string;
updatedAt: string;
settings?: any;
staticData?: any;
}
interface ExecutionResult {
id: string;
finished: boolean;
mode: string;
startedAt: string;
stoppedAt?: string;
workflowData: any;
data?: any;
}
class N8nService {
private client: AxiosInstance;
private config: N8nConfig;
constructor(config: N8nConfig) {
this.config = config;
this.client = axios.create({
baseURL: `${config.baseUrl}/api/v1`,
headers: {
'X-N8N-API-KEY': config.apiToken,
'Content-Type': 'application/json',
},
timeout: 30000,
});
// Add response interceptor for error handling
this.client.interceptors.response.use(
response => response,
error => {
console.error('N8n API Error:', error.response?.data || error.message);
throw error;
}
);
}
// Workflow Management
async getWorkflows(): Promise<N8nWorkflow[]> {
try {
const response = await this.client.get('/workflows');
return response.data.data || response.data;
} catch (error) {
console.error('Failed to fetch workflows:', error);
throw new Error('Failed to fetch workflows from n8n');
}
}
async getWorkflow(workflowId: string): Promise<N8nWorkflow> {
try {
const response = await this.client.get(`/workflows/${workflowId}`);
return response.data;
} catch (error) {
console.error(`Failed to fetch workflow ${workflowId}:`, error);
throw new Error(`Failed to fetch workflow ${workflowId} from n8n`);
}
}
async createWorkflow(workflowData: WorkflowData): Promise<N8nWorkflow> {
try {
const response = await this.client.post('/workflows', workflowData);
return response.data;
} catch (error) {
console.error('Failed to create workflow:', error);
throw new Error('Failed to create workflow in n8n');
}
}
async updateWorkflow(workflowId: string, workflowData: Partial<WorkflowData>): Promise<N8nWorkflow> {
try {
const response = await this.client.patch(`/workflows/${workflowId}`, workflowData);
return response.data;
} catch (error) {
console.error(`Failed to update workflow ${workflowId}:`, error);
throw new Error(`Failed to update workflow ${workflowId} in n8n`);
}
}
async deleteWorkflow(workflowId: string): Promise<void> {
try {
await this.client.delete(`/workflows/${workflowId}`);
} catch (error) {
console.error(`Failed to delete workflow ${workflowId}:`, error);
throw new Error(`Failed to delete workflow ${workflowId} from n8n`);
}
}
async activateWorkflow(workflowId: string): Promise<N8nWorkflow> {
try {
const response = await this.client.patch(`/workflows/${workflowId}`, { active: true });
return response.data;
} catch (error) {
console.error(`Failed to activate workflow ${workflowId}:`, error);
throw new Error(`Failed to activate workflow ${workflowId} in n8n`);
}
}
async deactivateWorkflow(workflowId: string): Promise<N8nWorkflow> {
try {
const response = await this.client.patch(`/workflows/${workflowId}`, { active: false });
return response.data;
} catch (error) {
console.error(`Failed to deactivate workflow ${workflowId}:`, error);
throw new Error(`Failed to deactivate workflow ${workflowId} in n8n`);
}
}
// Execution Management
async executeWorkflow(workflowId: string, inputData?: any): Promise<ExecutionResult> {
try {
const response = await this.client.post(`/workflows/${workflowId}/execute`, {
...(inputData && { inputData })
});
return response.data;
} catch (error) {
console.error(`Failed to execute workflow ${workflowId}:`, error);
throw new Error(`Failed to execute workflow ${workflowId} in n8n`);
}
}
async getExecutions(workflowId?: string, limit: number = 20): Promise<ExecutionResult[]> {
try {
const params: any = { limit };
if (workflowId) {
params.workflowId = workflowId;
}
const response = await this.client.get('/executions', { params });
return response.data.data || response.data;
} catch (error) {
console.error('Failed to fetch executions:', error);
throw new Error('Failed to fetch executions from n8n');
}
}
async getExecution(executionId: string): Promise<ExecutionResult> {
try {
const response = await this.client.get(`/executions/${executionId}`);
return response.data;
} catch (error) {
console.error(`Failed to fetch execution ${executionId}:`, error);
throw new Error(`Failed to fetch execution ${executionId} from n8n`);
}
}
async deleteExecution(executionId: string): Promise<void> {
try {
await this.client.delete(`/executions/${executionId}`);
} catch (error) {
console.error(`Failed to delete execution ${executionId}:`, error);
throw new Error(`Failed to delete execution ${executionId} from n8n`);
}
}
// Health and Status
async getHealth(): Promise<{ status: string }> {
try {
const response = await this.client.get('/health');
return response.data;
} catch (error) {
console.error('Failed to check n8n health:', error);
throw new Error('Failed to check n8n health');
}
}
// Credentials Management (if needed)
async getCredentials(): Promise<any[]> {
try {
const response = await this.client.get('/credentials');
return response.data.data || response.data;
} catch (error) {
console.error('Failed to fetch credentials:', error);
throw new Error('Failed to fetch credentials from n8n');
}
}
// Test connection
async testConnection(): Promise<boolean> {
try {
await this.getHealth();
return true;
} catch (error) {
return false;
}
}
}
// Factory function to create n8n service instance
export const createN8nService = (config: N8nConfig): N8nService => {
return new N8nService(config);
};
// Default instance using environment variables
export const n8nService = createN8nService({
baseUrl: process.env.N8N_BASE_URL || 'https://bot.ai-impress.com',
apiToken: process.env.N8N_API_TOKEN || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1OWQyN2Q0ZS1jNTU3LTQxMDUtYjZmMy05Y2JmM2U5MzU1NWUiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwiaWF0IjoxNzU5MDc1NDI4fQ.HCnDOPdq8GcphuPpz1o9871VOLbpMvd7m8C47e2Kq50',
});
export default n8nService;
export type { N8nWorkflow, WorkflowData, ExecutionResult, N8nConfig };