or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

api

features

charts

charts.mdconditional-formatting.mdvisualizations.md
authorization.mdchangesets.mdcharts-as-code.mdcompiler.mddashboards.mddbt.mdee-features.mdformatting.mdparameters.mdpivot.mdprojects-spaces.mdsql-runner.mdtemplating.mdwarehouse.md
index.md
tile.json

validation.mddocs/api/utilities/

Validation and Type Checking Utilities

This module provides comprehensive validation, type checking, and assertion utilities for the Lightdash platform. It includes email/password validation, organization name validation, type guards, assertion helpers, and JSON schema validation for configuration files.

Capabilities

This module provides the following functionality:

Dependencies

This module uses Zod for schema validation. Install it separately:

npm install zod
// Zod types used by validation functions
// These types come from the 'zod' package
import type { z } from 'zod';

type ZodSchema = z.ZodType<any, any, any>;

Validation Functions

Email Validation

/**
 * Validates an email address using a regular expression
 * Checks for valid email format and rejects whitespace
 * @param email - The email address to validate
 * @returns true if the email is valid, false otherwise
 */
function validateEmail(email: string): boolean;

/**
 * Returns a Zod schema for email validation
 * @returns Zod schema that validates email format and rejects whitespace
 */
function getEmailSchema(): ZodSchema;

/**
 * Validates a full email address using a stricter regex pattern
 * @param email - The email address to validate
 * @returns true if the email address matches the pattern
 */
function isValidEmailAddress(email: string): boolean;

/**
 * Extracts the domain portion from an email address
 * @param email - The email address
 * @returns The domain in lowercase (part after @)
 * @throws Error if email contains whitespace or is invalid
 */
function getEmailDomain(email: string): string;

/**
 * Validates that a domain string has valid format for email domains
 * Checks against VALID_EMAIL_DOMAIN_REGEX pattern using String.match()
 * @param value - The domain to validate
 * @returns RegExpMatchArray if domain is valid, null otherwise
 */
function isValidEmailDomain(value: string): RegExpMatchArray | null;

/**
 * Validates organization email domains, rejecting common email providers
 * Ensures domains are not consumer email services (gmail.com, yahoo.com, etc.)
 * @param domains - Array of domain strings to validate
 * @returns Error message string if invalid domains found, undefined if all valid
 */
function validateOrganizationEmailDomains(domains: string[]): string | undefined;

Example:

import {
  validateEmail,
  getEmailSchema,
  isValidEmailAddress,
  getEmailDomain,
  isValidEmailDomain,
  validateOrganizationEmailDomains,
} from '@lightdash/common';

// Basic email validation
if (validateEmail('user@example.com')) {
  console.log('Valid email');
}

// Use with Zod for form validation
const schema = z.object({
  email: getEmailSchema(),
});

// Stricter validation
if (isValidEmailAddress('user@company.example.com')) {
  console.log('Valid email address');
}

// Extract domain from email
const domain = getEmailDomain('user@company.com'); // Returns 'company.com'

// Validate domain format (returns RegExpMatchArray or null)
const domainMatch = isValidEmailDomain('company.com');
if (domainMatch) {
  console.log('Valid domain format');
}

// Validate organization domains (rejects consumer email providers)
const error = validateOrganizationEmailDomains(['company.com', 'gmail.com']);
if (error) {
  console.error(error); // "gmail.com is not allowed as organization email"
}

// Valid organization domains
const valid = validateOrganizationEmailDomains(['company.com', 'business.org']);
console.log(valid); // undefined (no errors)

Password Validation

/**
 * Validates a password string
 * Requires: minimum 8 characters, at least one letter, at least one number or symbol
 * @param password - Password to validate
 * @returns true if password meets requirements
 */
function validatePassword(password: string): boolean;

/**
 * Returns a Zod schema for password validation
 * Password must be at least 8 characters, contain a letter, and contain a number or symbol
 * @returns Zod schema for password validation
 */
function getPasswordSchema(): z.ZodEffects<z.ZodString>;

Example:

import { validatePassword, getPasswordSchema } from '@lightdash/common';

// Basic validation
if (validatePassword('SecurePass123!')) {
  console.log('Valid password');
}

// Use with Zod
const schema = z.object({
  password: getPasswordSchema(),
});

User Completion Schema

/**
 * Zod schema for completing user setup with organization details
 * Used during user onboarding to collect additional information
 */
const CompleteUserSchema: z.ZodObject<{
  organizationName: z.ZodOptional<z.ZodString>;
  jobTitle: z.ZodString;
  enableEmailDomainAccess: z.ZodDefault<z.ZodBoolean>;
  isMarketingOptedIn: z.ZodDefault<z.ZodBoolean>;
  isTrackingAnonymized: z.ZodDefault<z.ZodBoolean>;
}>;

/**
 * Type inferred from CompleteUserSchema
 */
type CompleteUserArgs = z.infer<typeof CompleteUserSchema>;

Example:

import { CompleteUserSchema, type CompleteUserArgs } from '@lightdash/common';

const completeUserData: CompleteUserArgs = {
  organizationName: 'My Company',
  jobTitle: 'Data Analyst',
  enableEmailDomainAccess: false,
  isMarketingOptedIn: true,
  isTrackingAnonymized: false,
};

// Validate with Zod
const result = CompleteUserSchema.safeParse(completeUserData);
if (result.success) {
  console.log('User data is valid');
}

Organization Name Validation

/**
 * Validates an organization name
 * @param name - Organization name to validate
 * @returns true if the name is valid (letters, numbers, spaces, underscores, dashes only)
 */
function validateOrganizationName(name: string): boolean;

/**
 * Returns a Zod schema for organization name validation
 * @returns Zod schema that validates organization names
 */
function getOrganizationNameSchema(): ZodSchema;

/**
 * Validates organization name and throws a ParameterError if invalid
 * @param name - Organization name to validate
 * @throws ParameterError if the name is invalid
 */
function validateOrganizationNameOrThrow(name: string): void;

Example:

import {
  validateOrganizationName,
  getOrganizationNameSchema,
  validateOrganizationNameOrThrow
} from '@lightdash/common';

// Basic validation
if (validateOrganizationName('My Company')) {
  console.log('Valid organization name');
}

// With Zod
const schema = z.object({
  orgName: getOrganizationNameSchema(),
});

// Validate and throw on error
try {
  validateOrganizationNameOrThrow('Invalid@Name');
} catch (error) {
  console.error('Invalid organization name');
}

Type Guards

/**
 * Type guard that filters out null values from arrays
 * Note: Only filters null, NOT undefined. Use with caution if your data may contain undefined.
 * @param arg - Value to check
 * @returns true if value is not null
 */
function isNotNull<T>(arg: T): arg is Exclude<T, null>;

/**
 * Type guard to check if a value is an API error response
 * @param error - Value to check
 * @returns true if value is an ApiError
 */
function isApiError(error: unknown): error is ApiError;

/**
 * Type guard to check if an account is a JWT user
 * @param account - Account to check (optional)
 * @returns true if account exists and is a JWT-authenticated user
 */
function isJwtUser(account?: Account): account is AnonymousAccount;

function isLightdashMode(x: string): x is LightdashMode;

Example:

import { isNotNull } from '@lightdash/common';

// Filters only null values
const values: (string | null)[] = ['a', null, 'b', null, 'c'];
const nonNull = values.filter(isNotNull);
// Returns: ['a', 'b', 'c'] with type string[]

// Important: isNotNull does NOT filter undefined
const valuesWithUndefined: (string | null | undefined)[] = ['a', null, 'b', undefined, 'c'];
const filtered = valuesWithUndefined.filter(isNotNull);
// Returns: ['a', 'b', undefined, 'c'] - undefined is NOT filtered!

Assertion Utilities

function assertUnreachable(_x: never, error: string | Error): never;

Example:

import assertUnreachable from '@lightdash/common';

type Status = 'pending' | 'success' | 'error';

function handleStatus(status: Status) {
  switch (status) {
    case 'pending':
      return 'Processing...';
    case 'success':
      return 'Done!';
    case 'error':
      return 'Failed';
    default:
      return assertUnreachable(status, 'Unknown status');
      // TypeScript will error if any status values are not handled
  }
}

JSON Schema Validation

JSON Schema definitions for validating "as-code" YAML configuration files for charts, dashboards, DBT models, and project configuration.

const chartAsCodeSchema: object;
const dashboardAsCodeSchema: object;
const lightdashDbtYamlSchema: object;
const lightdashProjectConfigSchema: object;
const modelAsCodeSchema: object;

These are JSON Schema files exported for external validation of Lightdash configuration files.

Example:

import {
  chartAsCodeSchema,
  dashboardAsCodeSchema,
  lightdashProjectConfigSchema,
} from '@lightdash/common';
// External dependency - Install separately: npm install ajv
import Ajv from 'ajv';

const ajv = new Ajv();

// Validate a chart-as-code YAML file
const validateChart = ajv.compile(chartAsCodeSchema);
const isValid = validateChart(chartConfig);

if (!isValid) {
  console.error('Chart validation errors:', validateChart.errors);
}

// Validate dashboard-as-code configuration
const validateDashboard = ajv.compile(dashboardAsCodeSchema);
const dashboardValid = validateDashboard(dashboardConfig);

// Validate project configuration
const validateProject = ajv.compile(lightdashProjectConfigSchema);
const projectValid = validateProject(projectConfig);

URL Templating

The package provides URL templating utilities for dynamic URL generation using Liquid template syntax.

Render Templated URL

/**
 * Renders a templated URL with values from a result row
 * @param templatedUrl - Template string using ${} syntax
 * @param value - Current cell value
 * @param row - Complete row data
 * @returns Rendered URL string
 */
function renderTemplatedUrl(
  templatedUrl: string,
  value: ResultValue,
  row: Record<string, Record<string, ResultValue>>
): string;

Usage:

import { renderTemplatedUrl } from '@lightdash/common';

const templatedUrl = 'https://example.com/user/${row.users_user_id.raw}';
const value = { raw: 'John', formatted: 'John' };
const row = {
  'users_user_id': { raw: 123, formatted: '123' },
  'users_name': { raw: 'John', formatted: 'John' }
};

const url = renderTemplatedUrl(templatedUrl, value, row);
// Result: 'https://example.com/user/123'

Get Template Dependencies

/**
 * Extracts row field dependencies from a templated URL
 * @param templatedUrl - Template string to analyze
 * @returns Array of field names referenced in template
 */
function getTemplatedUrlRowDependencies(templatedUrl: string): string[];

Usage:

import { getTemplatedUrlRowDependencies } from '@lightdash/common';

const templatedUrl = 'https://example.com/user/${row.users_user_id.raw}?name=${row.users_name.formatted}';
const dependencies = getTemplatedUrlRowDependencies(templatedUrl);
// Result: ['users_user_id', 'users_name']

Validation Error Types

Types for handling validation errors in charts, dashboards, and tables.

/**
 * Enum for different types of validation errors
 */
enum ValidationErrorType {
  Chart = 'chart',
  Sorting = 'sorting',
  Filter = 'filter',
  Metric = 'metric',
  Model = 'model',
  Dimension = 'dimension',
  CustomMetric = 'custom metric',
}

/**
 * Enum for dashboard filter-specific validation errors
 */
enum DashboardFilterValidationErrorType {
  FieldDoesNotExist = 'field_does_not_exist',
  TableNotUsedByAnyChart = 'table_not_used_by_any_chart',
  TableDoesNotExist = 'table_does_not_exist',
}

/**
 * Enum for validation source types (what entity is being validated)
 */
enum ValidationSourceType {
  Chart = 'chart',
  Dashboard = 'dashboard',
  Table = 'table',
}

/**
 * Enum for validation targets (what to validate)
 */
enum ValidationTarget {
  CHARTS = 'charts',
  DASHBOARDS = 'dashboards',
  TABLES = 'tables',
}

/**
 * Base validation response with common fields
 */
type ValidationResponseBase = {
  validationId: number;
  createdAt: Date;
  name: string;
  error: string;
  errorType: ValidationErrorType;
  projectUuid: string;
  spaceUuid?: string;
  source?: ValidationSourceType;
};

/**
 * Validation error response for chart-specific errors
 */
type ValidationErrorChartResponse = ValidationResponseBase & {
  chartUuid: string | undefined; // Can be undefined if private content
  chartKind?: ChartKind;
  fieldName?: string;
  lastUpdatedBy?: string;
  lastUpdatedAt?: Date;
  chartViews: number;
  chartName?: string;
};

/**
 * Validation error response for dashboard-specific errors
 */
type ValidationErrorDashboardResponse = ValidationResponseBase & {
  dashboardUuid: string | undefined; // Can be undefined if private content
  chartName?: string;
  fieldName?: string;
  tableName?: string; // For dashboard filter errors referencing specific tables
  dashboardFilterErrorType?: DashboardFilterValidationErrorType;
  lastUpdatedBy?: string;
  lastUpdatedAt?: Date;
  dashboardViews: number;
};

/**
 * Validation error response for table-specific errors
 */
type ValidationErrorTableResponse = Omit<ValidationResponseBase, 'name'> & {
  name: string | undefined;
};

/**
 * Union type of all validation error responses
 */
type ValidationResponse =
  | ValidationErrorChartResponse
  | ValidationErrorDashboardResponse
  | ValidationErrorTableResponse;

/**
 * Compact validation summary with essential error information
 * Used for displaying validation errors in lists or summaries
 */
type ValidationSummary = Pick<
  ValidationResponse,
  'error' | 'createdAt' | 'validationId'
>;

/**
 * Payload for creating a table validation error
 */
type CreateTableValidation = Pick<
  ValidationErrorTableResponse,
  'error' | 'errorType' | 'projectUuid' | 'name' | 'source'
> & {
  modelName: string;
};

/**
 * Payload for creating a chart validation error
 */
type CreateChartValidation = Pick<
  ValidationErrorChartResponse,
  | 'error'
  | 'errorType'
  | 'fieldName'
  | 'name'
  | 'projectUuid'
  | 'chartUuid'
  | 'source'
  | 'chartName'
>;

/**
 * Payload for creating a dashboard validation error
 */
type CreateDashboardValidation = Pick<
  ValidationErrorDashboardResponse,
  | 'error'
  | 'errorType'
  | 'fieldName'
  | 'name'
  | 'projectUuid'
  | 'dashboardUuid'
  | 'chartName'
  | 'source'
>;

/**
 * Union type of all validation creation payloads
 */
type CreateValidation =
  | CreateTableValidation
  | CreateChartValidation
  | CreateDashboardValidation;

/**
 * API response for validation requests
 */
type ApiValidateResponse = {
  status: 'ok';
  results: ValidationResponse[];
};

/**
 * API response for dismissing validation errors
 */
type ApiValidationDismissResponse = {
  status: 'ok';
};

/**
 * Type guard to check if a validation error is a table error
 * @param error - Validation error or creation payload to check
 * @returns true if error is a table validation error
 */
function isTableValidationError(
  error: ValidationResponse | CreateValidation
): error is ValidationErrorTableResponse | CreateTableValidation;

/**
 * Type guard to check if a validation error is a chart error
 * @param error - Validation error or creation payload to check
 * @returns true if error is a chart validation error
 */
function isChartValidationError(
  error: ValidationResponse | CreateValidation
): error is ValidationErrorChartResponse | CreateChartValidation;

/**
 * Type guard to check if a validation error is a dashboard error
 * @param error - Validation error or creation payload to check
 * @returns true if error is a dashboard validation error
 */
function isDashboardValidationError(
  error: ValidationResponse | CreateValidation
): error is ValidationErrorDashboardResponse | CreateDashboardValidation;

/**
 * Validates that a string is a valid ValidationTarget enum value
 * @param validationTarget - String to validate
 * @returns true if validationTarget is a valid ValidationTarget
 */
function isValidationTargetValid(validationTarget: string): boolean;

Example:

import {
  ValidationSummary,
  ValidationResponse,
  ValidationErrorType,
  ValidationSourceType,
  isChartValidationError,
  isDashboardValidationError,
  isTableValidationError,
} from '@lightdash/common';

// Handle validation errors by type
function handleValidationError(error: ValidationResponse) {
  if (isChartValidationError(error)) {
    console.log(`Chart error: ${error.chartName} - ${error.error}`);
    console.log(`Chart views: ${error.chartViews}`);
  } else if (isDashboardValidationError(error)) {
    console.log(`Dashboard error: ${error.dashboardUuid} - ${error.error}`);
    console.log(`Dashboard views: ${error.dashboardViews}`);
  } else if (isTableValidationError(error)) {
    console.log(`Table error: ${error.name} - ${error.error}`);
  }
}

// Create a validation summary for display
function createSummary(response: ValidationResponse): ValidationSummary {
  return {
    error: response.error,
    createdAt: response.createdAt,
    validationId: response.validationId,
  };
}

// Example: Creating a chart validation
const chartValidation: CreateChartValidation = {
  error: 'Field "revenue" does not exist in explore',
  errorType: ValidationErrorType.Dimension,
  fieldName: 'revenue',
  name: 'Sales Dashboard',
  projectUuid: 'project-123',
  chartUuid: 'chart-456',
  source: ValidationSourceType.Chart,
  chartName: 'Revenue Over Time',
};

JSON Schema Exports

JSON schemas for validating configuration files, dbt YAML files, and charts/dashboards-as-code.

/**
 * JSON schema for chart-as-code validation (version 1.0)
 * Use with JSON validators to ensure chart-as-code files conform to expected structure
 */
const chartAsCodeSchema: JSONSchema;

/**
 * JSON schema for dashboard-as-code validation (version 1.0)
 * Use with JSON validators to ensure dashboard-as-code files conform to expected structure
 */
const dashboardAsCodeSchema: JSONSchema;

/**
 * JSON schema for Lightdash dbt YAML configuration (version 2.0)
 * Validates lightdash.yml files in dbt projects for proper structure and properties
 */
const lightdashDbtYamlSchema: JSONSchema;

/**
 * JSON schema for Lightdash project configuration (version 1.0)
 * Validates lightdash_config.yml files for project-level settings
 */
const lightdashProjectConfigSchema: JSONSchema;

/**
 * JSON schema for model-as-code validation (version 1.0)
 * Use with JSON validators to ensure model definitions conform to expected structure
 */
const modelAsCodeSchema: JSONSchema;

Usage:

import {
  chartAsCodeSchema,
  dashboardAsCodeSchema,
  lightdashDbtYamlSchema,
  lightdashProjectConfigSchema,
  modelAsCodeSchema,
} from '@lightdash/common';
// External dependency - Install separately: npm install ajv
import Ajv from 'ajv';

const ajv = new Ajv();

// Validate a chart-as-code file
const validate = ajv.compile(chartAsCodeSchema);
const valid = validate(chartData);

if (!valid) {
  console.error('Validation errors:', validate.errors);
}

// Validate dbt YAML configuration
const validateDbtYaml = ajv.compile(lightdashDbtYamlSchema);
const dbtYamlValid = validateDbtYaml(dbtYamlData);