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

project-config.mddocs/api/utilities/specialized/

Project Configuration Utilities

Functions for loading, validating, and working with Lightdash project configurations.

Capabilities

This module provides the following functionality:

Configuration Loading

/**
 * Loads Lightdash project configuration from lightdash.yml file
 * Validates and parses the configuration with error handling
 * @param projectDir - Path to project directory containing lightdash.yml
 * @returns Parsed and validated project configuration
 * @throws Error if configuration is invalid or file cannot be read
 */
function loadLightdashProjectConfig(projectDir: string): Promise<LightdashProjectConfig>;

Project Utilities

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

Examples

Loading Project Configuration

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

// Load project configuration
try {
  const config = await loadLightdashProjectConfig('/path/to/dbt/project');

  console.log('Project name:', config.name);
  console.log('DBT project:', config.dbt_project_dir);
  console.log('DBT profiles:', config.dbt_profiles_dir);

  // Access model configuration
  if (config.models) {
    console.log('Model overrides:', Object.keys(config.models));
  }

  // Access metric overrides
  if (config.metrics) {
    console.log('Metric overrides:', Object.keys(config.metrics));
  }
} catch (error) {
  console.error('Failed to load project config:', error.message);
}

// Use in CLI or API
const projectConfig = await loadLightdashProjectConfig(process.cwd());

Working with DBT Configuration

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

// Get project directory from DBT connection
const dbtConnection: DbtProjectConfig = {
  type: 'dbt_cloud_ide',
  target: 'dev',
  project_dir: '/home/user/my-dbt-project',
  profiles_dir: '/home/user/.dbt',
};

const projectDir = getProjectDirectory(dbtConnection);
console.log('Project directory:', projectDir);
// Output: '/home/user/my-dbt-project'

// Handle missing configuration
const emptyDir = getProjectDirectory();
console.log('Directory:', emptyDir); // undefined

Configuration Validation

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

async function validateProjectSetup(projectPath: string): Promise<boolean> {
  try {
    const config = await loadLightdashProjectConfig(projectPath);

    // Verify required fields
    if (!config.name) {
      console.error('Project name is required');
      return false;
    }

    if (!config.dbt_project_dir) {
      console.error('DBT project directory is required');
      return false;
    }

    console.log('Project configuration is valid');
    return true;
  } catch (error) {
    console.error('Invalid configuration:', error.message);
    return false;
  }
}

CLI Tool Example

import { loadLightdashProjectConfig, getProjectDirectory } from '@lightdash/common';
// Node.js built-in (server-side only)
import path from 'path';

async function deployProject(options: { projectDir?: string }) {
  // Determine project directory
  const projectDir = options.projectDir || process.cwd();

  // Load configuration
  const config = await loadLightdashProjectConfig(projectDir);

  console.log(`Deploying project: ${config.name}`);

  // Get DBT project directory
  const dbtProjectDir = config.dbt_project_dir || path.join(projectDir, 'dbt');
  console.log(`DBT project directory: ${dbtProjectDir}`);

  // Use configuration for deployment
  await deployToLightdash(config);
}

// Usage
deployProject({ projectDir: '/path/to/project' });

Configuration Inspection

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

async function inspectProject(projectPath: string) {
  const config = await loadLightdashProjectConfig(projectPath);

  console.log('=== Project Configuration ===');
  console.log(`Name: ${config.name}`);
  console.log(`DBT Project: ${config.dbt_project_dir}`);
  console.log(`DBT Profiles: ${config.dbt_profiles_dir}`);

  // List model overrides
  if (config.models && Object.keys(config.models).length > 0) {
    console.log('\nModel Overrides:');
    for (const [modelName, modelConfig] of Object.entries(config.models)) {
      console.log(`  - ${modelName}`);
      if (modelConfig.enabled !== undefined) {
        console.log(`    Enabled: ${modelConfig.enabled}`);
      }
    }
  }

  // List metric overrides
  if (config.metrics && Object.keys(config.metrics).length > 0) {
    console.log('\nMetric Overrides:');
    for (const [metricName, metricConfig] of Object.entries(config.metrics)) {
      console.log(`  - ${metricName}`);
    }
  }
}

Project Migration

import { loadLightdashProjectConfig } from '@lightdash/common';
// Node.js built-in (server-side only)
import fs from 'fs/promises';

async function migrateProjectConfig(oldPath: string, newPath: string) {
  // Load old configuration
  const config = await loadLightdashProjectConfig(oldPath);

  console.log(`Migrating project: ${config.name}`);

  // Update paths for new location
  const updatedConfig = {
    ...config,
    dbt_project_dir: config.dbt_project_dir?.replace(oldPath, newPath),
    dbt_profiles_dir: config.dbt_profiles_dir?.replace(oldPath, newPath),
  };

  // Save to new location
  const yamlContent = YAML.stringify(updatedConfig);
  await fs.writeFile(
    path.join(newPath, 'lightdash.yml'),
    yamlContent
  );

  console.log('Migration complete');
}

Configuration Builder

import type { LightdashProjectConfig } from '@lightdash/common';

function createProjectConfig(options: {
  name: string;
  dbtProjectDir: string;
  dbtProfilesDir?: string;
}): LightdashProjectConfig {
  return {
    name: options.name,
    dbt_project_dir: options.dbtProjectDir,
    dbt_profiles_dir: options.dbtProfilesDir || '~/.dbt',
    models: {},
    metrics: {},
  };
}

// Usage
const config = createProjectConfig({
  name: 'my-analytics-project',
  dbtProjectDir: './dbt',
});

API Integration

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

// API endpoint to get project configuration
app.get('/api/projects/:id/config', async (req, res) => {
  try {
    const project = await getProject(req.params.id);
    const projectPath = getProjectPath(project);

    const config = await loadLightdashProjectConfig(projectPath);

    // Return sanitized configuration (without sensitive data)
    res.json({
      name: config.name,
      dbtProjectDir: config.dbt_project_dir,
      modelCount: Object.keys(config.models || {}).length,
      metricCount: Object.keys(config.metrics || {}).length,
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Configuration Testing

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

describe('Project configuration', () => {
  it('should load valid configuration', async () => {
    const config = await loadLightdashProjectConfig('./test-fixtures/valid-project');

    expect(config.name).toBe('Test Project');
    expect(config.dbt_project_dir).toBeDefined();
  });

  it('should throw on invalid configuration', async () => {
    await expect(
      loadLightdashProjectConfig('./test-fixtures/invalid-project')
    ).rejects.toThrow();
  });

  it('should extract project directory', () => {
    const dbtConfig = {
      type: 'dbt_cloud_ide',
      project_dir: '/path/to/project',
    };

    const dir = getProjectDirectory(dbtConfig);
    expect(dir).toBe('/path/to/project');
  });
});

Configuration Structure

The lightdash.yml file typically contains:

name: my-project
dbt_project_dir: ./dbt
dbt_profiles_dir: ~/.dbt

models:
  my_model:
    enabled: true
    meta:
      lightdash:
        label: "My Model"

metrics:
  my_metric:
    enabled: false

Use Cases

  • CLI Tools: Load configuration for command-line operations
  • Project Deployment: Read settings before deploying to Lightdash
  • Configuration Validation: Validate project setup before operations
  • Path Resolution: Resolve DBT project and profile directories
  • Project Migration: Transfer projects between environments
  • API Integration: Expose project configuration through APIs

Error Handling

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

async function safeLoadConfig(projectPath: string) {
  try {
    return await loadLightdashProjectConfig(projectPath);
  } catch (error) {
    if (error.code === 'ENOENT') {
      console.error('lightdash.yml not found in project directory');
    } else if (error.name === 'YAMLException') {
      console.error('Invalid YAML syntax in lightdash.yml');
    } else {
      console.error('Failed to load configuration:', error.message);
    }
    return null;
  }
}

Related Utilities

  • DBT Helpers: See dbt-helpers.md for DBT-specific utilities
  • Project Types: Configuration types for different project setups
  • Validation: Schema validation for configuration files