import type { IDataObject, IExecuteFunctions, ILoadOptionsFunctions, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription, } from 'n8n-workflow'; import { lonescaleApiRequest } from './GenericFunctions'; export class LoneScale implements INodeType { description: INodeTypeDescription = { displayName: 'LoneScale', name: 'loneScale', group: ['transform'], icon: 'file:lonescale-logo.svg', version: 1, description: 'Create List, add / delete items', subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}', defaults: { name: 'LoneScale', }, inputs: ['main'], outputs: ['main'], credentials: [ { name: 'loneScaleApi', required: true, }, ], properties: [ { displayName: 'Resource', name: 'resource', type: 'options', options: [ { name: 'List', value: 'list', description: 'Manipulate list', }, { name: 'Item', value: 'item', description: 'Manipulate item', }, ], default: 'list', noDataExpression: true, required: true, description: 'Create a new list', }, { displayName: 'Operation', name: 'operation', type: 'options', displayOptions: { show: { resource: ['list'], }, }, options: [ { name: 'Create', value: 'create', description: 'Create a list', action: 'Create a list', }, ], default: 'create', noDataExpression: true, }, { displayName: 'Operation', name: 'operation', type: 'options', displayOptions: { show: { resource: ['item'], }, }, options: [ { name: 'Create', value: 'add', description: 'Create an item', action: 'Create a item', }, ], default: 'add', noDataExpression: true, }, { displayName: 'Type', name: 'type', type: 'options', required: true, displayOptions: { show: { resource: ['item'], }, }, options: [ { name: 'Company', value: 'COMPANY', description: 'List of company', }, { name: 'Contact', value: 'PEOPLE', description: 'List of contact', }, ], default: 'PEOPLE', description: 'Type of your list', noDataExpression: true, }, { displayName: 'List Name or ID', name: 'list', type: 'options', displayOptions: { show: { resource: ['item'], }, }, typeOptions: { loadOptionsMethod: 'getLists', loadOptionsDependsOn: ['type'], }, default: '', description: 'Choose from the list, or specify an ID using an expression', required: true, }, { displayName: 'First Name', name: 'first_name', type: 'string', displayOptions: { show: { operation: ['add'], resource: ['item'], type: ['PEOPLE'], }, }, default: '', description: 'Contact first name', required: true, }, { displayName: 'Last Name', name: 'last_name', type: 'string', displayOptions: { show: { operation: ['add'], resource: ['item'], type: ['PEOPLE'], }, }, default: '', description: 'Contact last name', required: true, }, { displayName: 'Company Name', name: 'company_name', type: 'string', displayOptions: { show: { operation: ['add'], resource: ['item'], type: ['COMPANY'], }, }, default: '', description: 'Contact company name', }, { displayName: 'Additional Fields', name: 'peopleAdditionalFields', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { operation: ['add'], resource: ['item'], type: ['PEOPLE'], }, }, options: [ { displayName: 'Full Name', name: 'full_name', type: 'string', default: '', description: 'Contact full name', }, { displayName: 'Contact Email', name: 'email', type: 'string', placeholder: 'name@email.com', default: '', }, { displayName: 'Company Name', name: 'company_name', type: 'string', default: '', description: 'Contact company name', }, { displayName: 'Current Position', name: 'current_position', type: 'string', default: '', description: 'Contact current position', }, { displayName: 'Company Domain', name: 'domain', type: 'string', default: '', description: 'Contact company domain', }, { displayName: 'Linkedin Url', name: 'linkedin_url', type: 'string', default: '', description: 'Contact Linkedin URL', }, { displayName: 'Contact Location', name: 'location', type: 'string', default: '', }, { displayName: 'Contact ID', name: 'contact_id', type: 'string', default: '', description: 'Contact ID from your source', }, ], }, { displayName: 'Additional Fields', name: 'companyAdditionalFields', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { operation: ['add'], resource: ['item'], type: ['COMPANY'], }, }, options: [ { displayName: 'Linkedin Url', name: 'linkedin_url', type: 'string', default: '', description: 'Company Linkedin URL', }, { displayName: 'Company Domain', name: 'domain', type: 'string', default: '', description: 'Company company domain', }, { displayName: 'Contact Location', name: 'location', type: 'string', default: '', }, { displayName: 'Contact ID', name: 'contact_id', type: 'string', default: '', description: 'Contact ID from your source', }, ], }, { displayName: 'Name', name: 'name', type: 'string', required: true, displayOptions: { show: { operation: ['create'], resource: ['list'], }, }, default: '', placeholder: 'list name', description: 'Name of your list', }, { displayName: 'Type', name: 'type', type: 'options', required: true, displayOptions: { show: { operation: ['create'], resource: ['list'], }, }, options: [ { name: 'Company', value: 'COMPANY', description: 'Create a list of companies', action: 'Create a list of companies', }, { name: 'Contact', value: 'PEOPLE', description: 'Create a list of contacts', action: 'Create a list of contacts', }, ], default: 'COMPANY', description: 'Type of your list', noDataExpression: true, }, ], }; methods = { loadOptions: { async getLists(this: ILoadOptionsFunctions): Promise { const type = this.getNodeParameter('type') as string; const data = await lonescaleApiRequest.call(this, 'GET', '/lists', {}, { entity: type }); return (data as { list: Array<{ name: string; id: string; entity: string }> })?.list ?.filter((l) => l.entity === type) .map((d) => ({ name: d.name, value: d.id, })); }, }, }; async execute(this: IExecuteFunctions): Promise { const items = this.getInputData(); let responseData; const returnData = []; const resource = this.getNodeParameter('resource', 0); const operation = this.getNodeParameter('operation', 0); for (let i = 0; i < items.length; i++) { try { if (resource === 'list') { if (operation === 'create') { const name = this.getNodeParameter('name', i) as string; const entity = this.getNodeParameter('type', i) as string; const body: IDataObject = { name, entity, }; responseData = await lonescaleApiRequest.call(this, 'POST', '/lists', body); const executionData = this.helpers.constructExecutionMetaData( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this.helpers.returnJsonArray(responseData), { itemData: { item: i } }, ); returnData.push(...executionData); } } if (resource === 'item') { if (operation === 'add') { let firstName = ''; let lastName = ''; let currentPosition = ''; let fullName = ''; let email = ''; let linkedinUrl = ''; let companyName = ''; let domain = ''; let location = ''; let contactId = ''; const entity = this.getNodeParameter('type', i) as string; const listId = this.getNodeParameter('list', i) as string; if (entity === 'PEOPLE') { const peopleAdditionalFields = this.getNodeParameter('peopleAdditionalFields', i) as { email: string; full_name: string; current_position: string; linkedin_url: string; company_name: string; domain: string; location: string; contact_id: string; }; firstName = this.getNodeParameter('first_name', i) as string; lastName = this.getNodeParameter('last_name', i) as string; fullName = peopleAdditionalFields?.full_name; currentPosition = peopleAdditionalFields?.current_position; email = peopleAdditionalFields?.email; linkedinUrl = peopleAdditionalFields?.linkedin_url; companyName = peopleAdditionalFields?.company_name; domain = peopleAdditionalFields?.domain; location = peopleAdditionalFields?.location; contactId = peopleAdditionalFields?.contact_id; } if (entity === 'COMPANY') { const companyAdditionalFields = this.getNodeParameter( 'companyAdditionalFields', i, ) as { linkedin_url: string; domain: string; location: string; contact_id: string; }; companyName = this.getNodeParameter('company_name', i) as string; linkedinUrl = companyAdditionalFields?.linkedin_url; domain = companyAdditionalFields?.domain; location = companyAdditionalFields?.location; contactId = companyAdditionalFields?.contact_id; } const body: IDataObject = { ...(firstName && { first_name: firstName }), ...(lastName && { last_name: lastName }), ...(fullName && { full_name: fullName }), ...(linkedinUrl && { linkedin_url: linkedinUrl }), ...(companyName && { company_name: companyName }), ...(currentPosition && { current_position: currentPosition }), ...(domain && { domain }), ...(location && { location }), ...(email && { email }), ...(contactId && { contact_id: contactId }), }; responseData = await lonescaleApiRequest.call( this, 'POST', `/lists/${listId}/item`, body, ); const executionData = this.helpers.constructExecutionMetaData( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this.helpers.returnJsonArray(responseData), { itemData: { item: i } }, ); returnData.push(...executionData); } } } catch (error) { if (this.continueOnFail()) { const executionData = this.helpers.constructExecutionMetaData( this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } }, ); returnData.push(...executionData); continue; } throw error; } } return this.prepareOutputData(returnData); } }