UNPKG

n8n-nodes-inflow-crm

Version:

Official Inflow CRM integration for n8n. Create, update, search records and handle webhooks with dynamic field support.

110 lines (109 loc) 5.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.executeSearchAction = void 0; const api_1 = require("../../lib/api"); const endpoints_1 = require("../../lib/endpoints"); const logger_1 = require("../../lib/logger"); const fieldsAccess_1 = require("../../access/fieldsAccess"); /** * Removes all boolean fields with value false from the filter object (shallow). * This is to avoid sending default false values auto-added by the UI. */ function cleanFilterObject(filter) { if (!filter || typeof filter !== 'object') return filter; const cleaned = {}; for (const [key, value] of Object.entries(filter)) { if (typeof value === 'boolean' && value === false) { continue; // skip unwanted false booleans } cleaned[key] = value; } return cleaned; } async function executeSearchAction(itemIndex, moduleName, searchFields, options) { // Context and parameter validation if (!this || typeof this.getNodeParameter !== 'function') { throw new Error('Context error: IExecuteFunctions context is required'); } if (!moduleName || typeof moduleName !== 'string') { throw new Error('module name is required'); } if (!searchFields || typeof searchFields !== 'object') { throw new Error('searchFields must be an object'); } logger_1.actionsLogger.info(`Searching records in module: ${moduleName}`); logger_1.actionsLogger.info('Original searchFields:', JSON.stringify(searchFields, null, 2)); let cleanedSearchFields = cleanFilterObject(searchFields); logger_1.actionsLogger.info('Cleaned searchFields:', JSON.stringify(cleanedSearchFields, null, 2)); // Fetch valid API field names for the module const validFieldNames = await (0, fieldsAccess_1.getValidApiFieldNames)(moduleName, this); logger_1.actionsLogger.info('Valid API field names:', validFieldNames); // Process fields with relationships (e.g., process fields that need to be split into process ID and stage) cleanedSearchFields = (0, fieldsAccess_1.processFieldsWithRelationships)(cleanedSearchFields, validFieldNames); logger_1.actionsLogger.info('Processed searchFields:', JSON.stringify(cleanedSearchFields, null, 2)); logger_1.actionsLogger.info('Options:', JSON.stringify(options, null, 2)); try { // Validate limit const limit = options.limit ?? 50; if (limit > 200) { throw new Error('The maximum allowed value for "limit" is 200. Please set a value between 1 and 200.'); } if (limit < 1) { throw new Error('The minimum allowed value for "limit" is 1. Please set a value between 1 and 200.'); } // Build request body per new API spec const requestBody = { module: moduleName, page: options.page || 1, limit, }; // Sorting if (options.sortField && options.sortField.trim()) { requestBody.sort = { [options.sortField.trim()]: options.sortDirection === 'desc' ? -1 : 1, }; } // Filtering if (cleanedSearchFields && Object.keys(cleanedSearchFields).length > 0) { requestBody.filters = cleanedSearchFields; } logger_1.actionsLogger.info('Request body:', JSON.stringify(requestBody, null, 2)); let response; try { response = await (0, api_1.inflowApiRequest)(this, 'POST', endpoints_1.Endpoints.SEARCH_RECORDS, requestBody); } catch (apiError) { logger_1.actionsLogger.error('API request failed with error:', apiError); if (apiError?.error && apiError.error.code) { throw new Error(`[${apiError.error.code}] ${apiError.error.message}`); } throw apiError; } logger_1.actionsLogger.info('API Response:', JSON.stringify(response, null, 2)); // Expect { data: [...], meta } if (response && typeof response === 'object' && 'data' in response) { const { data, meta } = response; if (!Array.isArray(data)) { logger_1.actionsLogger.warn('Search returned non-array data for', moduleName, '.'); return [{ json: { success: true, count: 0, data: [], meta }, pairedItem: { item: itemIndex } }]; } // n8n expects an array of INodeExecutionData // Include meta information in each record for transparency return data.map(record => ({ json: { ...record, meta }, pairedItem: { item: itemIndex } })); } logger_1.actionsLogger.error('Unexpected API response format:', response); throw new Error('API returned unexpected response format'); } catch (error) { logger_1.actionsLogger.error('Error searching records:', error); if (error?.error && error.error.code) { throw new Error(`[${error.error.code}] ${error.error.message}`); } throw new Error(`Failed to search records in "${moduleName}": ${error.message || 'unknown error'}`); } } exports.executeSearchAction = executeSearchAction;