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
JavaScript
;
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;