This guide provides a comprehensive introduction to @lightdash/common, a TypeScript library for building dbt-based BI applications. It covers common patterns, essential workflows, and best practices to help you get started quickly.
Note: The Quick Reference below shows abbreviated function signatures for easy scanning. For complete parameter descriptions, type details, and usage examples, refer to the detailed documentation linked in the Reference Documentation section.
// === DATA MODELING TYPES ===
type Explore, CompiledTable, ExploreType, SummaryExplore, ExploreError
type Field, Dimension, Metric, CompiledDimension, CompiledMetric, CompiledField
type DimensionType, MetricType, FieldType, FieldId, FieldUrl
type Table, LineageGraph, Set
type CustomDimension, AdditionalMetric, TableCalculation
type ItemsMap, Item, FilterableItem
type ArgumentsOf<F> (Utility type extracting function arguments)
// === QUERY TYPES ===
type MetricQuery, MetricQueryRequest, CompiledMetricQuery
type Filters, FilterGroup, FilterRule, FilterGroupItem, MetricFilterRule
FilterOperator (19 operators: equals, greaterThan, inThePast, etc.)
type SortField, FieldValueSearchResult
type DateZoom
// === CORE API TYPES ===
type UUID, Email, ApiSuccess<T>, ApiSuccessEmpty
type ApiSort, ApiSortDirection
// === DASHBOARD & CHART TYPES ===
type Dashboard, DashboardTile, DashboardFilters, DashboardTab
type SavedChart, ChartConfig, ChartType, ChartKind
type CartesianChartConfig, PieChartConfig, TableChartConfig
type PivotConfig, PivotData, ConditionalFormattingConfig
// === WAREHOUSE TYPES ===
type WarehouseClient, WarehouseCredentials, WarehouseResults, WarehouseCatalog
WarehouseTypes (bigquery, postgres, snowflake, redshift, databricks, trino, clickhouse)
type Project, ProjectType, DbtProjectConfig
// === USER & AUTH TYPES ===
type LightdashUser, SessionUser, UserProfile, SerializedAccount
type Role, Group, ProjectMemberProfile, OrganizationMemberProfile
type PersonalAccessToken, OpenIdIdentity, LightdashOAuthToken
type ApiGetAccountResponse
type CompleteUserArgs
const CompleteUserSchema (Zod schema for user completion)
// === BACKGROUND JOBS ===
type Job, CompileJob, CreateProjectJob, JobStep, DbtLog
enum JobType, JobStatusType, JobStepStatusType, JobStepType
isCompileJob(value): value is CompileJob
isCreateProjectJob(value): value is CreateProjectJob
// === FEATURE FLAGS ===
enum FeatureFlags (UserGroupsEnabled, DashboardComments, AiCustomViz, Maps, DarkMode, etc.)
type FeatureFlag
isFeatureFlags(value): value is FeatureFlags
// === QUERY HISTORY ===
type QueryHistory, WarehouseQueryMetadata, BigQueryWarehouseQueryMetadata
enum QueryHistoryStatus (pending, ready, error, cancelled)
// === TAGS ===
type Tag, ApiGetTagsResponse, ApiCreateTagResponse
// === CONTENT PROMOTION ===
type PromotionChanges, PromotedSpace, PromotedDashboard, PromotedChart
enum PromotionAction (no changes, create, update, delete)
// === COMPILER & DBT ===
class ExploreCompiler { compileExplore(explore): Explore }
type UncompiledExplore, DbtManifestVersion, DbtModelNode, DbtMetric
// === FIELD & EXPLORE UTILITIES ===
getFields(explore): CompiledField[]
getDimensions(explore): CompiledDimension[]
getMetrics(explore): CompiledMetric[]
getVisibleFields(explore): CompiledField[]
findFieldByIdInExplore(explore, id): Field | undefined
getFieldMap(explore, additionalMetrics = []): Record<string, Field>
getItemMap(explore, additionalMetrics = [], tableCalculations = [], customDimensions = []): ItemsMap
getDimensionsFromItemsMap(itemsMap): Record<string, Dimension>
getFilterableDimensionsFromItemsMap(itemsMap): Record<string, FilterableDimension>
getMetricsFromItemsMap(itemsMap, filter?): Record<string, Metric>
getTableCalculationsFromItemsMap(itemsMap?): Record<string, TableCalculation>
// === FORMATTING UTILITIES ===
formatItemValue(item, value, convertToUTC?, parameters?): string
formatDate(date, timeInterval?, convertToUTC?): string
formatTimestamp(value, timeInterval?, convertToUTC?): string
formatNumberValue(value, format?): string
applyCustomFormat(item, value, customFormat): string
formatRawValue(field, value): unknown // Format raw value with UTC timezone handling
formatRawRows(rows, itemsMap): Record<string, unknown>[] // Format multiple raw rows
friendlyName(text): string
capitalize(word): string
isHexCodeColor(color): boolean
getInvalidHexColors(colors): string[]
cleanColorArray(colors): string[]
getReadableTextColor(backgroundColor): 'white' | 'black'
// === QUERY UTILITIES ===
itemsInMetricQuery(metricQuery): string[]
formatRows(rows, itemsMap, pivotValuesColumns?, parameters?): ResultRow[]
getResultValueArray(rows, preferRaw?, calculateMinAndMax?, excludeNulls?): { results, minsAndMaxes? }
getDateGroupLabel(axisItem): string | undefined // Get label for date-grouped dimensions
getAxisName({...}): string | undefined // Determine axis name for chart configuration
// === AUTHORIZATION ===
defineUserAbility(user, projectProfiles, customRoleScopes?): MemberAbility
getUserAbilityBuilder(args): AbilityBuilder<MemberAbility>
getScopes(options?): Scope[]
// === VISUALIZATION DATA MODELS ===
class CartesianChartDataModel { getChartOptions(), getPivotedChartData(), getTransformedData() }
class PieChartDataModel { constructor(args) }
class TableDataModel { constructor(args) }
// === VALIDATION UTILITIES ===
validateEmail(email): boolean
validatePassword(password): boolean
getEmailSchema(): ZodSchema // Returns Zod schema for email validation
getPasswordSchema(): ZodSchema // Returns Zod schema for password validation
isExploreError(explore): explore is ExploreError
isField(item): item is Field
isDimension(item): item is Dimension
isMetric(item): item is Metric
isCustomDimension(item): item is CustomDimension
isTableCalculation(item): item is TableCalculation
// === DATA UTILITIES ===
hasIntersection(arr1, arr2): boolean
toggleArrayValue(array, value): T[]
replaceStringInArray(array, valueToReplace, newValue): string[]
removeEmptyProperties(obj): Record<string, unknown>
deepEqual(obj1, obj2): boolean
getItemId(item): string
getItemLabel(item): string
snakeCaseName(text): string
hasSpecialCharacters(text): boolean
hexToRGB(hex, alpha: number | undefined): string
isNotNull<T>(arg): arg is Exclude<T, null>
getProjectDirectory(dbtConnection?): string | undefined
// === FILTER UTILITIES ===
isFilterGroup(item): item is FilterGroup
// === SQL RUNNER TYPES ===
type SqlRunnerQuery, SqlRunnerField, SqlRunnerTimeDimension
type SqlChart, SqlRunnerFilter, SqlRunnerPivot
type SqlResultsRow, SqlResultsField, SqlQueryResults
// === SPACE & CONTENT TYPES ===
type Space, SpaceDashboard, SpaceQuery, SpaceShare
type ContentType, Content, ContentAction
type TreeCreateSpace (Hierarchical space structure with children)
// === PARAMETER SYSTEM ===
type ParameterValue, ParametersValuesMap, LightdashProjectParameter
getParameterReferences(sql): string[]
validateParameterReferences(tableName, refs, available): void
getAvailableParameterNames(projectParams, exploreParams): string[]
// === CONDITIONAL FORMATTING ===
type ConditionalFormattingConfig, ConditionalFormattingColorRange
createConditionalFormattingConfigWithSingleColor(color, target?): Config
createConditionalFormattingConfigWithColorRange(color, target?): Config
// === PIVOT TABLES ===
getPivotConfig(savedChart): PivotConfig | undefined
pivotQueryResults(args): PivotData
derivePivotConfigurationFromChart(chart, query, itemsMap): PivotConfiguration | undefined
// === CHARTS-AS-CODE ===
type ChartAsCode, DashboardAsCode, DashboardTileAsCode
// === CHANGESETS ===
type Changeset, Change, ChangePayload
// === ENTERPRISE EDITION (EE) ===
type AiAgent, AiConversation, AiPrompt, AiAgentTool
type EmbedJwt, EmbedContent, FilterInteractivityValues
enum CommercialFeatureFlags (Embedding, Scim, AiCopilot, ServiceAccounts, OrganizationWarehouseCredentials, AgentReasoning)
type ScimUser, ScimGroup, ServiceAccount
// === CONSTANTS ===
UnitOfTime, TimeFrames, Format, Compact
JWT_HEADER_NAME, LightdashParameters, OrderFieldsByStrategy
enum LightdashInstallType (DOCKER_IMAGE, BASH_INSTALL, HEROKU, UNKNOWN)
// === JSON SCHEMAS ===
chartAsCodeSchema, dashboardAsCodeSchema, modelAsCodeSchema
lightdashDbtYamlSchema, lightdashProjectConfigSchema
// === TEST SEED DATA ===
SEED_ORG_1, SEED_ORG_2, SEED_PROJECT, SEED_SPACE, SEED_GROUP, SEED_GROUP_2, SEED_EMBED_SECRET
SEED_ORG_1_ADMIN, SEED_ORG_1_EDITOR, SEED_ORG_1_VIEWER, SEED_ORG_2_ADMIN
SPACE_TREE_1, SPACE_TREE_2 (Hierarchical space structures for testing)
// === TIMEZONE ===
enum TimeZone (29 timezones: UTC, America/New_York, Europe/London, Asia/Tokyo, etc.)
isTimeZone(timezone): timezone is TimeZone
// === SLACK INTEGRATION ===
type SlackSettings (OAuth scopes, channels, AI features, notification settings)
// === EMAIL VERIFICATION ===
type EmailStatus, EmailStatusExpiring, ApiEmailStatusResponse
// === CSV DOWNLOADS ===
type DownloadMetricCsv (CSV export configuration with formatting options)// Pattern 1: Query Building
import {
type MetricQuery,
type Explore,
FilterOperator,
UnitOfTime,
getFields,
getDimensions,
getMetrics,
} from "@lightdash/common";
// Pattern 2: Dashboard & Charts
import {
type Dashboard,
type SavedChart,
ChartKind,
type ChartConfig,
type DashboardTile,
} from "@lightdash/common";
// Pattern 3: Data Formatting
import {
formatItemValue,
formatDate,
formatTimestamp,
formatNumberValue,
type CustomFormat,
} from "@lightdash/common";
// Pattern 4: Authorization
import {
defineUserAbility,
type LightdashUser,
type ProjectMemberProfile,
type MemberAbility,
} from "@lightdash/common";
// Pattern 5: Compilation
import { ExploreCompiler, type UncompiledExplore, type Explore } from "@lightdash/common";
// Pattern 6: Warehouse Integration
import {
type WarehouseClient,
WarehouseTypes,
type WarehouseCredentials,
type Project,
} from "@lightdash/common";
// Pattern 7: Visualization
import {
CartesianChartDataModel,
PieChartDataModel,
ChartKind,
type VizCartesianChartOptions,
} from "@lightdash/common";
// Pattern 8: Filtering
import {
type Filters,
type FilterGroup,
type FilterRule,
FilterOperator,
isFilterGroup,
} from "@lightdash/common";
// Pattern 9: Field Operations
import {
getItemMap,
getFieldMap,
findFieldByIdInExplore,
getItemId,
type ItemsMap,
} from "@lightdash/common";
// Pattern 10: Validation & Type Guards
import { validateEmail, validatePassword, isDimension, isMetric, isField } from "@lightdash/common";// === TYPES ===
import {
// Data Modeling
type Explore,
type MetricQuery,
type Field,
type Dimension,
type Metric,
type CompiledField,
type CompiledDimension,
type CompiledMetric,
type Table,
type CompiledTable,
// Filtering
type Filters,
type FilterGroup,
type FilterRule,
FilterOperator,
// Dashboards & Charts
type Dashboard,
type SavedChart,
type ChartConfig,
ChartKind,
// Warehouses
type WarehouseClient,
type WarehouseCredentials,
WarehouseTypes,
// Projects
type Project,
type Space,
ProjectType,
} from "@lightdash/common";
// === COMPILER ===
import { ExploreCompiler } from "@lightdash/common";
// === UTILITIES ===
import {
// Explore/Field Operations
getFields,
getDimensions,
getMetrics,
getVisibleFields,
findFieldByIdInExplore,
getFieldMap,
getItemMap,
// Formatting
formatItemValue,
formatDate,
formatTimestamp,
formatNumberValue,
// Validation
validateEmail,
validatePassword,
validateOrganizationName,
// JSON Schemas
chartAsCodeSchema,
dashboardAsCodeSchema,
lightdashDbtYamlSchema,
lightdashProjectConfigSchema,
modelAsCodeSchema,
// Authorization
defineUserAbility,
// Visualization
CartesianChartDataModel,
PieChartDataModel,
TableDataModel,
} from "@lightdash/common";For CommonJS environments (Node.js with require):
// Note: TypeScript type imports are not available in CommonJS
// Use JSDoc comments for type hints if needed
const {
// Compiler
ExploreCompiler,
// Utilities
getFields,
getDimensions,
getMetrics,
formatItemValue,
validateEmail,
defineUserAbility,
// Data Models
CartesianChartDataModel,
PieChartDataModel,
TableDataModel,
// Enums
FilterOperator,
WarehouseTypes,
ChartKind,
// JSON Schemas
chartAsCodeSchema,
dashboardAsCodeSchema,
// Constants
JWT_HEADER_NAME,
} = require("@lightdash/common");Note: Type definitions are only available when using TypeScript or ESM imports. In CommonJS, types must be specified through JSDoc comments or TypeScript declaration files.
import {
type Explore,
type MetricQuery,
FilterOperator,
getFields,
getDimensions,
getMetrics,
} from '@lightdash/common';
// 1. Inspect available fields
const explore: Explore = /* ... */;
const allFields = getFields(explore);
const dimensions = getDimensions(explore);
const metrics = getMetrics(explore);
console.log(`Available: ${dimensions.length} dimensions, ${metrics.length} metrics`);
// 2. Build query
const query: MetricQuery = {
exploreName: explore.name,
dimensions: dimensions.slice(0, 2).map(d => d.name), // Select first 2 dimensions
metrics: metrics.slice(0, 3).map(m => m.name), // Select first 3 metrics
filters: {
dimensions: {
id: 'root',
and: [
{
id: 'date_filter',
target: { fieldId: 'orders.created_date' },
operator: FilterOperator.IN_THE_PAST,
values: [7],
settings: { unitOfTime: 'days' },
},
],
},
},
sorts: [{ fieldId: metrics[0].name, descending: true }],
limit: 100,
tableCalculations: [],
};
// 3. Execute query (requires warehouse client)
// See warehouse.md for execution detailsimport {
type Dashboard,
type DashboardTile,
type SavedChart,
ChartKind,
type MetricQuery,
} from "@lightdash/common";
// 1. Create saved chart
const savedChart: SavedChart = {
uuid: "chart-uuid-1",
projectUuid: "project-uuid",
name: "Revenue by Month",
description: "Monthly revenue trend",
tableName: "orders",
metricQuery: {
exploreName: "orders",
dimensions: ["orders.created_month"],
metrics: ["orders.total_revenue"],
filters: {},
sorts: [{ fieldId: "orders.created_month", descending: false }],
limit: 12,
tableCalculations: [],
},
chartConfig: {
type: ChartKind.VERTICAL_BAR,
config: {
layout: {
xField: "orders.created_month",
yField: ["orders.total_revenue"],
},
eChartsConfig: {},
},
},
tableConfig: {
columnOrder: [],
},
updatedAt: new Date(),
spaceUuid: "space-uuid",
dashboardUuid: null,
dashboardName: null,
};
// 2. Create dashboard with chart tile
const dashboard: Dashboard = {
organizationUuid: "org-uuid",
projectUuid: "project-uuid",
uuid: "dashboard-uuid",
name: "Sales Dashboard",
description: "Key sales metrics",
updatedAt: new Date(),
tiles: [
{
uuid: "tile-uuid-1",
type: "saved_chart",
properties: {
savedChartUuid: "chart-uuid-1",
title: "Revenue Trend",
hideTitle: false,
},
x: 0,
y: 0,
h: 10,
w: 12,
},
],
filters: {
dimensions: [],
metrics: [],
tableCalculations: [],
},
spaceUuid: "space-uuid",
views: 0,
firstViewedAt: null,
pinnedListUuid: null,
pinnedListOrder: null,
};import {
defineUserAbility,
type LightdashUser,
type ProjectMemberProfile,
} from "@lightdash/common";
// Define user with project memberships
const user: LightdashUser = {
userUuid: "user-uuid",
organizationUuid: "org-uuid",
role: "member",
roleUuid: "role-uuid",
/* ...other user properties */
};
const projectProfiles: ProjectMemberProfile[] = [
{
projectUuid: "project-1",
userUuid: "user-uuid",
role: "editor",
roleUuid: "editor-role-uuid",
},
];
// Get user abilities
const ability = defineUserAbility(user, projectProfiles);
// Check permissions
if (ability.can("view", "Dashboard")) {
console.log("User can view dashboards");
}
if (ability.can("update", "SavedChart")) {
console.log("User can edit charts");
}
// Check project-specific permissions
if (ability.can("view", { type: "Project", uuid: "project-1" })) {
console.log("User has access to project-1");
}import {
CartesianChartDataModel,
ChartKind,
type MetricQuery,
type Explore,
} from '@lightdash/common';
// Given: query results and configuration
const resultsRunner = /* IResultsRunner implementation */;
// Create data model
const dataModel = new CartesianChartDataModel({
resultsRunner,
fieldConfig: {
x: {
reference: 'orders.created_month',
type: 'category',
},
y: [
{
reference: 'orders.total_revenue',
aggregation: 'sum',
},
],
groupBy: undefined,
},
type: ChartKind.VERTICAL_BAR,
});
// Get ECharts options
const echartsOptions = dataModel.getChartOptions();
// Use with ECharts library (in frontend code)
// const chart = echarts.init(document.getElementById('chart'));
// chart.setOption(echartsOptions);import {
ExploreCompiler,
type UncompiledExplore,
type Explore,
type WarehouseSqlBuilder,
} from '@lightdash/common';
// Warehouse SQL builder (specific to your warehouse type)
const warehouseSqlBuilder: WarehouseSqlBuilder = /* ... */;
// Create compiler
const compiler = new ExploreCompiler(warehouseSqlBuilder);
// Uncompiled explore from DBT
const uncompiledExplore: UncompiledExplore = {
name: 'customers',
label: 'Customers',
tags: [],
baseTable: 'customers',
joinedTables: [],
tables: {
customers: {
name: 'customers',
label: 'Customers',
database: 'analytics',
schema: 'public',
sqlTable: 'customers',
dimensions: {
customer_id: {
name: 'customer_id',
label: 'Customer ID',
type: 'string',
sql: '${TABLE}.customer_id',
},
created_at: {
name: 'created_at',
label: 'Created At',
type: 'timestamp',
sql: '${TABLE}.created_at',
},
},
metrics: {
count: {
name: 'count',
label: 'Count',
type: 'count',
sql: '${TABLE}.customer_id',
},
},
},
},
/* ...other explore properties */
};
// Compile to executable explore
const explore: Explore = compiler.compileExplore(uncompiledExplore);
// Now explore has compiled SQL and can be queried
console.log(`Compiled explore: ${explore.name}`);
console.log(`Fields: ${Object.keys(explore.tables[explore.baseTable].dimensions).length} dimensions`);
console.log(`Metrics: ${Object.keys(explore.tables[explore.baseTable].metrics).length} metrics`);import { ExploreCompiler, type UncompiledExplore } from "@lightdash/common";
try {
const compiler = new ExploreCompiler(warehouseSqlBuilder);
const explore = compiler.compileExplore(uncompiledExplore);
console.log("Compilation successful");
} catch (error) {
if (error instanceof Error) {
// Compilation errors include details about what failed
console.error("Compilation failed:", error.message);
// Check for specific error types
if (error.message.includes("Circular dependency")) {
console.error("Found circular dependency in model");
} else if (error.message.includes("Unknown field reference")) {
console.error("Invalid field reference in SQL");
}
}
}import {
validateParameterReferences,
getParameterReferences,
getAvailableParameterNames,
} from "@lightdash/common";
const sql = "SELECT * FROM orders WHERE status = ${lightdash.parameters.order_status}";
try {
const references = getParameterReferences(sql);
const available = getAvailableParameterNames(projectParams, exploreParams);
validateParameterReferences("orders", references, available);
console.log("All parameters are valid");
} catch (error) {
if (error instanceof Error) {
console.error("Parameter validation failed:", error.message);
// Error message will indicate which parameters are missing
}
}import { FilterOperator, type MetricQuery, type FilterRule } from "@lightdash/common";
function createDateFilter(fieldId: string, days: number): FilterRule {
// Validate inputs
if (days <= 0) {
throw new Error("Days must be positive");
}
if (!fieldId.includes(".")) {
throw new Error('Field ID must be in format "table.field"');
}
return {
id: crypto.randomUUID(),
target: { fieldId },
operator: FilterOperator.IN_THE_PAST,
values: [days],
settings: { unitOfTime: "days" },
};
}
// Usage with error handling
try {
const filter = createDateFilter("orders.created_date", 30);
console.log("Filter created successfully");
} catch (error) {
console.error("Filter creation failed:", error.message);
}import { getFieldMap, getItemMap, type Explore } from "@lightdash/common";
// Instead of repeatedly calling getFields(), create a map once
const fieldMap = getFieldMap(explore);
const itemsMap = getItemMap(explore, additionalMetrics, tableCalculations);
// O(1) field lookup
const field = fieldMap["orders.customer_id"];
const item = itemsMap["orders.total_revenue"];import { ExploreCompiler, type Explore } from "@lightdash/common";
const exploreCache = new Map<string, Explore>();
function getCompiledExplore(
exploreName: string,
uncompiledExplore: UncompiledExplore,
compiler: ExploreCompiler
): Explore {
// Check cache first
if (exploreCache.has(exploreName)) {
return exploreCache.get(exploreName)!;
}
// Compile and cache
const explore = compiler.compileExplore(uncompiledExplore);
exploreCache.set(exploreName, explore);
return explore;
}import {
isCartesianChartConfig,
isPieChartConfig,
isTableChartConfig,
type ChartConfig,
} from "@lightdash/common";
function renderChart(chartConfig: ChartConfig) {
if (isCartesianChartConfig(chartConfig)) {
// TypeScript knows this is a CartesianChartConfig
console.log("Rendering cartesian chart:", chartConfig.type);
} else if (isPieChartConfig(chartConfig)) {
// TypeScript knows this is a PieChartConfig
console.log("Rendering pie chart");
} else if (isTableChartConfig(chartConfig)) {
// TypeScript knows this is a TableChartConfig
console.log("Rendering table");
}
}import { type WarehouseCredentials, WarehouseTypes } from "@lightdash/common";
function getConnectionString(credentials: WarehouseCredentials): string {
switch (credentials.type) {
case WarehouseTypes.BIGQUERY:
// TypeScript knows this is BigqueryCredentials
return `bigquery://${credentials.project}`;
case WarehouseTypes.POSTGRES:
// TypeScript knows this is PostgresCredentials
return `postgres://${credentials.host}:${credentials.port}/${credentials.dbname}`;
case WarehouseTypes.SNOWFLAKE:
// TypeScript knows this is SnowflakeCredentials
return `snowflake://${credentials.account}.snowflakecomputing.com`;
// ... other warehouse types
default:
throw new Error(`Unsupported warehouse type`);
}
}// DEPRECATED: getFieldQuoteChar()
// ❌ Old way (deprecated)
import { getFieldQuoteChar } from "@lightdash/common";
const quoteChar = getFieldQuoteChar(warehouseType);
// ✅ New way (recommended)
import { type WarehouseSqlBuilder } from "@lightdash/common";
const quoteChar = warehouseSqlBuilder.getFieldQuoteChar();