Shared TypeScript library for the Lightdash platform containing common types, utilities, and business logic for analytics workflows
npx @tessl/cli install tessl/npm-lightdash--common@0.2231.5Lightdash Common (@lightdash/common) is a comprehensive TypeScript library providing shared types, utilities, and business logic for the Lightdash analytics platform. It enables building dbt-based BI applications with extensive support for data modeling, query execution, authorization, visualization, and warehouse integration across 7 data warehouse types.
npm install @lightdash/commonimport {
// Core types
type Explore,
type CompiledField,
type MetricQuery,
type Field,
type Filters,
type Dashboard,
type SavedChart,
// Query building
FilterOperator,
UnitOfTime,
// Utilities
getFields,
formatItemValue,
getVisibleFields,
validateEmail,
// Compiler
ExploreCompiler,
// Authorization
defineUserAbility,
getUserAbilityBuilder,
} from "@lightdash/common";For CommonJS environments (Node.js with require):
const {
// Note: Types not available in CommonJS (use JSDoc for type hints)
// Compiler
ExploreCompiler,
// Utilities
getFields,
getDimensions,
getMetrics,
formatItemValue,
getVisibleFields,
validateEmail,
// Authorization
defineUserAbility,
getUserAbilityBuilder,
// Enums
FilterOperator,
WarehouseTypes,
ChartKind,
} = require("@lightdash/common");Note: TypeScript type imports are not available in CommonJS. Use JSDoc comments for type hints if needed.
Complete workflow showing compilation, field access, and querying:
import {
type Explore,
type MetricQuery,
type Field,
ExploreCompiler,
FilterOperator,
UnitOfTime,
getFields,
getDimensions,
getMetrics,
formatItemValue,
} from "@lightdash/common";
// 1. Compile a dbt model into a Lightdash explore
const compiler = new ExploreCompiler({
warehouseClient,
targetWarehouse: "snowflake",
});
const compiledExplore = await compiler.compileExplore({
dbtManifest,
modelName: "customers",
// ... additional options
});
// 2. Access fields from the explore (data model)
const fields = getFields(compiledExplore);
const dimensions = getDimensions(compiledExplore);
const metrics = getMetrics(compiledExplore);
console.log(`Available: ${dimensions.length} dimensions, ${metrics.length} metrics`);
// 3. Format values for display
const formatted = formatItemValue(field, rawValue, true); // Convert to UTC
// 4. Build metric queries
const query: MetricQuery = {
exploreName: "customers",
dimensions: ["customer_id", "customer_name"],
metrics: ["total_revenue"],
filters: {
dimensions: {
id: "root",
and: [
{
target: { fieldId: "customer_created_at" },
operator: FilterOperator.IN_THE_PAST,
values: [6],
settings: { completed: true, unitOfTime: UnitOfTime.months },
},
],
},
},
sorts: [{ fieldId: "total_revenue", descending: true }],
limit: 100,
tableCalculations: [],
};import { type MetricQuery, FilterOperator, UnitOfTime } from "@lightdash/common";
const query: MetricQuery = {
exploreName: "orders",
dimensions: ["orders_customer_id", "orders_status"],
metrics: ["orders_count", "orders_total_revenue"],
filters: {
dimensions: {
id: "root",
and: [{
id: "date_filter",
target: { fieldId: "orders_created_at" },
operator: FilterOperator.IN_THE_PAST,
values: [30],
settings: { unitOfTime: UnitOfTime.days },
}],
},
},
sorts: [{ fieldId: "orders_total_revenue", descending: true }],
limit: 100,
tableCalculations: [],
};import { formatItemValue, getItemMap, type Explore, type MetricQuery } from "@lightdash/common";
// Get item map for formatting
const itemsMap = getItemMap(explore, query.additionalMetrics, query.tableCalculations, query.customDimensions);
// Format individual values
results.rows.forEach(row => {
Object.entries(row).forEach(([fieldId, value]) => {
const item = itemsMap[fieldId];
const formatted = formatItemValue(item, value, false); // Use false or true for UTC conversion
console.log(`${fieldId}: ${formatted}`);
});
});import { defineUserAbility, type LightdashUser, type ProjectMemberProfile } from "@lightdash/common";
const ability = defineUserAbility(user, projectProfiles);
if (ability.can("view", "Dashboard")) {
// User can view dashboards
}
if (ability.can("update", "SavedChart")) {
// User can edit charts
}Quick navigation to common tasks:
| Task | See |
|---|---|
| Build a query | Building Queries Guide |
| Filter data | Filter System |
| Parse filter expressions | Filter Parsing & DSL |
| Compare time periods | Period-over-Period Comparison |
| Format values | Formatting Guide |
| Create charts | Visualization Guide |
| Check permissions | Authorization Guide |
| Embed dashboards | JWT Authentication |
| Compile dbt models | Compilation Guide |
| Work with dashboards | Dashboards API |
| Access warehouse | Warehouse Integration |
| Import common APIs | Import Patterns |
| Look up an API | Common APIs |
Fast lookups for common needs:
Task-oriented tutorials:
Comprehensive API documentation:
Query Operations:
Charts and Visualization:
Core Features:
Core Utilities:
Specialized Utilities:
Additional reference materials:
An Explore is a compiled data model containing tables, dimensions, metrics, and joins. Explores are created by compiling dbt models using the ExploreCompiler.
// Key explore functions
import { getFields, getDimensions, getMetrics, type Explore } from "@lightdash/common";
const fields = getFields(explore); // All fields (dimensions + metrics)
const dimensions = getDimensions(explore); // Only dimensions
const metrics = getMetrics(explore); // Only metricsA MetricQuery declaratively defines what data to fetch without writing SQL:
interface MetricQuery {
exploreName: string; // Data model to query
dimensions: string[]; // Fields to group by
metrics: string[]; // Values to aggregate
filters: Filters; // Dimension/metric filters
sorts: SortField[]; // Sort order
limit: number; // Max rows
tableCalculations: TableCalculation[]; // Post-query calculations
additionalMetrics?: AdditionalMetric[]; // Ad-hoc metrics
customDimensions?: CustomDimension[]; // Runtime dimensions
}The filter system supports complex conditions with AND/OR logic:
enum FilterOperator {
EQUALS = 'equals',
NOT_EQUALS = 'notEquals',
LESS_THAN = 'lessThan',
GREATER_THAN = 'greaterThan',
IN_THE_PAST = 'inThePast',
IN_THE_NEXT = 'inTheNext',
IN_BETWEEN = 'inBetween',
// ... 12 more operators
}Format values based on field type and custom format options:
import { formatItemValue, type Field } from "@lightdash/common";
// Auto-detects field type and applies formatting
const formatted = formatItemValue(field, rawValue, {
timeZone: 'UTC',
parameters: {},
});Role-based permissions using CASL library:
import { defineUserAbility } from "@lightdash/common";
const ability = defineUserAbility(user, projectProfiles);
// Check permissions
if (ability.can('view', 'Dashboard')) { /* ... */ }
if (ability.can('update', { type: 'SavedChart', uuid: chartId })) { /* ... */ }import { getFieldMap, getItemMap } from "@lightdash/common";
// Create maps once for O(1) lookups
const fieldMap = getFieldMap(explore);
const itemsMap = getItemMap(explore, additionalMetrics, tableCalculations);
// Fast lookups
const field = fieldMap["orders_customer_id"];
const item = itemsMap["orders_total_revenue"];import { isDimension, isMetric, isTableCalculation } from "@lightdash/common";
function processField(field: Field) {
if (isDimension(field)) {
// TypeScript knows this is a Dimension
console.log("Dimension type:", field.type);
} else if (isMetric(field)) {
// TypeScript knows this is a Metric
console.log("Metric type:", field.type);
}
}import { ExploreCompiler, isExploreError } from "@lightdash/common";
try {
const explore = compiler.compileExplore(uncompiledExplore);
if (isExploreError(explore)) {
console.error("Compilation errors:", explore.errors);
} else {
// Use compiled explore
}
} catch (error) {
console.error("Compilation failed:", error.message);
}getFieldMap() once, reuse for O(1) lookups