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

helpers.mddocs/api/utilities/

Helper Utilities

General-purpose utility functions for data manipulation, string operations, and type checking.

Capabilities

String Operations

Snake Case Conversion

Converts text to snake_case format.

/**
 * Convert text to snake_case format
 * @param text - Text to convert
 * @returns Snake-cased string
 */
function snakeCaseName(text: string): string;

Usage Example:

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

snakeCaseName('UserProfile');      // 'user_profile'
snakeCaseName('dataSource');       // 'data_source'
snakeCaseName('My Chart Name');    // 'my_chart_name'

Special Characters Check

Checks if text contains special characters.

/**
 * Check if text contains special characters (non-alphanumeric, excluding spaces)
 * @param text - Text to check
 * @returns True if text contains special characters
 */
function hasSpecialCharacters(text: string): boolean;

Usage Example:

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

hasSpecialCharacters('Hello World');   // false
hasSpecialCharacters('Hello@World');   // true
hasSpecialCharacters('test123');       // false

Array Operations

Array Intersection

Checks if two arrays have common elements.

/**
 * Check if two arrays have any common elements
 * @param tags - First array
 * @param tags2 - Second array
 * @returns True if arrays have intersection
 */
function hasIntersection(tags: string[], tags2: string[]): boolean;

Usage Example:

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

hasIntersection(['a', 'b'], ['b', 'c']);    // true
hasIntersection(['a', 'b'], ['c', 'd']);    // false
hasIntersection(['x'], ['x', 'y', 'z']);    // true

Toggle Array Value

Adds or removes a value from an array.

/**
 * Toggle a value in an array (add if missing, remove if present)
 * @param initialArray - Source array
 * @param value - Value to toggle
 * @returns New array with value toggled
 */
function toggleArrayValue<T = string>(initialArray: T[], value: T): T[];

Usage Example:

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

toggleArrayValue(['a', 'b'], 'c');     // ['a', 'b', 'c']
toggleArrayValue(['a', 'b', 'c'], 'b'); // ['a', 'c']
toggleArrayValue([1, 2, 3], 4);        // [1, 2, 3, 4]

Replace String in Array

Replaces occurrences of a string in an array.

/**
 * Replace all occurrences of a string in an array
 * @param arrayToUpdate - Array to update
 * @param valueToReplace - Value to find
 * @param newValue - Replacement value
 * @returns New array with replacements
 */
function replaceStringInArray(
  arrayToUpdate: string[],
  valueToReplace: string,
  newValue: string
): string[];

Usage Example:

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

replaceStringInArray(
  ['old', 'test', 'old'],
  'old',
  'new'
);
// Result: ['new', 'test', 'new']

Color Operations

Hex to RGB Conversion

Converts hex color to RGB or RGBA format.

/**
 * Convert hex color to RGB or RGBA string
 * @param hex - Hex color code (e.g., '#FF5733')
 * @param alpha - Optional alpha value (0-1)
 * @returns RGB or RGBA string
 */
function hexToRGB(hex: string, alpha: number | undefined): string;

Usage Example:

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

hexToRGB('#FF5733', undefined);   // 'rgb(255, 87, 51)'
hexToRGB('#FF5733', 0.5);         // 'rgba(255, 87, 51, 0.5)'
hexToRGB('#00FF00', 1);           // 'rgba(0, 255, 0, 1)'

Is Hex Code Color

Validates if a string is a valid hex color code.

/**
 * Validate if a string is a valid hex color code
 * @param color - String to validate
 * @returns True if valid hex color (#RGB, #RRGGBB, or #RRGGBBAA)
 */
function isHexCodeColor(color: string): boolean;

Usage Example:

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

isHexCodeColor('#FF5733');    // true
isHexCodeColor('#FFF');       // true (3-digit hex)
isHexCodeColor('#FF5733AA');  // true (with alpha)
isHexCodeColor('FF5733');     // false (missing #)
isHexCodeColor('red');        // false (not hex)
isHexCodeColor('#GGGGGG');    // false (invalid characters)

Get Invalid Hex Colors

Validates an array of hex color codes and returns invalid ones.

/**
 * Validate an array of hex color codes
 * @param colors - Array of strings to validate as hex colors
 * @returns Array of invalid colors found, empty if all are valid
 */
function getInvalidHexColors(colors: string[]): string[];

Usage Example:

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

const colors = ['#FF5733', '#00FF00', 'red', '#GGGGGG', '#123'];
const invalid = getInvalidHexColors(colors);
console.log(invalid); // ['red', '#GGGGGG']

// Validate before use
const userColors = ['#FF0000', '#00FF00', 'blue'];
const invalidColors = getInvalidHexColors(userColors);
if (invalidColors.length > 0) {
  console.error('Invalid colors:', invalidColors);
}

Clean Color Array

Processes an array of strings, trimming whitespace and filtering out empty values.

/**
 * Clean an array of strings, trimming and filtering empty values
 * @param colors - Array of strings to process
 * @returns Cleaned array of strings
 */
function cleanColorArray(colors: string[]): string[];

Usage Example:

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

const rawColors = ['#FF5733', '  #00FF00  ', '', '  ', '#0000FF'];
const cleaned = cleanColorArray(rawColors);
console.log(cleaned); // ['#FF5733', '#00FF00', '#0000FF']

Get Readable Text Color

Returns the best contrasting text color (black or white) for a given background color.

/**
 * Get the best contrasting text color for a background
 * Uses APCA contrast algorithm for perception-based contrast
 * @param backgroundColor - Hex color string for the background
 * @returns 'white' or 'black' depending on which has better contrast
 */
function getReadableTextColor(backgroundColor: string): string;

Usage Example:

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

getReadableTextColor('#FF5733'); // 'white' (dark red background)
getReadableTextColor('#FFFF00'); // 'black' (yellow background)
getReadableTextColor('#000000'); // 'white' (black background)
getReadableTextColor('#FFFFFF'); // 'black' (white background)

// Use for dynamic styling
const bgColor = userPreferences.backgroundColor;
const textColor = getReadableTextColor(bgColor);
console.log(`Use text color ${textColor} on background ${bgColor}`);

Object Operations

Remove Empty Properties

Removes undefined and null properties from an object recursively.

/**
 * Remove undefined and null properties from an object recursively
 * @param object - Object to clean
 * @returns New object without empty properties
 */
function removeEmptyProperties(object: Record<string, any>): Record<string, any>;

Usage Example:

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

removeEmptyProperties({
  name: 'test',
  value: null,
  nested: {
    a: 1,
    b: undefined
  }
});
// Result: { name: 'test', nested: { a: 1 } }

Deep Equality

Performs deep equality comparison between two objects.

/**
 * Deep equality comparison between two objects
 * @param object1 - First object
 * @param object2 - Second object
 * @returns True if objects are deeply equal
 */
function deepEqual(
  object1: Record<string, any>,
  object2: Record<string, any>
): boolean;

Usage Example:

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

deepEqual({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } });  // true
deepEqual({ a: 1 }, { a: 2 });                             // false
deepEqual({ a: { b: 1 } }, { a: { b: 2 } });              // false

Type Guards

Not Null Type Guard

Type guard to filter out null values.

/**
 * Type guard to exclude null values
 * @param arg - Value to check
 * @returns True if value is not null
 */
function isNotNull<T>(arg: T): arg is Exclude<T, null>;

Usage Example:

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

const values = [1, null, 2, null, 3];
const filtered = values.filter(isNotNull);  // Type: number[]
// Result: [1, 2, 3]

Lightdash Mode Check

Type guard for LightdashMode enum values.

/**
 * Check if a string is a valid LightdashMode
 * @param x - String to check
 * @returns True if x is a valid LightdashMode
 */
function isLightdashMode(x: string): x is LightdashMode;

DBT Project Utilities

Get Project Directory

Extracts project directory from DBT connection configuration.

/**
 * Get project directory from DBT connection configuration
 * @param dbtConnection - DBT project configuration
 * @returns Project directory path or undefined
 */
function getProjectDirectory(dbtConnection?: DbtProjectConfig): string | undefined;

Usage Example:

import { getProjectDirectory, DbtProjectType } from '@lightdash/common';

const dbtConfig = {
  type: DbtProjectType.DBT,
  project_dir: '/path/to/project'
};

const dir = getProjectDirectory(dbtConfig);  // '/path/to/project'

Additional Types

SQL Query Results

Types for working with raw SQL query results.

type SqlResultsRow = { [columnName: string]: unknown };

type SqlResultsField = {
  name: string;
  type: string;
};

type SqlQueryResults = {
  fields: SqlResultsField[];
  rows: SqlResultsRow[];
};

Complete User Schema

Zod schema for user profile completion.

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 CompleteUserArgs = z.infer<typeof CompleteUserSchema>;

Lightdash Install Type

Enum for tracking how Lightdash was installed.

enum LightdashInstallType {
  DOCKER_IMAGE = 'docker_image',
  BASH_INSTALL = 'bash_install',
  HEROKU = 'heroku',
  UNKNOWN = 'unknown'
}

Tree Create Space

Type for creating hierarchical space structures.

type TreeCreateSpace = CreateSpace & {
  children?: TreeCreateSpace[];
  groupAccess?: {
    groupUuid: string;
    role: SpaceMemberRole;
  }[];
};

Accessor Functions

Safe access to array and object values with error handling.

/**
 * Safely get a value from an array-like object with index bounds checking
 * @param obj - Array-like object to access
 * @param key - Index to access
 * @param errorMessage - Optional custom error message
 * @returns Value at the index
 * @throws Error if index is out of bounds or object is undefined
 */
function getArrayValue<T>(
  obj: ArrayLike<T> | undefined,
  key: number,
  errorMessage?: string
): T;

/**
 * Safely get a value from an object with key existence checking
 * @param obj - Object to access
 * @param key - Key to access
 * @param errorMessage - Optional custom error message
 * @returns Value at the key
 * @throws Error if key doesn't exist or object is undefined
 */
function getObjectValue<T>(
  obj: Record<string | number, T> | undefined,
  key: string | number,
  errorMessage?: string
): T;

/**
 * Type guard to check if an object has a specific property
 * @param obj - Object to check
 * @param property - Property name to check for
 * @returns True if object has the property
 */
function hasProperty<T>(obj: unknown, property: string): obj is { scope: T };

Usage:

import { getArrayValue, getObjectValue, hasProperty } from '@lightdash/common';

// Safe array access
const arr = ['a', 'b', 'c'];
const value = getArrayValue(arr, 1);  // 'b'

// Safe object access
const obj = { name: 'John', age: 30 };
const name = getObjectValue(obj, 'name');  // 'John'

// Property checking
if (hasProperty(someObject, 'scope')) {
  console.log(someObject.scope);
}

Slug Utilities

Generate and manipulate slugs for content-as-code paths.

/**
 * Generate a URL-safe slug from a name
 * @param name - Name to convert to slug
 * @returns URL-safe slug string
 */
function generateSlug(name: string): string;

/**
 * Convert a slug to ltree path format (PostgreSQL ltree extension)
 * @param slug - Slug to convert
 * @returns Ltree path string
 */
function getLtreePathFromSlug(slug: string): string;

/**
 * Convert a content-as-code file path to ltree path
 * @param path - Content-as-code path
 * @returns Ltree path string
 */
function getLtreePathFromContentAsCodePath(path: string): string;

/**
 * Convert ltree path back to content-as-code path
 * @param path - Ltree path
 * @returns Content-as-code path string
 */
function getContentAsCodePathFromLtreePath(path: string): string;

/**
 * Get deepest paths from a list (removes parent paths if children exist)
 * @param paths - Array of ltree paths
 * @returns Array of deepest paths only
 */
function getDeepestPaths(paths: string[]): string[];

/**
 * Check if one path is a sub-path of another
 * @param path - Parent path
 * @param subPath - Potential sub-path
 * @returns True if subPath is under path
 */
function isSubPath(path: string, subPath: string): boolean;

Usage:

import {
  generateSlug,
  getLtreePathFromSlug,
  getDeepestPaths,
  isSubPath,
} from '@lightdash/common';

// Generate slugs
const slug = generateSlug('My Dashboard Name');  // 'my-dashboard-name'

// Ltree path conversion
const ltreePath = getLtreePathFromSlug('parent.child.item');

// Check path relationships
isSubPath('spaces.sales', 'spaces.sales.dashboards');  // true

// Get deepest paths
const paths = ['a', 'a.b', 'a.b.c', 'd', 'd.e'];
const deepest = getDeepestPaths(paths);  // ['a.b.c', 'd.e']

Miscellaneous Utilities

/**
 * Get subtotal cache key from dimension names
 * @param dimensions - Array of dimension names
 * @returns Cache key string
 */
function getSubtotalKey(dimensions: string[]): string;

/**
 * Set a UUID parameter in the URL
 * @param key - Parameter key
 * @param value - UUID value (or null to remove)
 */
function setUuidParam(key: string, value?: string | null): void;

/**
 * Maximum number of nodes in metrics tree visualization
 */
const MAX_METRICS_TREE_NODE_COUNT: number;  // Value: 30

Seed Data Constants

Test and development seed data for consistent testing.

// Organization seed data
const SEED_ORG_1: {
  organization_uuid: string;
  organization_name: string;
};

// User seed data
const SEED_ORG_1_ADMIN: {
  user_uuid: string;
  first_name: string;
  last_name: string;
  is_marketing_opted_in: boolean;
  is_tracking_anonymized: boolean;
  is_setup_complete: boolean;
  is_active: boolean;
};

const SEED_ORG_1_ADMIN_EMAIL: {
  email: string;
  is_primary: boolean;
};

const SEED_ORG_1_ADMIN_PASSWORD: {
  password: string;
};

const SEED_ORG_1_ADMIN_ROLE: OrganizationMemberRole;

// Additional user seeds
const SEED_ORG_1_EDITOR: typeof SEED_ORG_1_ADMIN;
const SEED_ORG_1_VIEWER: typeof SEED_ORG_1_ADMIN;
const SEED_ORG_2_ADMIN: typeof SEED_ORG_1_ADMIN;

// Project and space seeds
const SEED_PROJECT: {
  project_uuid: string;
  name: string;
  project_type: ProjectType;
  dbt_connection_type: DbtProjectType;
  dbt_connection: null;
  copied_from_project_uuid: null;
  organization_warehouse_credentials_uuid: null;
};

const SEED_SPACE: {
  name: string;
};

// Group seeds
const SEED_GROUP: {
  groupUuid: string;
  name: string;
};

const SEED_EMBED_SECRET: string;

// Space tree structures for testing
const SPACE_TREE_1: readonly TreeCreateSpace[];
const SPACE_TREE_2: readonly TreeCreateSpace[];