CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-superset-ui--core

Core utilities and components for Apache Superset's frontend UI framework providing data visualization, formatting, and chart composition capabilities

Pending
Overview
Eval results
Files

validation-math.mddocs/

Validation & Math

This module provides input validation utilities and mathematical expression evaluation capabilities for Superset applications. It includes both modern and legacy validation functions for common data types, as well as a powerful expression evaluator that supports mathematical operations, logical comparisons, and variable substitution.

Overview

The validation and math module serves two primary purposes: ensuring data integrity through comprehensive input validation and providing dynamic mathematical computation through expression evaluation. The validation system supports both modern and legacy validation patterns, while the math expression system enables conditional logic and calculations with support for comparison operators and logical operations.

Input Validation

Modern Validation Functions { .api }

Current validation functions that return error messages or false for valid inputs:

import { 
  validateNumber, 
  validateInteger, 
  validateNonEmpty 
} from '@superset-ui/core';

// Validate numeric input
function validateNumber(value: unknown): string | false;

// Validate integer input  
function validateInteger(value: unknown): string | false;

// Validate non-empty input (not null, undefined, empty string, etc.)
function validateNonEmpty(value: unknown): string | false;

Legacy Validation Functions { .api }

Legacy validation functions for backward compatibility:

import { 
  legacyValidateNumber, 
  legacyValidateInteger 
} from '@superset-ui/core';

// Legacy number validation
function legacyValidateNumber(value: unknown): string | false;

// Legacy integer validation
function legacyValidateInteger(value: unknown): string | false;

Mathematical Expressions

Expression Evaluation { .api }

Powerful mathematical expression evaluator with support for variables and logical operations:

import { evalExpression, isValidExpression } from '@superset-ui/core';

// Evaluate mathematical expression with variable substitution
function evalExpression(expression: string, value: number): number;

// Validate expression syntax
function isValidExpression(expression: string): boolean;

Supported Operations

The expression evaluator supports a comprehensive set of mathematical and logical operations:

Arithmetic Operations

  • + - Addition
  • - - Subtraction
  • * - Multiplication
  • / - Division
  • % - Modulo
  • ^ - Exponentiation

Comparison Operations

  • == - Equal to
  • > - Greater than
  • >= - Greater than or equal to
  • < - Less than
  • <= - Less than or equal to

Logical Operations

  • and - Logical AND
  • or - Logical OR
  • xor - Exclusive OR (XOR)
  • & - Bitwise AND
  • | - Bitwise OR

Variables

  • x - Variable that gets substituted with the provided value

Usage Examples

Basic Input Validation

import { 
  validateNumber, 
  validateInteger, 
  validateNonEmpty 
} from '@superset-ui/core';

// Number validation
const numberValidation1 = validateNumber(42);         // false (valid)
const numberValidation2 = validateNumber('123.45');   // false (valid)
const numberValidation3 = validateNumber('abc');      // "is expected to be a number"
const numberValidation4 = validateNumber(null);       // "is expected to be a number"

// Integer validation  
const integerValidation1 = validateInteger(42);       // false (valid)
const integerValidation2 = validateInteger('123');    // false (valid)
const integerValidation3 = validateInteger('12.34');  // "is expected to be an integer"
const integerValidation4 = validateInteger('abc');    // "is expected to be an integer"

// Non-empty validation
const emptyValidation1 = validateNonEmpty('hello');   // false (valid)
const emptyValidation2 = validateNonEmpty(0);         // false (valid - 0 is not empty)
const emptyValidation3 = validateNonEmpty('');        // "cannot be empty"
const emptyValidation4 = validateNonEmpty(null);      // "cannot be empty"
const emptyValidation5 = validateNonEmpty(undefined); // "cannot be empty"

Form Validation Integration

import React, { useState } from 'react';
import { validateNumber, validateInteger } from '@superset-ui/core';

interface FormData {
  rowLimit: string;
  threshold: string;
}

const ChartConfigForm: React.FC = () => {
  const [formData, setFormData] = useState<FormData>({
    rowLimit: '',
    threshold: ''
  });
  
  const [errors, setErrors] = useState<Partial<FormData>>({});
  
  const validateForm = (data: FormData) => {
    const newErrors: Partial<FormData> = {};
    
    // Validate row limit as integer
    const rowLimitError = validateInteger(data.rowLimit);
    if (rowLimitError) {
      newErrors.rowLimit = rowLimitError;
    }
    
    // Validate threshold as number
    const thresholdError = validateNumber(data.threshold);
    if (thresholdError) {
      newErrors.threshold = thresholdError;
    }
    
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };
  
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (validateForm(formData)) {
      console.log('Form is valid:', formData);
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Row Limit (Integer):</label>
        <input
          value={formData.rowLimit}
          onChange={(e) => setFormData({...formData, rowLimit: e.target.value})}
        />
        {errors.rowLimit && <span className="error">{errors.rowLimit}</span>}
      </div>
      
      <div>
        <label>Threshold (Number):</label>
        <input
          value={formData.threshold}
          onChange={(e) => setFormData({...formData, threshold: e.target.value})}
        />
        {errors.threshold && <span className="error">{errors.threshold}</span>}
      </div>
      
      <button type="submit">Submit</button>
    </form>
  );
};

Mathematical Expression Evaluation

import { evalExpression, isValidExpression } from '@superset-ui/core';

// Basic arithmetic
const result1 = evalExpression('x + 10', 5);          // 15
const result2 = evalExpression('x * 2 + 1', 3);       // 7
const result3 = evalExpression('x ^ 2', 4);           // 16
const result4 = evalExpression('x % 3', 10);          // 1

// Comparison operations (return 1 for true, 0 for false)
const comparison1 = evalExpression('x > 10', 15);     // 1 (true)
const comparison2 = evalExpression('x == 5', 5);      // 1 (true) 
const comparison3 = evalExpression('x < 0', 5);       // 0 (false)
const comparison4 = evalExpression('x >= 100', 50);   // 0 (false)
const comparison5 = evalExpression('x <= 10', 10);    // 1 (true)

// Logical operations
const logical1 = evalExpression('x > 5 and x < 15', 10);  // 1 (true)
const logical2 = evalExpression('x < 0 or x > 100', 5);   // 0 (false)
const logical3 = evalExpression('x == 5 xor x == 10', 5); // 1 (true - only first condition met)

// Complex expressions
const complex1 = evalExpression('(x * 2) > 20 and (x + 5) < 30', 12);  // 1 (true)
const complex2 = evalExpression('x >= 0 and x <= 100', 50);             // 1 (true)

Conditional Logic for Data Processing

import { evalExpression, isValidExpression } from '@superset-ui/core';

// Create data filters based on expressions
interface DataFilter {
  expression: string;
  description: string;
}

const dataFilters: DataFilter[] = [
  { expression: 'x > 0', description: 'Positive values only' },
  { expression: 'x >= 18 and x <= 65', description: 'Working age (18-65)' },
  { expression: 'x % 2 == 0', description: 'Even numbers only' },
  { expression: 'x > 1000 or x < -1000', description: 'Outliers (absolute value > 1000)' }
];

// Apply filters to dataset
const applyFilters = (data: number[], filters: DataFilter[]): number[] => {
  return data.filter(value => {
    return filters.every(filter => {
      if (!isValidExpression(filter.expression)) {
        console.warn(`Invalid expression: ${filter.expression}`);
        return true; // Include value if expression is invalid
      }
      
      return evalExpression(filter.expression, value) === 1;
    });
  });
};

// Usage
const dataset = [-500, 25, 42, 1500, -2000, 30, 17, 66];
const activeFilters = [
  dataFilters[0], // Positive values only
  dataFilters[1]  // Working age (18-65)
];

const filteredData = applyFilters(dataset, activeFilters);
console.log(filteredData); // [25, 42, 30] (positive and between 18-65)

Chart Data Thresholds

import { evalExpression, isValidExpression } from '@superset-ui/core';

// Define threshold configurations for charts
interface ThresholdConfig {
  condition: string;
  color: string;
  label: string;
}

const thresholds: ThresholdConfig[] = [
  { condition: 'x < 25', color: '#FF4444', label: 'Critical' },
  { condition: 'x >= 25 and x < 75', color: '#FFA500', label: 'Warning' },
  { condition: 'x >= 75', color: '#00AA00', label: 'Good' }
];

// Apply threshold coloring to chart data
const applyThresholdColoring = (values: number[], thresholds: ThresholdConfig[]) => {
  return values.map(value => {
    // Find first matching threshold
    const threshold = thresholds.find(t => {
      if (!isValidExpression(t.condition)) return false;
      return evalExpression(t.condition, value) === 1;
    });
    
    return {
      value,
      color: threshold?.color || '#666666',
      label: threshold?.label || 'Unknown',
      status: threshold ? 'matched' : 'no_match'
    };
  });
};

// Usage
const performanceScores = [15, 45, 85, 92, 30, 60];
const coloredData = applyThresholdColoring(performanceScores, thresholds);

coloredData.forEach(item => {
  console.log(`Score: ${item.value}, Status: ${item.label}, Color: ${item.color}`);
});
// Score: 15, Status: Critical, Color: #FF4444
// Score: 45, Status: Warning, Color: #FFA500
// Score: 85, Status: Good, Color: #00AA00
// etc.

Dynamic Alert Rules

import { evalExpression, isValidExpression } from '@superset-ui/core';

// Alert rule configuration
interface AlertRule {
  id: string;
  name: string;
  expression: string;
  message: string;
  severity: 'low' | 'medium' | 'high' | 'critical';
}

const alertRules: AlertRule[] = [
  {
    id: 'high_cpu',
    name: 'High CPU Usage',
    expression: 'x > 80',
    message: 'CPU usage is above 80%',
    severity: 'high'
  },
  {
    id: 'memory_critical',
    name: 'Critical Memory Usage', 
    expression: 'x >= 95',
    message: 'Memory usage is critically high',
    severity: 'critical'
  },
  {
    id: 'disk_warning',
    name: 'Disk Space Warning',
    expression: 'x > 70 and x <= 90',
    message: 'Disk space is running low',
    severity: 'medium'
  }
];

// Evaluate alerts for system metrics
interface SystemMetric {
  name: string;
  value: number;
  timestamp: Date;
}

interface Alert {
  ruleId: string;
  ruleName: string;
  metric: SystemMetric;
  message: string;
  severity: string;
  triggered: boolean;
}

const evaluateAlerts = (metrics: SystemMetric[], rules: AlertRule[]): Alert[] => {
  const alerts: Alert[] = [];
  
  metrics.forEach(metric => {
    rules.forEach(rule => {
      if (!isValidExpression(rule.expression)) {
        console.error(`Invalid alert expression for rule ${rule.id}: ${rule.expression}`);
        return;
      }
      
      const triggered = evalExpression(rule.expression, metric.value) === 1;
      
      alerts.push({
        ruleId: rule.id,
        ruleName: rule.name,
        metric,
        message: rule.message,
        severity: rule.severity,
        triggered
      });
    });
  });
  
  return alerts.filter(alert => alert.triggered);
};

// Usage
const systemMetrics: SystemMetric[] = [
  { name: 'CPU Usage', value: 85, timestamp: new Date() },
  { name: 'Memory Usage', value: 72, timestamp: new Date() },
  { name: 'Disk Usage', value: 88, timestamp: new Date() }
];

const activeAlerts = evaluateAlerts(systemMetrics, alertRules);
activeAlerts.forEach(alert => {
  console.log(`[${alert.severity.toUpperCase()}] ${alert.ruleName}: ${alert.message} (Value: ${alert.metric.value})`);
});

Expression Validation for User Input

import { isValidExpression } from '@superset-ui/core';

// Validate user-entered expressions in real-time
const validateUserExpression = (expression: string): { valid: boolean; error?: string } => {
  if (!expression.trim()) {
    return { valid: false, error: 'Expression cannot be empty' };
  }
  
  if (!isValidExpression(expression)) {
    return { valid: false, error: 'Invalid mathematical expression' };
  }
  
  // Additional validation rules
  const forbiddenPatterns = [
    /[a-zA-Z]+/g,  // No letters except 'x', 'and', 'or', 'xor'
    /\.\./g,       // No double dots
    /[{}[\]]/g     // No brackets/braces
  ];
  
  const allowedWords = ['x', 'and', 'or', 'xor'];
  const letterMatches = expression.match(/[a-zA-Z]+/g);
  
  if (letterMatches) {
    const invalidWords = letterMatches.filter(word => !allowedWords.includes(word));
    if (invalidWords.length > 0) {
      return { 
        valid: false, 
        error: `Invalid words: ${invalidWords.join(', ')}. Only 'x', 'and', 'or', 'xor' are allowed.` 
      };
    }
  }
  
  for (const pattern of forbiddenPatterns.slice(1)) { // Skip the letter pattern
    if (pattern.test(expression)) {
      return { valid: false, error: 'Expression contains forbidden characters' };
    }
  }
  
  return { valid: true };
};

// React component for expression input
const ExpressionInput: React.FC<{
  value: string;
  onChange: (value: string) => void;
}> = ({ value, onChange }) => {
  const validation = validateUserExpression(value);
  
  return (
    <div>
      <input
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder="Enter expression (e.g., x > 10 and x < 100)"
        style={{
          borderColor: validation.valid ? 'green' : 'red'
        }}
      />
      {!validation.valid && validation.error && (
        <div style={{ color: 'red', fontSize: '12px' }}>
          {validation.error}
        </div>
      )}
      {validation.valid && (
        <div style={{ color: 'green', fontSize: '12px' }}>
          ✓ Valid expression
        </div>
      )}
    </div>
  );
};

Advanced Mathematical Operations

import { evalExpression } from '@superset-ui/core';

// Mathematical utilities using expressions
const mathUtils = {
  // Check if number is in range
  isInRange: (value: number, min: number, max: number): boolean => {
    return evalExpression(`x >= ${min} and x <= ${max}`, value) === 1;
  },
  
  // Check if number is even
  isEven: (value: number): boolean => {
    return evalExpression('x % 2 == 0', value) === 1;
  },
  
  // Check if number is prime (simplified check for small numbers)
  isPrime: (value: number): boolean => {
    if (value < 2) return false;
    if (value === 2) return true;
    if (value % 2 === 0) return false;
    
    // Check odd divisors up to sqrt(value)
    for (let i = 3; i <= Math.sqrt(value); i += 2) {
      if (evalExpression(`x % ${i} == 0`, value) === 1) {
        return false;
      }
    }
    return true;
  },
  
  // Apply scaling based on conditions
  conditionalScale: (value: number): number => {
    // Scale differently based on value ranges
    if (evalExpression('x < 10', value)) return value * 10;
    if (evalExpression('x >= 10 and x < 100', value)) return value * 2;
    if (evalExpression('x >= 100', value)) return value * 0.1;
    return value;
  }
};

// Usage
const numbers = [2, 5, 8, 15, 25, 150];
numbers.forEach(num => {
  console.log(`${num}: even=${mathUtils.isEven(num)}, prime=${mathUtils.isPrime(num)}, scaled=${mathUtils.conditionalScale(num)}`);
});

Related Documentation

  • Core Models & Utilities - Utility functions and type checking
  • Data Formatting - Number formatting and validation integration
  • Translation - Internationalized error messages
  • Plugin System - Chart plugin validation and configuration

Install with Tessl CLI

npx tessl i tessl/npm-superset-ui--core@0.18.1

docs

core-models.md

dashboard.md

data-connection.md

data-formatting.md

index.md

plugin-system.md

translation.md

ui-styling.md

validation-math.md

tile.json