CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-n8n-workflow

Workflow base code of n8n providing foundational workflow execution engine for automation platform

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

extension-system.mddocs/

Extension System

Comprehensive extension system providing data type extensions, native method access, expression parsing capabilities, and enhanced functionality for workflow expressions and data manipulation.

Capabilities

Expression Extensions Registry

Core extension system for registering and managing expression functions.

/**
 * Expression extensions registry and management
 */
class ExpressionExtensions {
  /**
   * Registry of all available extension functions
   */
  static readonly functions: Record<string, Extension>;

  /**
   * Add custom extension function to registry
   * @param name - Extension function name
   * @param extension - Extension implementation
   */
  static addExtension(name: string, extension: Extension): void;

  /**
   * Get extension function by name
   * @param name - Extension name
   * @returns Extension implementation or undefined
   */
  static getExtension(name: string): Extension | undefined;

  /**
   * Remove extension from registry
   * @param name - Extension name to remove
   * @returns Boolean indicating if extension was removed
   */
  static removeExtension(name: string): boolean;

  /**
   * List all available extension names
   * @returns Array of extension names
   */
  static listExtensions(): string[];
}

/**
 * Extension function interface
 */
interface Extension {
  doc: DocMetadata;
  transform: (value: any, ...args: any[]) => any;
}

/**
 * Extension documentation metadata
 */
interface DocMetadata {
  name: string;
  description: string;
  returnType?: string;
  args?: DocMetadataArgument[];
  examples?: DocMetadataExample[];
  section?: string;
  hidden?: boolean;
}

interface DocMetadataArgument {
  name: string;
  type?: string;
  description?: string;
  default?: any;
  optional?: boolean;
}

interface DocMetadataExample {
  example: string;
  description: string;
  result?: any;
}

Native Methods Access

Secure access to native JavaScript and Node.js methods within expressions.

/**
 * Native methods registry for expression evaluation
 */
class NativeMethods {
  /**
   * Get native method implementation
   * @param methodName - Native method name
   * @returns Native method function or undefined
   */
  static getNativeMethod(methodName: string): Function | undefined;

  /**
   * Register native method for expression use
   * @param name - Method name
   * @param method - Method implementation
   * @param options - Registration options
   */
  static registerNativeMethod(
    name: string,
    method: Function,
    options?: INativeMethodOptions
  ): void;

  /**
   * List all available native methods
   * @returns Array of native method names
   */
  static listNativeMethods(): string[];
}

interface INativeMethodOptions {
  allowedInSandbox?: boolean;
  documentation?: DocMetadata;
  category?: string;
}

Data Type Extensions

Built-in extensions for different data types with comprehensive functionality.

/**
 * Array data type extensions
 */
interface ArrayExtensions {
  /**
   * Split array into chunks of specified size
   * @param size - Chunk size
   * @returns Array of chunks
   */
  chunk(size: number): any[][];

  /**
   * Remove falsy values from array
   * @returns Array with truthy values only
   */
  compact(): any[];

  /**
   * Get difference between arrays
   * @param values - Values to exclude
   * @returns Array with differences
   */
  difference(values: any[]): any[];

  /**
   * Get first element
   * @returns First array element
   */
  first(): any;

  /**
   * Get last element
   * @returns Last array element
   */
  last(): any;

  /**
   * Remove duplicate values
   * @returns Array with unique values
   */
  unique(): any[];

  /**
   * Flatten nested arrays
   * @param depth - Maximum depth to flatten
   * @returns Flattened array
   */
  flatten(depth?: number): any[];

  /**
   * Check if array is empty
   * @returns Boolean indicating if array is empty
   */
  isEmpty(): boolean;

  /**
   * Get array length
   * @returns Array length
   */
  length(): number;

  /**
   * Sum all numeric values
   * @returns Sum of array values
   */
  sum(): number;

  /**
   * Get average of numeric values
   * @returns Average value
   */
  average(): number;

  /**
   * Get minimum value
   * @returns Minimum value
   */
  min(): any;

  /**
   * Get maximum value
   * @returns Maximum value
   */
  max(): any;
}

/**
 * String data type extensions
 */
interface StringExtensions {
  /**
   * Check if string contains substring
   * @param searchString - String to search for
   * @returns Boolean indicating if string contains substring
   */
  contains(searchString: string): boolean;

  /**
   * Check if string starts with substring
   * @param searchString - String to check
   * @returns Boolean indicating if string starts with substring
   */
  startsWith(searchString: string): boolean;

  /**
   * Check if string ends with substring
   * @param searchString - String to check
   * @returns Boolean indicating if string ends with substring
   */
  endsWith(searchString: string): boolean;

  /**
   * Convert to title case
   * @returns Title case string
   */
  toTitleCase(): string;

  /**
   * Convert to sentence case
   * @returns Sentence case string
   */
  toSentenceCase(): string;

  /**
   * Remove HTML tags
   * @returns String without HTML tags
   */
  stripTags(): string;

  /**
   * URL encode string
   * @returns URL encoded string
   */
  urlEncode(): string;

  /**
   * URL decode string
   * @returns URL decoded string
   */
  urlDecode(): string;

  /**
   * Generate hash of string
   * @param algorithm - Hash algorithm (default: 'md5')
   * @returns Hash string
   */
  hash(algorithm?: string): string;

  /**
   * Extract email addresses from string
   * @returns Array of email addresses
   */
  extractEmails(): string[];

  /**
   * Extract URLs from string
   * @returns Array of URLs
   */
  extractUrls(): string[];

  /**
   * Truncate string to specified length
   * @param length - Maximum length
   * @param suffix - Suffix to add (default: '...')
   * @returns Truncated string
   */
  truncate(length: number, suffix?: string): string;
}

/**
 * Number data type extensions
 */
interface NumberExtensions {
  /**
   * Get absolute value
   * @returns Absolute value
   */
  abs(): number;

  /**
   * Round up to nearest integer
   * @returns Ceiling value
   */
  ceil(): number;

  /**
   * Round down to nearest integer
   * @returns Floor value
   */
  floor(): number;

  /**
   * Round to specified precision
   * @param precision - Number of decimal places
   * @returns Rounded number
   */
  round(precision?: number): number;

  /**
   * Check if value is NaN
   * @returns Boolean indicating if value is NaN
   */
  isNaN(): boolean;

  /**
   * Check if value is finite
   * @returns Boolean indicating if value is finite
   */
  isFinite(): boolean;

  /**
   * Format number with locale options
   * @param options - Formatting options
   * @returns Formatted number string
   */
  format(options?: NumberFormatOptions): string;

  /**
   * Convert to percentage
   * @param decimals - Number of decimal places
   * @returns Percentage string
   */
  toPercent(decimals?: number): string;

  /**
   * Convert to currency format
   * @param currency - Currency code
   * @param locale - Locale code
   * @returns Currency formatted string
   */
  toCurrency(currency?: string, locale?: string): string;
}

interface NumberFormatOptions {
  locale?: string;
  style?: 'decimal' | 'currency' | 'percent';
  currency?: string;
  minimumFractionDigits?: number;
  maximumFractionDigits?: number;
}

Date Extensions

Comprehensive date and time manipulation extensions.

/**
 * Date data type extensions
 */
interface DateExtensions {
  /**
   * Format date using specified format string
   * @param format - Format string (e.g., 'yyyy-MM-dd')
   * @returns Formatted date string
   */
  format(format: string): string;

  /**
   * Convert to ISO string
   * @returns ISO formatted date string
   */
  toISOString(): string;

  /**
   * Get beginning of time unit
   * @param unit - Time unit ('day', 'month', 'year', etc.)
   * @returns Date at beginning of unit
   */
  beginningOf(unit: DateUnit): Date;

  /**
   * Get end of time unit
   * @param unit - Time unit
   * @returns Date at end of unit
   */
  endOf(unit: DateUnit): Date;

  /**
   * Add duration to date
   * @param duration - Duration object or number
   * @param unit - Time unit (if duration is number)
   * @returns New date with added duration
   */
  plus(duration: Duration | number, unit?: DateUnit): Date;

  /**
   * Subtract duration from date
   * @param duration - Duration object or number
   * @param unit - Time unit (if duration is number)
   * @returns New date with subtracted duration
   */
  minus(duration: Duration | number, unit?: DateUnit): Date;

  /**
   * Get difference between dates
   * @param date - Date to compare with
   * @param unit - Unit for difference calculation
   * @returns Difference in specified unit
   */
  diff(date: Date, unit?: DateUnit): number;

  /**
   * Check if date is before another date
   * @param date - Date to compare with
   * @returns Boolean indicating if date is before
   */
  isBefore(date: Date): boolean;

  /**
   * Check if date is after another date
   * @param date - Date to compare with
   * @returns Boolean indicating if date is after
   */
  isAfter(date: Date): boolean;

  /**
   * Check if date is between two dates
   * @param start - Start date
   * @param end - End date
   * @returns Boolean indicating if date is between
   */
  isBetween(start: Date, end: Date): boolean;
}

type DateUnit = 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year';

interface Duration {
  years?: number;
  months?: number;
  weeks?: number;
  days?: number;
  hours?: number;
  minutes?: number;
  seconds?: number;
  milliseconds?: number;
}

Object Extensions

Object manipulation and transformation extensions.

/**
 * Object data type extensions
 */
interface ObjectExtensions {
  /**
   * Get object keys
   * @returns Array of object keys
   */
  keys(): string[];

  /**
   * Get object values
   * @returns Array of object values
   */
  values(): any[];

  /**
   * Get object entries as key-value pairs
   * @returns Array of [key, value] pairs
   */
  entries(): Array<[string, any]>;

  /**
   * Check if object has property
   * @param key - Property key to check
   * @returns Boolean indicating if property exists
   */
  hasKey(key: string): boolean;

  /**
   * Pick specified properties
   * @param keys - Keys to pick
   * @returns Object with only specified keys
   */
  pick(keys: string[]): object;

  /**
   * Omit specified properties
   * @param keys - Keys to omit
   * @returns Object without specified keys
   */
  omit(keys: string[]): object;

  /**
   * Merge with another object
   * @param other - Object to merge with
   * @returns Merged object
   */
  merge(other: object): object;

  /**
   * Convert keys to camelCase
   * @returns Object with camelCase keys
   */
  camelCaseKeys(): object;

  /**
   * Convert keys to snake_case
   * @returns Object with snake_case keys
   */
  snakeCaseKeys(): object;

  /**
   * Flatten nested object
   * @param separator - Key separator (default: '.')
   * @returns Flattened object
   */
  flatten(separator?: string): object;

  /**
   * Unflatten dot notation object
   * @returns Nested object structure
   */
  unflatten(): object;
}

Expression Parser

Advanced expression parsing and validation capabilities.

/**
 * Expression parser module
 */
namespace ExpressionParser {
  /**
   * Parse expression string into AST
   * @param expression - Expression string to parse
   * @returns Parsed expression AST
   */
  function parse(expression: string): ExpressionAST;

  /**
   * Validate expression syntax
   * @param expression - Expression to validate
   * @returns Validation result
   */
  function validate(expression: string): ExpressionValidationResult;

  /**
   * Extract all variables from expression
   * @param expression - Expression string
   * @returns Array of variable names
   */
  function extractVariables(expression: string): string[];

  /**
   * Get expression dependencies
   * @param expression - Expression string
   * @returns Dependency information
   */
  function getDependencies(expression: string): ExpressionDependencies;

  /**
   * Transform expression AST
   * @param ast - Expression AST
   * @param transformer - Transformation function
   * @returns Transformed AST
   */
  function transform(
    ast: ExpressionAST,
    transformer: (node: ASTNode) => ASTNode
  ): ExpressionAST;
}

interface ExpressionAST {
  type: string;
  body: ASTNode[];
  sourceType: 'script' | 'module';
}

interface ASTNode {
  type: string;
  [key: string]: any;
}

interface ExpressionValidationResult {
  isValid: boolean;
  errors: ExpressionSyntaxError[];
  warnings: ExpressionWarning[];
}

interface ExpressionDependencies {
  variables: string[];
  functions: string[];
  dataRefs: string[];
  nodeRefs: string[];
}

Usage Examples:

import { 
  ExpressionExtensions,
  NativeMethods,
  ExpressionParser
} from "n8n-workflow";

// Register custom extension
ExpressionExtensions.addExtension('customTransform', {
  doc: {
    name: 'customTransform',
    description: 'Transform data using custom logic',
    returnType: 'any',
    args: [
      { name: 'data', type: 'any', description: 'Data to transform' },
      { name: 'options', type: 'object', optional: true, description: 'Transform options' }
    ],
    examples: [
      {
        example: 'data.customTransform({ format: "uppercase" })',
        description: 'Transform data to uppercase format'
      }
    ]
  },
  transform: (value: any, options: any = {}) => {
    if (options.format === 'uppercase' && typeof value === 'string') {
      return value.toUpperCase();
    }
    return value;
  }
});

// Use data type extensions in expressions
const arrayExpression = `
  {{ 
    $json.items
      .chunk(3)
      .map(chunk => chunk.sum())
      .unique()
      .sort()
  }}
`;

const stringExpression = `
  {{ 
    $json.description
      .stripTags()
      .truncate(100)
      .toTitleCase()
  }}
`;

const dateExpression = `
  {{ 
    $json.createdAt
      .beginningOf('day')
      .plus(1, 'week')
      .format('yyyy-MM-dd')
  }}
`;

// Register native method
NativeMethods.registerNativeMethod('customMath', Math.pow, {
  allowedInSandbox: true,
  documentation: {
    name: 'customMath',
    description: 'Calculate power of a number',
    args: [
      { name: 'base', type: 'number', description: 'Base number' },
      { name: 'exponent', type: 'number', description: 'Exponent' }
    ]
  },
  category: 'math'
});

// Parse and analyze expressions
const expressionCode = '{{ $json.user.name.toTitleCase() + " - " + $json.createdAt.format("yyyy-MM-dd") }}';

const ast = ExpressionParser.parse(expressionCode);
console.log('Parsed AST:', ast);

const validation = ExpressionParser.validate(expressionCode);
if (!validation.isValid) {
  console.log('Expression validation errors:', validation.errors);
}

const variables = ExpressionParser.extractVariables(expressionCode);
console.log('Variables used:', variables); // ['$json']

const dependencies = ExpressionParser.getDependencies(expressionCode);
console.log('Expression dependencies:', dependencies);

// List available extensions
const availableExtensions = ExpressionExtensions.listExtensions();
console.log('Available extensions:', availableExtensions);

// Get extension documentation
const stringExtension = ExpressionExtensions.getExtension('toTitleCase');
if (stringExtension) {
  console.log('Extension documentation:', stringExtension.doc);
}

// Complex data manipulation using extensions
const complexExpression = `
  {{ 
    $json.users
      .filter(user => user.active && user.email.contains('@company.com'))
      .map(user => ({
        id: user.id,
        name: user.name.toTitleCase(),
        email: user.email.toLowerCase(),
        joinDate: user.joinDate.format('MMM dd, yyyy'),
        tenure: user.joinDate.diff($now, 'months')
      }))
      .sort((a, b) => a.tenure - b.tenure)
      .chunk(10)
      .first()
  }}
`;

// Object transformation example
const objectTransformExpression = `
  {{ 
    $json.apiResponse
      .pick(['id', 'name', 'email', 'metadata'])
      .camelCaseKeys()
      .merge({ 
        processedAt: $now.toISOString(),
        status: 'processed'
      })
  }}
`;

console.log('Complex expressions ready for evaluation');

docs

constants.md

data-proxy.md

error-handling.md

expression-system.md

extension-system.md

graph-utilities.md

index.md

node-execution.md

specialized-modules.md

type-guards.md

type-validation.md

utilities.md

workflow-management.md

tile.json