import { Request, Response } from 'express'; import { pool } from '../db/connection'; import { AuthRequest } from '../middleware/auth'; import { n8nService } from '../services/n8nService'; export const getTemplates = async (req: AuthRequest, res: Response) => { try { const { category, search } = req.query; const userRole = req.user?.role || 'free'; // Build query for local templates let queryText = ` SELECT id, name, description, category, trigger_type, tags, is_featured, install_count, created_at FROM templates WHERE 1=1 `; const params: any[] = []; let paramCount = 0; if (category) { paramCount++; queryText += ` AND category = $${paramCount}`; params.push(category); } if (search) { paramCount++; queryText += ` AND (name ILIKE $${paramCount} OR description ILIKE $${paramCount})`; params.push(`%${search}%`); } queryText += ' ORDER BY is_featured DESC, install_count DESC, created_at DESC'; // Get local templates const localResult = await pool.query(queryText, params); let templates = localResult.rows.map(template => ({ ...template, source: 'local' })); // For admin users, also fetch templates from n8n if (userRole === 'admin') { try { const n8nWorkflows = await n8nService.getWorkflows(); const n8nTemplates = n8nWorkflows.map(workflow => ({ id: `n8n_${workflow.id}`, name: workflow.name, description: `N8n workflow: ${workflow.name}`, category: 'n8n', trigger_type: 'n8n_workflow', tags: ['n8n', 'automation'], is_featured: false, install_count: 0, created_at: workflow.createdAt, source: 'n8n', n8n_workflow_id: workflow.id, n8n_data: workflow })); // Filter n8n templates if search is provided if (search) { const searchTerm = search.toString().toLowerCase(); const filteredN8nTemplates = n8nTemplates.filter(template => template.name.toLowerCase().includes(searchTerm) || template.description.toLowerCase().includes(searchTerm) ); templates = [...templates, ...filteredN8nTemplates]; } else { templates = [...templates, ...n8nTemplates]; } } catch (n8nError) { console.error('Error fetching n8n workflows:', n8nError); // Continue with local templates only } } res.json({ success: true, templates: templates }); } catch (error) { console.error('Get templates error:', error); res.status(500).json({ success: false, message: 'Internal server error' }); } }; export const installTemplate = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; const { workflow_name } = req.body; // Check if it's an n8n template if (id.startsWith('n8n_')) { const n8nWorkflowId = id.replace('n8n_', ''); try { // Get the n8n workflow const n8nWorkflow = await n8nService.getWorkflow(n8nWorkflowId); // Create workflow in our database that references the n8n workflow const workflowResult = await pool.query( `INSERT INTO workflows (user_id, name, description, trigger_type, n8n_workflow_id, status, is_active) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id`, [ req.user?.id, workflow_name || n8nWorkflow.name, `N8n workflow: ${n8nWorkflow.name}`, 'n8n_workflow', n8nWorkflowId, 'connected', n8nWorkflow.active ] ); const workflowId = workflowResult.rows[0].id; res.status(201).json({ success: true, message: 'N8n workflow connected successfully', workflow_id: workflowId, n8n_workflow_id: n8nWorkflowId }); } catch (n8nError) { console.error('Error connecting n8n workflow:', n8nError); return res.status(500).json({ success: false, message: 'Failed to connect n8n workflow' }); } } else { // Handle local template installation const template = await pool.query('SELECT * FROM templates WHERE id = $1', [id]); if (template.rows.length === 0) { return res.status(404).json({ success: false, message: 'Template not found' }); } const templateData = template.rows[0]; const workflowName = workflow_name || templateData.name; // Check user's workflow limit const userQuery = await pool.query('SELECT workflow_limit FROM users WHERE id = $1', [req.user?.id]); const userWorkflowLimit = userQuery.rows[0]?.workflow_limit || 3; const currentWorkflowsQuery = await pool.query( 'SELECT COUNT(*) as count FROM workflows WHERE user_id = $1', [req.user?.id] ); const currentWorkflowCount = parseInt(currentWorkflowsQuery.rows[0].count); if (userWorkflowLimit !== -1 && currentWorkflowCount >= userWorkflowLimit) { return res.status(403).json({ success: false, message: 'Workflow limit reached. Please upgrade your plan to create more workflows.' }); } const workflowResult = await pool.query( `INSERT INTO workflows (user_id, name, description, trigger_type, trigger_config, actions_config) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id`, [req.user?.id, workflowName, templateData.description, templateData.trigger_type, templateData.trigger_config, templateData.actions_config] ); const workflowId = workflowResult.rows[0].id; await pool.query( 'INSERT INTO user_templates (user_id, template_id, workflow_id) VALUES ($1, $2, $3)', [req.user?.id, id, workflowId] ); await pool.query( 'UPDATE templates SET install_count = install_count + 1 WHERE id = $1', [id] ); res.status(201).json({ success: true, message: 'Template installed successfully', workflow_id: workflowId }); } } catch (error) { console.error('Install template error:', error); res.status(500).json({ success: false, message: 'Internal server error' }); } };