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