n8n-nodes-cronlytic
Version:
n8n community node for Cronlytic advanced cron scheduling
263 lines • 11.3 kB
JavaScript
;
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