UNPKG

n8n-nodes-cronlytic

Version:

n8n community node for Cronlytic advanced cron scheduling

263 lines 11.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CronlyticTrigger = void 0; const n8n_workflow_1 = require("n8n-workflow"); class CronlyticTrigger { constructor() { this.description = { displayName: 'Cronlytic Trigger', name: 'cronlyticTrigger', icon: 'file:cronlytic.svg', group: ['trigger'], version: 1, subtitle: '={{$parameter["jobName"]}}', description: 'Trigger workflows using Cronlytic advanced cron scheduling', defaults: { name: 'Cronlytic Trigger', }, inputs: [], outputs: ["main"], credentials: [ { name: 'cronlyticApi', required: true, }, ], webhooks: [ { name: 'default', httpMethod: 'POST', responseMode: 'onReceived', path: 'webhook', }, ], properties: [ { displayName: 'Job Name', name: 'jobName', type: 'string', default: '', required: true, description: 'Unique name for the cron job (alphanumeric, hyphens, underscores only)', placeholder: 'my-workflow-trigger', }, { displayName: 'Cron Expression', name: 'cronExpression', type: 'string', default: '0 9 * * *', required: true, description: '5-field cron expression (minute hour day month day-of-week)', placeholder: '*/5 * * * * (every 5 minutes)', }, { displayName: 'Webhook Body', name: 'webhookBody', type: 'json', default: '{}', description: 'JSON data to send with webhook trigger (optional)', }, { displayName: 'Additional Headers', name: 'webhookHeaders', type: 'fixedCollection', default: {}, description: 'Additional headers for webhook requests', options: [ { name: 'headers', displayName: 'Headers', values: [ { displayName: 'Name', name: 'name', type: 'string', default: '', description: 'Header name', }, { displayName: 'Value', name: 'value', type: 'string', default: '', description: 'Header value', }, ], }, ], typeOptions: { multipleValues: true, }, }, ], }; this.webhookMethods = { default: { async checkExists() { try { const webhookData = this.getWorkflowStaticData('node'); const jobId = webhookData.jobId; if (!jobId) { return false; } const credentials = await this.getCredentials('cronlyticApi'); const triggerInstance = new CronlyticTrigger(); await triggerInstance.warmLambda(this, credentials); const response = await triggerInstance.cronlyticRequest(this, 'GET', `/jobs/${jobId}`, credentials); return response !== null; } catch (error) { return false; } }, async create() { try { const webhookUrl = this.getNodeWebhookUrl('default'); const jobName = this.getNodeParameter('jobName'); const cronExpression = this.getNodeParameter('cronExpression'); const webhookBody = this.getNodeParameter('webhookBody', '{}'); const webhookHeaders = this.getNodeParameter('webhookHeaders'); const headers = { 'Content-Type': 'application/json', 'User-Agent': 'n8n-cronlytic-trigger', }; if (webhookHeaders === null || webhookHeaders === void 0 ? void 0 : webhookHeaders.headers) { for (const header of webhookHeaders.headers) { if (header.name && header.value) { headers[header.name] = header.value; } } } const credentials = await this.getCredentials('cronlyticApi'); const triggerInstance = new CronlyticTrigger(); await triggerInstance.warmLambda(this, credentials); const jobData = { name: jobName, url: webhookUrl, method: 'POST', headers, body: webhookBody || '{}', cron_expression: cronExpression, }; const response = await triggerInstance.cronlyticRequest(this, 'POST', '/jobs', credentials, jobData); if (response === null || response === void 0 ? void 0 : response.job_id) { const webhookData = this.getWorkflowStaticData('node'); webhookData.jobId = response.job_id; return true; } return false; } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to create Cronlytic job: ${error.message}`); } }, async delete() { try { const webhookData = this.getWorkflowStaticData('node'); const jobId = webhookData.jobId; if (!jobId) { return true; } const credentials = await this.getCredentials('cronlyticApi'); const triggerInstance = new CronlyticTrigger(); await triggerInstance.warmLambda(this, credentials); await triggerInstance.cronlyticRequest(this, 'DELETE', `/jobs/${jobId}`, credentials); delete webhookData.jobId; return true; } catch (error) { if (error.message.includes('404') || error.message.includes('not found')) { const webhookData = this.getWorkflowStaticData('node'); delete webhookData.jobId; return true; } throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to delete Cronlytic job: ${error.message}`); } }, }, }; } async warmLambda(context, credentials) { const maxRetries = 3; const baseDelay = 1000; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const options = { method: 'GET', url: 'https://api.cronlytic.com/prog/ping', timeout: 5000, }; const response = await context.helpers.request(options); if (response && typeof response === 'object' && response.message === 'pong') { return; } if (response && typeof response === 'string') { const parsed = JSON.parse(response); if (parsed.message === 'pong') { return; } } } catch (error) { if (attempt === maxRetries) { throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Failed to warm lambda after ${maxRetries} attempts: ${error.message}`); } const delay = baseDelay * Math.pow(2, attempt - 1); await new Promise(resolve => { const nodeSetTimeout = require('timers').setTimeout; nodeSetTimeout(() => resolve(), delay); }); } } } async cronlyticRequest(context, method, endpoint, credentials, body) { var _a; const options = { method, url: `https://api.cronlytic.com/prog${endpoint}`, headers: { 'X-API-Key': credentials.apiKey, 'X-User-ID': credentials.userId, 'Content-Type': 'application/json', }, timeout: 10000, }; if (body) { options.body = body; options.json = true; } try { const response = await context.helpers.request(options); return response; } catch (error) { if (error.response) { const errorMessage = ((_a = error.response.body) === null || _a === void 0 ? void 0 : _a.detail) || error.response.body || error.message; throw new n8n_workflow_1.NodeOperationError(context.getNode(), `API Error: ${errorMessage}`); } throw error; } } async webhook() { const bodyData = this.getBodyData(); const headers = this.getHeaderData(); const query = this.getQueryData(); const outputData = [ { json: { headers, params: query, body: bodyData, timestamp: new Date().toISOString(), source: 'cronlytic', cronlytic_trigger: true, }, }, ]; return { workflowData: [outputData], }; } } exports.CronlyticTrigger = CronlyticTrigger; //# sourceMappingURL=CronlyticTrigger.node.js.map