UNPKG

n8n-nodes-aixyte

Version:

Complete n8n node for Aixyte API - Manage Excites, Domains, and Files for personalized web experiences

802 lines (801 loc) 39.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Aixyte = void 0; const n8n_workflow_1 = require("n8n-workflow"); class Aixyte { constructor() { this.description = { displayName: 'Aixyte API', name: 'aixyte', icon: 'fa:rocket', group: ['output'], version: 4, description: 'Complete API for managing personalized web experiences - Excites, Domains, and Files (Rate limited: 300 requests/min)', defaults: { name: 'Aixyte API', color: '#772244', }, inputs: ["main" /* NodeConnectionType.Main */], outputs: ["main" /* NodeConnectionType.Main */], credentials: [ { name: 'aixyteApi', required: true, }, ], properties: [ // === UNIFIED OPERATIONS === { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, options: [ // EXCITE OPERATIONS { name: 'Excite: List', value: 'excite_list', description: 'Retrieve paginated list of excites with optional filtering' }, { name: 'Excite: Create', value: 'excite_create', description: 'Create a new excite with optional files' }, { name: 'Excite: Get', value: 'excite_get', description: 'Retrieve specific excite by ID with files' }, { name: 'Excite: Update', value: 'excite_update', description: 'Update existing excite and files' }, { name: 'Excite: Delete', value: 'excite_delete', description: 'Delete an excite permanently' }, // DOMAIN OPERATIONS { name: 'Domain: List', value: 'domain_list', description: 'Retrieve all domains with optional search' }, { name: 'Domain: Create', value: 'domain_create', description: 'Create a new domain configuration' }, { name: 'Domain: Get', value: 'domain_get', description: 'Retrieve specific domain by ID' }, { name: 'Domain: Update', value: 'domain_update', description: 'Update existing domain configuration' }, { name: 'Domain: Delete', value: 'domain_delete', description: 'Delete domain permanently' }, // FILE OPERATIONS { name: 'File: List', value: 'file_list', description: 'List all files for a specific excite' }, { name: 'File: Add', value: 'file_add', description: 'Add new file (photo/video) to an excite' }, { name: 'File: Update', value: 'file_update', description: 'Update existing file metadata' }, { name: 'File: Delete', value: 'file_delete', description: 'Remove file from excite' }, ], default: 'excite_list', description: 'Choose the operation to perform', }, // === ID PARAMETERS === { displayName: 'Excite ID', name: 'exciteId', type: 'string', required: true, displayOptions: { show: { operation: ['excite_get', 'excite_update', 'excite_delete'], }, }, default: '', description: 'UUID of the excite to operate on', placeholder: 'e.g. 123e4567-e89b-12d3-a456-426614174000', }, { displayName: 'Domain ID', name: 'domainId', type: 'string', required: true, displayOptions: { show: { operation: ['domain_get', 'domain_update', 'domain_delete'], }, }, default: '', description: 'UUID of the domain to operate on', placeholder: 'e.g. 123e4567-e89b-12d3-a456-426614174000', }, { displayName: 'Excite ID', name: 'fileExciteId', type: 'string', required: true, displayOptions: { show: { operation: ['file_list', 'file_add', 'file_update', 'file_delete'], }, }, default: '', description: 'UUID of the excite that owns the files', placeholder: 'e.g. 123e4567-e89b-12d3-a456-426614174000', }, { displayName: 'File ID', name: 'fileId', type: 'string', required: true, displayOptions: { show: { operation: ['file_update', 'file_delete'], }, }, default: '', description: 'UUID of the file to operate on', placeholder: 'e.g. 123e4567-e89b-12d3-a456-426614174000', }, // === EXCITE FIELDS === { displayName: 'Title', name: 'title', type: 'string', required: true, displayOptions: { show: { operation: ['excite_create', 'excite_update'], }, }, default: '', description: 'Display title for the excite (1-255 characters)', typeOptions: { validation: [ { type: 'minLength', properties: { minLength: 1, errorMessage: 'Title is required and must be at least 1 character', }, }, { type: 'maxLength', properties: { maxLength: 255, errorMessage: 'Title must be 255 characters or less', }, }, ], }, }, { displayName: 'Goal', name: 'goal', type: 'string', required: true, displayOptions: { show: { operation: ['excite_create', 'excite_update'], }, }, default: '', description: 'The objective or purpose of this excite (1-500 characters)', typeOptions: { validation: [ { type: 'minLength', properties: { minLength: 1, errorMessage: 'Goal is required and must be at least 1 character', }, }, { type: 'maxLength', properties: { maxLength: 500, errorMessage: 'Goal must be 500 characters or less', }, }, ], }, }, { displayName: 'Domain ID', name: 'exciteDomainId', type: 'string', required: true, displayOptions: { show: { operation: ['excite_create', 'excite_update'], }, }, default: '', description: 'UUID of the domain this excite belongs to', placeholder: 'e.g. 123e4567-e89b-12d3-a456-426614174000', }, { displayName: 'Slug', name: 'slug', type: 'string', required: true, displayOptions: { show: { operation: ['excite_create', 'excite_update'], }, }, default: '', description: 'URL-friendly identifier, unique per user (lowercase letters, numbers, hyphens only, 1-50 chars)', placeholder: 'e.g. my-awesome-excite', typeOptions: { validation: [ { type: 'minLength', properties: { minLength: 1, errorMessage: 'Slug is required and must be at least 1 character', }, }, { type: 'regex', properties: { regex: '^[a-z0-9-]+$', errorMessage: 'Slug must contain only lowercase letters, numbers, and hyphens', }, }, { type: 'maxLength', properties: { maxLength: 50, errorMessage: 'Slug must be 50 characters or less', }, }, ], }, }, { displayName: 'Is Global', name: 'isGlobal', type: 'boolean', displayOptions: { show: { operation: ['excite_create', 'excite_update'], }, }, default: false, description: 'When true, applies to entire domain; when false, applies only to specified paths', }, { displayName: 'Paths', name: 'paths', type: 'fixedCollection', displayOptions: { show: { operation: ['excite_create', 'excite_update'], }, }, default: {}, placeholder: 'Add Path', typeOptions: { multipleValues: true, }, options: [ { name: 'path', displayName: 'Path', values: [ { displayName: 'URL Path', name: 'value', type: 'string', default: '', placeholder: '/example-path', description: 'Specific URL path where this excite applies', }, ], }, ], description: 'Array of URL paths where this excite applies (ignored if is_global is true)', }, { displayName: 'Additional Data', name: 'additionalData', type: 'json', displayOptions: { show: { operation: ['excite_create', 'excite_update'], }, }, default: '{}', description: 'Custom JSON data for additional configuration or metadata', placeholder: '{"key": "value", "config": {"option": true}}', }, // === EXCITE FILES (for create/update) === { displayName: 'Files', name: 'exciteFiles', type: 'fixedCollection', displayOptions: { show: { operation: ['excite_create', 'excite_update'], }, }, default: {}, placeholder: 'Add File', typeOptions: { multipleValues: true, }, options: [ { name: 'file', displayName: 'File', values: [ { displayName: 'File Type', name: 'file_type', type: 'options', options: [ { name: 'Photo', value: 'photo' }, { name: 'Video', value: 'video' }, ], default: 'photo', description: 'Type of file', }, { displayName: 'File URL', name: 'file_url', type: 'string', default: '', placeholder: 'https://example.com/file.jpg', description: 'Direct URL to the file', }, { displayName: 'File Name', name: 'file_name', type: 'string', default: '', placeholder: 'My Photo', description: 'Display name for the file', }, { displayName: 'Description', name: 'description', type: 'string', default: '', placeholder: 'Optional file description', description: 'Optional description of the file', }, ], }, ], description: 'Files to attach to this excite (optional)', }, // === DOMAIN FIELDS === { displayName: 'Domain Name', name: 'domainName', type: 'string', displayOptions: { show: { operation: ['domain_create', 'domain_update'], }, }, default: '', description: 'Display name for the domain (1-100 characters)', typeOptions: { validation: [ { type: 'minLength', properties: { minLength: 1, errorMessage: 'Domain name must be at least 1 character', }, }, { type: 'maxLength', properties: { maxLength: 100, errorMessage: 'Domain name must be 100 characters or less', }, }, ], }, }, { displayName: 'Domain URL', name: 'domainUrl', type: 'string', required: true, displayOptions: { show: { operation: ['domain_create', 'domain_update'], }, }, default: '', description: 'The domain URL (1-255 characters)', placeholder: 'https://example.com', typeOptions: { validation: [ { type: 'minLength', properties: { minLength: 1, errorMessage: 'Domain URL is required', }, }, { type: 'maxLength', properties: { maxLength: 255, errorMessage: 'Domain URL must be 255 characters or less', }, }, ], }, }, // === FILE FIELDS === { displayName: 'File Type', name: 'fileType', type: 'options', required: true, displayOptions: { show: { operation: ['file_add', 'file_update'], }, }, options: [ { name: 'Photo', value: 'photo', description: 'Image file (JPG, PNG, etc.)' }, { name: 'Video', value: 'video', description: 'Video file (MP4, MOV, etc.)' }, ], default: 'photo', description: 'Type of file being uploaded', }, { displayName: 'File URL', name: 'fileUrl', type: 'string', required: true, displayOptions: { show: { operation: ['file_add', 'file_update'], }, }, default: '', description: 'Direct URL to the file', placeholder: 'https://example.com/files/image.jpg', }, { displayName: 'File Name', name: 'fileName', type: 'string', required: true, displayOptions: { show: { operation: ['file_add', 'file_update'], }, }, default: '', description: 'Display name for the file (1-255 characters)', typeOptions: { validation: [ { type: 'minLength', properties: { minLength: 1, errorMessage: 'File name is required', }, }, { type: 'maxLength', properties: { maxLength: 255, errorMessage: 'File name must be 255 characters or less', }, }, ], }, }, { displayName: 'Description', name: 'fileDescription', type: 'string', displayOptions: { show: { operation: ['file_add', 'file_update'], }, }, default: '', description: 'Optional description of the file (max 500 characters)', typeOptions: { validation: [ { type: 'maxLength', properties: { maxLength: 500, errorMessage: 'Description must be 500 characters or less', }, }, ], }, }, // === LIST PARAMETERS === { displayName: 'Limit', name: 'limit', type: 'number', displayOptions: { show: { operation: ['excite_list'], }, }, default: 10, description: 'Number of excites to return (1-100)', typeOptions: { minValue: 1, maxValue: 100, }, }, { displayName: 'Offset', name: 'offset', type: 'number', displayOptions: { show: { operation: ['excite_list'], }, }, default: 0, description: 'Number of excites to skip for pagination', typeOptions: { minValue: 0, }, }, { displayName: 'Search', name: 'search', type: 'string', displayOptions: { show: { operation: ['excite_list', 'domain_list'], }, }, default: '', description: 'Search term to filter results by title, goal, or domain', placeholder: 'Enter search term...', }, ], }; } async execute() { var _a, _b; const items = this.getInputData(); const returnData = []; const credentials = await this.getCredentials('aixyteApi'); const baseUrl = 'https://azxjgkopxmhwzvkxouuy.supabase.co/functions/v1/api'; for (let i = 0; i < items.length; i++) { try { const operation = this.getNodeParameter('operation', i); const options = { headers: { 'Authorization': `Bearer ${credentials.apiKey}`, 'Content-Type': 'application/json', }, method: 'GET', json: true, }; let responseData; // === EXCITE OPERATIONS === if (operation.startsWith('excite_')) { const exciteOp = operation.replace('excite_', ''); options.url = `${baseUrl}/excites`; switch (exciteOp) { case 'list': const limit = this.getNodeParameter('limit', i); const offset = this.getNodeParameter('offset', i); const search = this.getNodeParameter('search', i); options.qs = {}; if (limit) options.qs.limit = limit; if (offset) options.qs.offset = offset; if (search) options.qs.search = search; responseData = await this.helpers.request(options); if (responseData.data && Array.isArray(responseData.data)) { responseData.data.forEach((item) => { returnData.push({ json: item }); }); } break; case 'create': const title = this.getNodeParameter('title', i); const goal = this.getNodeParameter('goal', i); const exciteDomainId = this.getNodeParameter('exciteDomainId', i); const slug = this.getNodeParameter('slug', i); const isGlobal = this.getNodeParameter('isGlobal', i); const pathsCollection = this.getNodeParameter('paths', i); const additionalDataStr = this.getNodeParameter('additionalData', i); const exciteFilesCollection = this.getNodeParameter('exciteFiles', i); const paths = ((_a = pathsCollection === null || pathsCollection === void 0 ? void 0 : pathsCollection.path) === null || _a === void 0 ? void 0 : _a.map((p) => p.value)) || []; let additionalData = {}; try { additionalData = additionalDataStr ? JSON.parse(additionalDataStr) : {}; } catch (error) { additionalData = {}; } const files = (exciteFilesCollection === null || exciteFilesCollection === void 0 ? void 0 : exciteFilesCollection.file) || []; options.method = 'POST'; options.body = { title, goal, domain_id: exciteDomainId, slug, is_global: isGlobal, paths, additional_data: additionalData, files, }; responseData = await this.helpers.request(options); returnData.push({ json: responseData.data }); break; case 'get': const exciteId = this.getNodeParameter('exciteId', i); options.url += `/${exciteId}`; responseData = await this.helpers.request(options); returnData.push({ json: responseData.data }); break; case 'update': const updateExciteId = this.getNodeParameter('exciteId', i); const updateTitle = this.getNodeParameter('title', i); const updateGoal = this.getNodeParameter('goal', i); const updateDomainId = this.getNodeParameter('exciteDomainId', i); const updateSlug = this.getNodeParameter('slug', i); const updateIsGlobal = this.getNodeParameter('isGlobal', i); const updatePathsCollection = this.getNodeParameter('paths', i); const updateAdditionalDataStr = this.getNodeParameter('additionalData', i); const updateExciteFilesCollection = this.getNodeParameter('exciteFiles', i); const updatePaths = ((_b = updatePathsCollection === null || updatePathsCollection === void 0 ? void 0 : updatePathsCollection.path) === null || _b === void 0 ? void 0 : _b.map((p) => p.value)) || []; let updateAdditionalData = {}; try { updateAdditionalData = updateAdditionalDataStr ? JSON.parse(updateAdditionalDataStr) : {}; } catch (error) { updateAdditionalData = {}; } const updateFiles = (updateExciteFilesCollection === null || updateExciteFilesCollection === void 0 ? void 0 : updateExciteFilesCollection.file) || []; options.method = 'PUT'; options.url += `/${updateExciteId}`; options.body = { title: updateTitle, goal: updateGoal, domain_id: updateDomainId, slug: updateSlug, is_global: updateIsGlobal, paths: updatePaths, additional_data: updateAdditionalData, files: updateFiles, }; responseData = await this.helpers.request(options); returnData.push({ json: responseData.data }); break; case 'delete': const deleteExciteId = this.getNodeParameter('exciteId', i); options.method = 'DELETE'; options.url += `/${deleteExciteId}`; responseData = await this.helpers.request(options); returnData.push({ json: responseData.data || { message: 'excite deleted successfully' } }); break; } } // === DOMAIN OPERATIONS === else if (operation.startsWith('domain_')) { const domainOp = operation.replace('domain_', ''); options.url = `${baseUrl}/domains`; switch (domainOp) { case 'list': const domainSearch = this.getNodeParameter('search', i); if (domainSearch) { options.qs = { search: domainSearch }; } responseData = await this.helpers.request(options); if (responseData.data && Array.isArray(responseData.data)) { responseData.data.forEach((item) => { returnData.push({ json: item }); }); } break; case 'create': const domainName = this.getNodeParameter('domainName', i); const domainUrl = this.getNodeParameter('domainUrl', i); options.method = 'POST'; options.body = { name: domainName, domain: domainUrl, }; responseData = await this.helpers.request(options); returnData.push({ json: responseData.data }); break; case 'get': const getDomainId = this.getNodeParameter('domainId', i); options.url += `/${getDomainId}`; responseData = await this.helpers.request(options); returnData.push({ json: responseData.data }); break; case 'update': const updateDomainIdParam = this.getNodeParameter('domainId', i); const updateDomainName = this.getNodeParameter('domainName', i); const updateDomainUrl = this.getNodeParameter('domainUrl', i); options.method = 'PUT'; options.url += `/${updateDomainIdParam}`; options.body = { name: updateDomainName, domain: updateDomainUrl, }; responseData = await this.helpers.request(options); returnData.push({ json: responseData.data }); break; case 'delete': const deleteDomainId = this.getNodeParameter('domainId', i); options.method = 'DELETE'; options.url += `/${deleteDomainId}`; responseData = await this.helpers.request(options); returnData.push({ json: responseData.data || { message: 'domain deleted successfully' } }); break; } } // === FILE OPERATIONS === else if (operation.startsWith('file_')) { const fileOp = operation.replace('file_', ''); const fileExciteId = this.getNodeParameter('fileExciteId', i); switch (fileOp) { case 'list': options.url = `${baseUrl}/excites/${fileExciteId}/files`; responseData = await this.helpers.request(options); if (responseData.data && Array.isArray(responseData.data)) { responseData.data.forEach((item) => { returnData.push({ json: item }); }); } break; case 'add': const fileType = this.getNodeParameter('fileType', i); const fileUrl = this.getNodeParameter('fileUrl', i); const fileName = this.getNodeParameter('fileName', i); const fileDescription = this.getNodeParameter('fileDescription', i); options.method = 'POST'; options.url = `${baseUrl}/excites/${fileExciteId}/files`; options.body = { file_type: fileType, file_url: fileUrl, file_name: fileName, }; if (fileDescription) { options.body.description = fileDescription; } responseData = await this.helpers.request(options); returnData.push({ json: responseData.data }); break; case 'update': const updateFileId = this.getNodeParameter('fileId', i); const updateFileType = this.getNodeParameter('fileType', i); const updateFileUrl = this.getNodeParameter('fileUrl', i); const updateFileName = this.getNodeParameter('fileName', i); const updateFileDescription = this.getNodeParameter('fileDescription', i); options.method = 'PUT'; options.url = `${baseUrl}/excites/${fileExciteId}/files/${updateFileId}`; options.body = { file_type: updateFileType, file_url: updateFileUrl, file_name: updateFileName, }; if (updateFileDescription) { options.body.description = updateFileDescription; } responseData = await this.helpers.request(options); returnData.push({ json: responseData.data }); break; case 'delete': const deleteFileId = this.getNodeParameter('fileId', i); options.method = 'DELETE'; options.url = `${baseUrl}/excites/${fileExciteId}/files/${deleteFileId}`; responseData = await this.helpers.request(options); returnData.push({ json: responseData.data || { message: 'file deleted successfully' } }); break; } } } catch (error) { let errorMessage = error instanceof Error ? error.message : 'Unknown error'; // Handle rate limiting (429 responses) if (error.statusCode === 429 || error.status === 429) { errorMessage = 'Rate limit exceeded (300 requests/min). Please wait and try again later.'; } if (this.continueOnFail()) { returnData.push({ json: { error: errorMessage }, pairedItem: { item: i }, }); } else { throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage); } } } return [returnData]; } } exports.Aixyte = Aixyte;