UNPKG

n8n-nodes-mautic-advanced

Version:

Enhanced n8n node for Mautic with comprehensive API coverage including tags, campaigns, categories, and advanced contact management

159 lines (158 loc) 6.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateJSON = exports.serialiseMauticWhere = exports.mauticApiRequestAllItems = exports.mauticApiRequest = void 0; const n8n_workflow_1 = require("n8n-workflow"); async function mauticApiRequest(method, endpoint, body = {}, query, uri) { const authenticationMethod = this.getNodeParameter('authentication', 0, 'credentials'); const options = { headers: {}, method, qs: query, uri: uri || `/api${endpoint}`, body, json: true, }; try { let returnData; if (authenticationMethod === 'credentials') { const credentials = await this.getCredentials('mauticAdvancedApi'); const baseUrl = credentials.url; options.uri = `${baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl}${options.uri}`; returnData = await this.helpers.requestWithAuthentication.call(this, 'mauticAdvancedApi', options); } else { const credentials = await this.getCredentials('mauticAdvancedOAuth2Api'); const baseUrl = credentials.url; options.uri = `${baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl}${options.uri}`; returnData = await this.helpers.requestOAuth2.call(this, 'mauticAdvancedOAuth2Api', options, { includeCredentialsOnRefreshOnBody: true, }); } if (returnData.errors) { // They seem to sometimes return 200 status but still error. throw new n8n_workflow_1.NodeApiError(this.getNode(), returnData); } return returnData; } catch (error) { throw new n8n_workflow_1.NodeApiError(this.getNode(), error); } } exports.mauticApiRequest = mauticApiRequest; /** * Make an API request to paginated mautic endpoint * and return all results */ // Optional: Slightly improved error handling async function mauticApiRequestAllItems(propertyName, method, endpoint, body = {}, query = {}, maxResults) { const returnData = []; let responseData; query.limit = 30; query.start = 0; while (true) { try { responseData = await mauticApiRequest.call(this, method, endpoint, body, query); if (responseData.errors) { throw new n8n_workflow_1.NodeApiError(this.getNode(), responseData); } const pageItems = responseData[propertyName] ? Object.values(responseData[propertyName]) : []; if (!pageItems.length) { break; } if (maxResults !== undefined && returnData.length + pageItems.length > maxResults) { const needed = maxResults - returnData.length; returnData.push(...pageItems.slice(0, needed)); break; } else { returnData.push(...pageItems); } query.start = Number(query.start) + pageItems.length; // If less than limit returned, no more data if (pageItems.length < Number(query.limit)) { break; } } catch (error) { // Optional: Only wrap non-NodeApiError errors if (error instanceof n8n_workflow_1.NodeApiError) { throw error; } throw new n8n_workflow_1.NodeApiError(this.getNode(), error); } } return returnData; } exports.mauticApiRequestAllItems = mauticApiRequestAllItems; /** * Serialise the n8n fixedCollection 'where' structure into Mautic API query parameters. * Handles nested andX/orX logic recursively. * @param whereArray Array of conditions from the fixedCollection * @param prefix Used internally for recursion (should be omitted by callers) * @returns Object with keys/values for qs */ function serialiseMauticWhere(whereArray, prefix = 'where') { const params = {}; const dateFields = [ 'date_modified', 'date_added', 'last_active', 'date_identified', 'dateFrom', 'dateTo', ]; whereArray.forEach((condition, idx) => { const base = `${prefix}[${idx}]`; if (condition.expr === 'andX' || condition.expr === 'orX') { params[`${base}[expr]`] = condition.expr; // Nested conditions: recurse if (condition.nested && Array.isArray(condition.nested.conditions)) { // The value for 'val' is an array of nested conditions const nestedParams = serialiseMauticWhere(condition.nested.conditions, `${base}[val]`); Object.assign(params, nestedParams); } else { // Defensive: empty group params[`${base}[val]`] = []; } } else { // Simple condition if (condition.col) params[`${base}[col]`] = condition.col; if (condition.expr) params[`${base}[expr]`] = condition.expr; if (condition.val !== undefined && condition.val !== '') { let val = condition.val; // Auto-format date values for known date fields if (condition.col && dateFields.includes(condition.col) && typeof val === 'string' && (val.includes('T') || val.match(/^\d{4}-\d{2}-\d{2}/))) { // Try to parse and format as UTC 'YYYY-MM-DD HH:mm:ss' const d = new Date(val); if (!isNaN(d.getTime())) { const pad = (n) => n.toString().padStart(2, '0'); val = `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}`; } } params[`${base}[val]`] = val; } } }); return params; } exports.serialiseMauticWhere = serialiseMauticWhere; function validateJSON(json) { let result; try { result = JSON.parse(json); } catch (exception) { result = undefined; } return result; } exports.validateJSON = validateJSON;