n8n-nodes-close-crm
Version:
N8N community node for Close CRM integration with comprehensive lead, opportunity, task, note, and call management
146 lines (145 loc) • 7.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.closeApiRequest = closeApiRequest;
exports.closeApiRequestAllItems = closeApiRequestAllItems;
const n8n_workflow_1 = require("n8n-workflow");
async function closeApiRequest(method, resource, body = {}, qs = {}, option = {}) {
var _a, _b, _c, _d;
const options = {
headers: {
'Content-Type': 'application/json',
},
method,
qs,
body,
uri: `https://api.close.com/api/v1${resource}`,
json: true,
};
if (Object.keys(body).length === 0) {
delete options.body;
}
if (Object.keys(option).length !== 0) {
Object.assign(options, option);
}
try {
const credentials = await this.getCredentials('closeApi');
if (!credentials || !credentials.apiKey) {
throw new Error('Close API credentials are missing or invalid');
}
options.auth = {
user: credentials.apiKey,
pass: '',
};
// Disable automatic JSON parsing to handle responses manually
const requestOptions = { ...options, json: false };
const response = await this.helpers.request(requestOptions);
// Handle empty responses (common for successful updates/deletes)
if (!response || response === '') {
return {};
}
// Validate and parse JSON response
try {
if (typeof response === 'string') {
return JSON.parse(response);
}
return response;
}
catch (parseError) {
// Log the actual response content for debugging
const responsePreview = typeof response === 'string'
? response.substring(0, 200)
: String(response).substring(0, 200);
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: 'Invalid JSON response from Close CRM API',
description: `The API returned a non-JSON response. Response preview: "${responsePreview}"`
});
}
}
catch (error) {
// Handle JSON parsing errors specifically
if (((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('Expecting value')) || ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes('JSON'))) {
const responseBody = ((_c = error.response) === null || _c === void 0 ? void 0 : _c.body) || ((_d = error.response) === null || _d === void 0 ? void 0 : _d.data) || 'No response body';
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: 'Failed to parse Close CRM API response',
description: `The API response could not be parsed as JSON. This might indicate an empty response or server error. Response: ${responseBody}`
});
}
if (error.response) {
const statusCode = error.response.status || error.response.statusCode;
const responseBody = error.response.body || error.response.data;
let errorMessage = 'Unknown error';
// Try to extract error message from various response formats
if (typeof responseBody === 'string') {
try {
const parsedBody = JSON.parse(responseBody);
errorMessage = parsedBody.error || parsedBody.message || parsedBody.detail || responseBody;
}
catch {
errorMessage = responseBody;
}
}
else if (responseBody && typeof responseBody === 'object') {
errorMessage = responseBody.error || responseBody.message || responseBody.detail || JSON.stringify(responseBody);
}
switch (statusCode) {
case 400:
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: 'Bad Request - Invalid data sent to Close CRM',
description: `The request data is invalid. Error: ${errorMessage}. Please check your input data and field values.`
});
case 401:
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: 'Invalid API key. Please check your Close CRM credentials.',
description: 'The API key provided is not valid or has expired.'
});
case 403:
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: 'Access forbidden. Your API key does not have permission for this operation.',
description: 'Check that your Close account has the necessary permissions.'
});
case 404:
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: 'Resource not found.',
description: 'The requested resource does not exist or may have been deleted.'
});
case 422:
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: 'Validation Error - Invalid field values',
description: `The data validation failed. Error: ${errorMessage}. Please check that all required fields are provided and field values are valid.`
});
case 429:
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: 'Rate limit exceeded. Please try again later.',
description: 'You have made too many requests. Please wait before trying again.'
});
case 500:
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: 'Close CRM server error. Please try again later.',
description: 'There was an internal server error on Close CRM\'s side.'
});
default:
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: `Close CRM API error (${statusCode}): ${errorMessage}`,
description: `An unexpected error occurred while communicating with Close CRM. Request: ${method} ${options.uri}`
});
}
}
// Handle network errors, timeouts, etc.
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: error.message || 'Unknown error occurred',
description: `An error occurred while making the request to Close CRM. Details: ${error.message || 'No additional details available'}`
});
}
}
async function closeApiRequestAllItems(propertyName, method, endpoint, body = {}, query = {}) {
const returnData = [];
let responseData;
query._limit = 100;
query._skip = 0;
do {
responseData = await closeApiRequest.call(this, method, endpoint, body, query);
query._skip = returnData.length;
returnData.push.apply(returnData, responseData[propertyName]);
} while (responseData.has_more !== false);
return returnData;
}