Core utilities and components for Apache Superset's frontend UI framework providing data visualization, formatting, and chart composition capabilities
—
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.
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.
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 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;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;The expression evaluator supports a comprehensive set of mathematical and logical operations:
+ - Addition- - Subtraction* - Multiplication/ - Division% - Modulo^ - Exponentiation== - Equal to> - Greater than>= - Greater than or equal to< - Less than<= - Less than or equal toand - Logical ANDor - Logical ORxor - Exclusive OR (XOR)& - Bitwise AND| - Bitwise ORx - Variable that gets substituted with the provided valueimport {
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"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>
);
};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)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)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.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})`);
});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>
);
};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)}`);
});Install with Tessl CLI
npx tessl i tessl/npm-superset-ui--core@0.18.1