n8n-nodes-attio
Version:
n8n node for Attio API integration
372 lines • 17.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Attio = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const n8n_openapi_node_1 = require("@devlikeapro/n8n-openapi-node");
const doc = __importStar(require("./openapi.json"));
const config = {};
const parser = new n8n_openapi_node_1.N8NPropertiesBuilder(doc, config);
const properties = parser.build();
function makeOperationNameFriendly(name) {
const match = name.match(/^(GET|POST|PUT|PATCH|DELETE)\s+(.+)$/);
if (!match)
return name;
const [, method, path] = match;
const patterns = [
[/^\/v2\/objects$/, () => method === 'GET' ? 'List Objects' : 'Create Object'],
[/^\/v2\/objects\/\{object\}$/, () => {
switch (method) {
case 'GET': return 'Get Object';
case 'PATCH': return 'Update Object';
case 'DELETE': return 'Delete Object';
default: return `${method} Object`;
}
}],
[/^\/v2\/objects\/\{object\}\/records\/query$/, () => 'List Records'],
[/^\/v2\/objects\/\{object\}\/records$/, () => {
switch (method) {
case 'POST': return 'Create Record';
case 'PUT': return 'Assert Record';
default: return `${method} Records`;
}
}],
[/^\/v2\/objects\/\{object\}\/records\/\{record_id\}$/, () => {
switch (method) {
case 'GET': return 'Get Record';
case 'PUT': return 'Update Record (Overwrite)';
case 'PATCH': return 'Update Record (Append)';
case 'DELETE': return 'Delete Record';
default: return `${method} Record`;
}
}],
[/^\/v2\/objects\/\{object\}\/records\/\{record_id\}\/attributes$/, () => 'List Record Attributes'],
[/^\/v2\/objects\/\{object\}\/records\/\{record_id\}\/entries$/, () => 'List Record Entries'],
[/^\/v2\/\{target\}\/\{identifier\}\/attributes$/, () => method === 'GET' ? 'List Attributes' : 'Create Attribute'],
[/^\/v2\/\{target\}\/\{identifier\}\/attributes\/\{attribute\}$/, () => {
switch (method) {
case 'GET': return 'Get Attribute';
case 'PATCH': return 'Update Attribute';
case 'DELETE': return 'Delete Attribute';
default: return `${method} Attribute`;
}
}],
[/^\/v2\/lists$/, () => method === 'GET' ? 'List Lists' : 'Create List'],
[/^\/v2\/lists\/\{list\}$/, () => {
switch (method) {
case 'GET': return 'Get List';
case 'DELETE': return 'Delete List';
default: return `${method} List`;
}
}],
[/^\/v2\/lists\/\{list\}\/entries\/query$/, () => 'List Entries'],
[/^\/v2\/lists\/\{list\}\/entries$/, () => 'Create Entry'],
[/^\/v2\/lists\/\{list\}\/entries\/\{entry_id\}$/, () => {
switch (method) {
case 'GET': return 'Get Entry';
case 'PUT': return 'Update Entry (Overwrite)';
case 'PATCH': return 'Update Entry (Append)';
case 'DELETE': return 'Delete Entry';
default: return `${method} Entry`;
}
}],
[/^\/v2\/lists\/\{list\}\/entries\/\{entry_id\}\/attributes$/, () => 'List Entry Attributes'],
[/^\/v2\/workspace_members$/, () => 'List Workspace Members'],
[/^\/v2\/workspace_members\/\{workspace_member_id\}$/, () => 'Get Workspace Member'],
[/^\/v2\/notes$/, () => method === 'GET' ? 'List Notes' : 'Create Note'],
[/^\/v2\/notes\/\{note_id\}$/, () => {
switch (method) {
case 'GET': return 'Get Note';
case 'DELETE': return 'Delete Note';
default: return `${method} Note`;
}
}],
[/^\/v2\/tasks$/, () => method === 'GET' ? 'List Tasks' : 'Create Task'],
[/^\/v2\/tasks\/\{task_id\}$/, () => {
switch (method) {
case 'GET': return 'Get Task';
case 'PATCH': return 'Update Task';
case 'DELETE': return 'Delete Task';
default: return `${method} Task`;
}
}],
[/^\/v2\/threads\/\{thread_id\}\/comments$/, () => method === 'GET' ? 'List Comments' : 'Create Comment'],
[/^\/v2\/comments\/\{comment_id\}$/, () => {
switch (method) {
case 'GET': return 'Get Comment';
case 'DELETE': return 'Delete Comment';
default: return `${method} Comment`;
}
}],
[/^\/v2\/webhooks$/, () => method === 'GET' ? 'List Webhooks' : 'Create Webhook'],
[/^\/v2\/webhooks\/\{webhook_id\}$/, () => {
switch (method) {
case 'GET': return 'Get Webhook';
case 'PATCH': return 'Update Webhook';
case 'DELETE': return 'Delete Webhook';
default: return `${method} Webhook`;
}
}],
[/^\/v2\/self$/, () => 'Get Current User'],
];
for (const [pattern, getName] of patterns) {
if (pattern.test(path)) {
return typeof getName === 'function' ? getName() : getName;
}
}
return `${method} ${path.replace(/^\/v2\//, '').replace(/[{}]/g, '')}`;
}
const operationMapping = {};
const friendlyNameMapping = {};
const transformedProperties = properties.map((prop) => {
if (prop.name === 'operation' && prop.options) {
const transformedOptions = prop.options.map((opt) => {
const friendlyName = makeOperationNameFriendly(opt.name);
operationMapping[opt.name] = opt.value;
friendlyNameMapping[opt.value] = friendlyName;
return {
...opt,
name: friendlyName,
originalName: opt.name,
};
});
return {
...prop,
options: transformedOptions,
};
}
return prop;
});
const fixedProperties = transformedProperties.map((prop) => {
var _a, _b;
if ((_b = (_a = prop.displayOptions) === null || _a === void 0 ? void 0 : _a.show) === null || _b === void 0 ? void 0 : _b.operation) {
return {
...prop,
displayOptions: {
...prop.displayOptions,
show: {
...prop.displayOptions.show,
operation: prop.displayOptions.show.operation.map((opName) => operationMapping[opName] || opName),
},
},
};
}
return prop;
});
class Attio {
constructor() {
this.description = {
displayName: 'Attio',
name: 'attio',
icon: 'file:attio.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["resource"]}}',
description: 'Interact with Attio API',
defaults: {
name: 'Attio',
},
inputs: ["main"],
outputs: ["main"],
credentials: [
{
name: 'attioApi',
required: true,
},
],
requestDefaults: {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
properties: fixedProperties,
usableAsTool: true,
};
}
async execute() {
var _a, _b, _c;
const items = this.getInputData();
const returnData = [];
const credentials = await this.getCredentials('attioApi');
for (let i = 0; i < items.length; i++) {
try {
const resource = this.getNodeParameter('resource', i);
const operation = this.getNodeParameter('operation', i);
const operationProperty = properties.find((prop) => {
var _a, _b, _c, _d;
return prop.name === 'operation' &&
((_c = (_b = (_a = prop.displayOptions) === null || _a === void 0 ? void 0 : _a.show) === null || _b === void 0 ? void 0 : _b.resource) === null || _c === void 0 ? void 0 : _c[0]) === resource &&
((_d = prop.options) === null || _d === void 0 ? void 0 : _d.find((opt) => opt.value === operation));
});
if (!operationProperty || !operationProperty.options) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Operation ${operation} not found for resource ${resource}`);
}
const operationConfig = operationProperty.options.find((opt) => opt.value === operation);
if (!operationConfig || !((_a = operationConfig.routing) === null || _a === void 0 ? void 0 : _a.request)) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Operation configuration not found for ${operation}`);
}
let { method, url } = operationConfig.routing.request;
if (url && url.startsWith('=')) {
url = url.substring(1);
}
const requestOptions = {
method,
url,
headers: {
'Authorization': `Bearer ${credentials.accessToken}`,
'Accept': 'application/json',
'Content-Type': 'application/json',
},
json: true,
};
const allProperties = properties.filter((prop) => {
var _a, _b, _c, _d, _e, _f;
return ((_c = (_b = (_a = prop.displayOptions) === null || _a === void 0 ? void 0 : _a.show) === null || _b === void 0 ? void 0 : _b.operation) === null || _c === void 0 ? void 0 : _c[0]) === operation &&
((_f = (_e = (_d = prop.displayOptions) === null || _d === void 0 ? void 0 : _d.show) === null || _e === void 0 ? void 0 : _e.resource) === null || _f === void 0 ? void 0 : _f[0]) === resource;
});
for (const prop of allProperties) {
const propAny = prop;
if (propAny.name === 'operation' || propAny.type === 'notice')
continue;
try {
const value = this.getNodeParameter(propAny.name, i, propAny.default);
if (value !== undefined && value !== null && value !== '') {
if ((_b = propAny.routing) === null || _b === void 0 ? void 0 : _b.send) {
const { type, property, value: valueExpression } = propAny.routing.send;
let processedValue = value;
if (valueExpression && typeof value === 'string') {
try {
if (propAny.type === 'json') {
processedValue = JSON.parse(value);
}
}
catch (e) {
}
}
switch (type) {
case 'body':
if (!requestOptions.body)
requestOptions.body = {};
requestOptions.body[property] = processedValue;
break;
case 'query':
if (processedValue !== undefined && processedValue !== null && processedValue !== '') {
if (!requestOptions.qs)
requestOptions.qs = {};
requestOptions.qs[property] = processedValue;
}
break;
}
}
}
}
catch (error) {
}
}
let finalUrl = requestOptions.url;
const n8nParamMatches = finalUrl.match(/\{\{\$parameter\["([^"]+)"\]\}\}/g);
if (n8nParamMatches) {
for (const match of n8nParamMatches) {
const paramName = (_c = match.match(/\{\{\$parameter\["([^"]+)"\]\}\}/)) === null || _c === void 0 ? void 0 : _c[1];
if (paramName) {
try {
const paramValue = this.getNodeParameter(paramName, i);
if (paramValue !== undefined && paramValue !== null) {
finalUrl = finalUrl.replace(match, String(paramValue));
}
}
catch (error) {
}
}
}
}
const simpleParamMatches = finalUrl.match(/\{([^}]+)\}/g);
if (simpleParamMatches) {
for (const match of simpleParamMatches) {
const paramName = match.replace(/[{}]/g, '');
try {
const paramValue = this.getNodeParameter(paramName, i);
if (paramValue !== undefined && paramValue !== null) {
finalUrl = finalUrl.replace(match, String(paramValue));
}
}
catch (error) {
}
}
}
if (!finalUrl.startsWith('http')) {
finalUrl = 'https://api.attio.com' + finalUrl;
}
requestOptions.url = finalUrl;
if (requestOptions.qs && Object.keys(requestOptions.qs).length === 0) {
delete requestOptions.qs;
}
const cleanRequestOptions = {
method: requestOptions.method,
url: requestOptions.url,
headers: requestOptions.headers,
json: requestOptions.json,
};
if (requestOptions.body && Object.keys(requestOptions.body).length > 0) {
cleanRequestOptions.body = requestOptions.body;
}
if (requestOptions.qs && Object.keys(requestOptions.qs).length > 0) {
cleanRequestOptions.qs = requestOptions.qs;
}
const response = await this.helpers.request(cleanRequestOptions);
returnData.push({
json: response,
pairedItem: { item: i },
});
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: error.message,
},
pairedItem: { item: i },
});
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.Attio = Attio;
//# sourceMappingURL=Attio.node.js.map