n8n-nodes-variables
Version:
n8n community node for managing typed global variables accessible from any workflow stage - like programming language variables with strong typing support
544 lines • 24.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkflowVariables = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const WORKFLOW_VARIABLES_KEY = '__workflow_variables__';
function getWorkflowVariables(context) {
const staticData = context.getWorkflowStaticData('global');
if (!staticData[WORKFLOW_VARIABLES_KEY]) {
staticData[WORKFLOW_VARIABLES_KEY] = {};
}
return staticData[WORKFLOW_VARIABLES_KEY];
}
function setWorkflowVariable(context, name, value) {
const variables = getWorkflowVariables(context);
variables[name] = value;
}
function getWorkflowVariable(context, name) {
const variables = getWorkflowVariables(context);
return variables[name];
}
class WorkflowVariables {
constructor() {
this.description = {
displayName: 'Variables',
name: 'variables',
icon: 'fa:code-branch',
group: ['utility'],
version: 1,
description: 'Manage typed global variables accessible from any workflow stage - like programming language variables',
defaults: {
name: 'Variables',
},
inputs: ["main"],
outputs: ["main"],
properties: [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
options: [
{
name: 'Clear All Variables',
value: 'clear',
description: 'Reset all workflow variables',
action: 'Reset all workflow variables',
},
{
name: 'Get Variable',
value: 'get',
description: 'Retrieve a variable value',
action: 'Retrieve a variable value',
},
{
name: 'Initialize Variables',
value: 'initialize',
description: 'Set up initial variables for the workflow',
action: 'Set up initial variables for the workflow',
},
{
name: 'Set Variable',
value: 'set',
description: 'Update a variable value (can be used at any stage)',
action: 'Update a variable value can be used at any stage',
},
{
name: 'View All Variables',
value: 'viewAll',
description: 'Display all current variables and their values',
action: 'Display all current variables and their values',
},
],
default: 'set',
noDataExpression: true,
},
{
displayName: 'Variable Name',
name: 'variableName',
type: 'string',
default: '',
displayOptions: {
show: {
operation: ['set', 'get'],
},
},
required: true,
placeholder: 'e.g., URL, pageNumber, maxRetries',
description: 'Name of the variable to set or get',
},
{
displayName: 'Variable Type',
name: 'variableType',
type: 'options',
options: [
{
name: 'Boolean',
value: 'boolean',
description: 'True/False value',
},
{
name: 'Date',
value: 'date',
description: 'Date value',
},
{
name: 'JSON',
value: 'json',
description: 'Complex object or array',
},
{
name: 'Number',
value: 'number',
description: 'Numeric value',
},
{
name: 'String',
value: 'string',
description: 'Text value',
},
],
default: 'string',
displayOptions: {
show: {
operation: ['set'],
},
},
description: 'Type of the variable value',
},
{
displayName: 'Variable Value',
name: 'variableValue',
type: 'string',
default: '',
displayOptions: {
show: {
operation: ['set'],
variableType: ['string'],
},
},
placeholder: 'Enter text value',
description: 'Text value to store in the variable. Supports expressions.',
},
{
displayName: 'Variable Value',
name: 'variableValue',
type: 'number',
default: 0,
displayOptions: {
show: {
operation: ['set'],
variableType: ['number'],
},
},
placeholder: 'Enter numeric value',
description: 'Numeric value to store in the variable. Supports expressions.',
},
{
displayName: 'Variable Value',
name: 'variableValue',
type: 'boolean',
default: false,
displayOptions: {
show: {
operation: ['set'],
variableType: ['boolean'],
},
},
description: 'Whether to store true or false in the variable',
},
{
displayName: 'Variable Value',
name: 'variableValue',
type: 'json',
default: '',
displayOptions: {
show: {
operation: ['set'],
variableType: ['json'],
},
},
placeholder: 'Enter JSON object or array',
description: 'JSON object or array to store in the variable. Supports expressions.',
},
{
displayName: 'Variable Value',
name: 'variableValue',
type: 'dateTime',
default: '',
displayOptions: {
show: {
operation: ['set'],
variableType: ['date'],
},
},
placeholder: 'Select or enter date',
description: 'Date value to store in the variable. Supports expressions.',
},
{
displayName: 'Initial Variables',
name: 'initialVariables',
type: 'fixedCollection',
default: { variables: [] },
displayOptions: {
show: {
operation: ['initialize'],
},
},
placeholder: 'Add Variable',
typeOptions: {
multipleValues: true,
sortable: true,
},
options: [
{
name: 'variables',
displayName: 'Variable',
values: [
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
placeholder: 'variableName',
description: 'Variable name (e.g., URL, counter, maxPages)',
required: true,
},
{
displayName: 'Type',
name: 'type',
type: 'options',
options: [
{
name: 'Boolean',
value: 'boolean',
},
{
name: 'Date',
value: 'date',
},
{
name: 'JSON',
value: 'json',
},
{
name: 'Number',
value: 'number',
},
{
name: 'String',
value: 'string',
},
],
default: 'string',
description: 'Type of the variable',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
displayOptions: {
show: {
type: ['string'],
},
},
placeholder: 'Initial text value',
description: 'Initial text value for the variable',
},
{
displayName: 'Value',
name: 'value',
type: 'number',
default: 0,
displayOptions: {
show: {
type: ['number'],
},
},
placeholder: 'Initial numeric value',
description: 'Initial numeric value for the variable',
},
{
displayName: 'Value',
name: 'value',
type: 'boolean',
default: false,
displayOptions: {
show: {
type: ['boolean'],
},
},
description: 'Whether the initial variable value should be true or false',
},
{
displayName: 'Value',
name: 'value',
type: 'json',
default: '',
displayOptions: {
show: {
type: ['json'],
},
},
placeholder: 'Initial JSON value',
description: 'Initial JSON object or array for the variable',
},
{
displayName: 'Value',
name: 'value',
type: 'dateTime',
default: '',
displayOptions: {
show: {
type: ['date'],
},
},
placeholder: 'Initial date value',
description: 'Initial date value for the variable',
},
],
},
],
description: 'Set up initial variables for your workflow',
},
{
displayName: 'Usage Guide',
name: 'usageGuide',
type: 'collection',
default: {},
displayOptions: {
show: {
operation: ['initialize'],
},
},
placeholder: 'Expression Access',
description: 'After initialization, access variables in ANY node using: $workflow.variables.VARIABLE_NAME (e.g., $workflow.variables.URL in HTTP Request)',
options: [],
},
],
};
}
async execute() {
const items = this.getInputData();
const operation = this.getNodeParameter('operation', 0);
let returnData = [];
const staticData = this.getWorkflowStaticData('global');
if (!staticData.variables) {
staticData.variables = {};
}
for (let i = 0; i < items.length; i++) {
try {
if (operation === 'initialize') {
const initialVariables = this.getNodeParameter('initialVariables', i, { variables: [] });
const variables = getWorkflowVariables(this);
const resultVariables = {};
Object.keys(variables).forEach(key => delete variables[key]);
if (staticData.variables) {
Object.keys(staticData.variables).forEach(key => delete staticData.variables[key]);
}
for (const variable of initialVariables.variables) {
if (variable.name) {
let processedValue;
const varType = variable.type || 'string';
switch (varType) {
case 'string':
processedValue = String(variable.value || '');
break;
case 'number':
processedValue = Number(variable.value || 0);
if (isNaN(processedValue)) {
processedValue = 0;
}
break;
case 'boolean':
processedValue = Boolean(variable.value);
break;
case 'date':
if (variable.value) {
processedValue = new Date(variable.value);
if (isNaN(processedValue.getTime())) {
processedValue = new Date();
}
}
else {
processedValue = new Date();
}
break;
case 'json':
default:
if (typeof variable.value === 'string') {
try {
processedValue = JSON.parse(variable.value);
}
catch (e) {
processedValue = variable.value;
}
}
else {
processedValue = variable.value;
}
break;
}
variables[variable.name] = processedValue;
staticData.variables[variable.name] = processedValue;
resultVariables[variable.name] = processedValue;
}
}
returnData.push({
json: {
...items[i].json,
...resultVariables,
},
pairedItem: items[i].pairedItem,
});
}
else if (operation === 'set') {
const variableName = this.getNodeParameter('variableName', i);
const variableType = this.getNodeParameter('variableType', i);
const variableValue = this.getNodeParameter('variableValue', i);
if (!variableName) {
throw new n8n_workflow_1.ApplicationError('Variable name is required');
}
let processedValue;
switch (variableType) {
case 'string':
processedValue = String(variableValue);
break;
case 'number':
processedValue = Number(variableValue);
if (isNaN(processedValue)) {
throw new n8n_workflow_1.ApplicationError(`Invalid number value: ${variableValue}`);
}
break;
case 'boolean':
processedValue = Boolean(variableValue);
break;
case 'date':
if (variableValue) {
processedValue = new Date(variableValue);
if (isNaN(processedValue.getTime())) {
throw new n8n_workflow_1.ApplicationError(`Invalid date value: ${variableValue}`);
}
}
else {
processedValue = null;
}
break;
case 'json':
default:
if (typeof variableValue === 'string') {
try {
processedValue = JSON.parse(variableValue);
}
catch (e) {
throw new n8n_workflow_1.ApplicationError(`Invalid JSON value: ${variableValue}`);
}
}
else {
processedValue = variableValue;
}
break;
}
setWorkflowVariable(this, variableName, processedValue);
staticData.variables[variableName] = processedValue;
const allVariables = getWorkflowVariables(this);
returnData.push({
json: {
...items[i].json,
...allVariables,
},
pairedItem: items[i].pairedItem,
});
}
else if (operation === 'get') {
const variableName = this.getNodeParameter('variableName', i);
if (!variableName) {
throw new n8n_workflow_1.ApplicationError('Variable name is required');
}
const value = getWorkflowVariable(this, variableName);
returnData.push({
json: {
...items[i].json,
operation: 'get',
variableName: variableName,
variableValue: value,
[variableName]: value,
status: value !== undefined ? 'found' : 'not_found',
message: value !== undefined
? `Retrieved variable '${variableName}'`
: `Variable '${variableName}' not found`,
},
pairedItem: items[i].pairedItem,
});
}
else if (operation === 'viewAll') {
const variables = getWorkflowVariables(this);
returnData.push({
json: {
...items[i].json,
...variables,
},
pairedItem: items[i].pairedItem,
});
}
else if (operation === 'clear') {
const variables = getWorkflowVariables(this);
const clearedVariables = Object.keys(variables);
Object.keys(variables).forEach(key => delete variables[key]);
if (staticData.variables) {
Object.keys(staticData.variables).forEach(key => delete staticData.variables[key]);
}
returnData.push({
json: {
...items[i].json,
operation: 'clear',
clearedVariables: clearedVariables,
clearedCount: clearedVariables.length,
message: `Cleared ${clearedVariables.length} workflow variables`,
},
pairedItem: items[i].pairedItem,
});
}
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
...items[i].json,
error: error.message,
operation: operation,
status: 'error',
},
pairedItem: items[i].pairedItem,
});
}
else {
throw error;
}
}
}
return [returnData];
}
}
exports.WorkflowVariables = WorkflowVariables;
//# sourceMappingURL=WorkflowVariables.node.js.map