or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bigquery-client.mdclickhouse-client.mdcore-types.mdcredentials.mddatabricks-client.mdfactory-functions.mdindex.mdpostgres-client.mdredshift-client.mdsnowflake-client.mdsql-builders.mdssh-tunnel.mdtrino-client.md
tile.json

factory-functions.mddocs/

Factory Functions

Create warehouse clients and SQL builders dynamically based on configuration.

Warehouse Client Factory

TypeScript/ESM:

// Import from @lightdash/warehouses (factory function)
// Import from @lightdash/common (types and enums)
import { warehouseClientFromCredentials } from '@lightdash/warehouses';
import { type CreateWarehouseCredentials, type WarehouseClient, WarehouseTypes } from '@lightdash/common';

/**
 * Creates a warehouse client instance based on credentials type
 *
 * Uses the 'type' discriminator field in credentials to instantiate
 * the correct warehouse-specific client class.
 *
 * @param credentials - Warehouse-specific credentials object with type discriminator
 *   - Must include 'type' field (e.g., WarehouseTypes.POSTGRES or 'postgres')
 *   - Type discriminator determines which client class is instantiated
 *   - Each warehouse type requires specific credential fields (see Credentials Reference)
 *   - All credentials must extend CreateWarehouseCredentials
 *
 * @returns WarehouseClient instance for the specified warehouse type
 *   - Returns concrete implementation (PostgresWarehouseClient, BigqueryWarehouseClient, etc.)
 *   - All returned clients implement WarehouseClient interface
 *   - Clients include warehouse-specific methods and properties
 *   - Type narrowing works based on credentials.type field
 *
 * @throws {UnexpectedServerError} If credentials type is not recognized or invalid
 *   - Thrown when credentials.type doesn't match any known warehouse type
 *   - Thrown when required credential fields are missing
 *   - Check error message for details on invalid credential format
 */
function warehouseClientFromCredentials(
  credentials: CreateWarehouseCredentials
): WarehouseClient;

CommonJS:

// Import from @lightdash/warehouses and @lightdash/common
const { warehouseClientFromCredentials } = require('@lightdash/warehouses');
const { WarehouseTypes } = require('@lightdash/common');

/**
 * @typedef {import('@lightdash/common').CreateWarehouseCredentials} CreateWarehouseCredentials
 * @typedef {import('@lightdash/common').WarehouseClient} WarehouseClient
 */

/**
 * Creates a warehouse client instance based on credentials type
 * @param {CreateWarehouseCredentials} credentials - Warehouse-specific credentials
 * @returns {WarehouseClient} Warehouse client instance
 * @throws {Error} If credentials type is not recognized
 */
function warehouseClientFromCredentials(credentials) {
  // Implementation handled by library
}

Usage:

// Type discriminator determines which client class is instantiated
const client = warehouseClientFromCredentials({
  type: WarehouseTypes.POSTGRES,  // or 'postgres' string literal
  host: 'localhost',
  port: 5432,
  user: 'myuser',
  password: 'mypassword',
  dbname: 'mydb',
  schema: 'public',
});
// Returns: PostgresWarehouseClient instance

Supported Types:

  • WarehouseTypes.BIGQUERYBigqueryWarehouseClient
  • WarehouseTypes.CLICKHOUSEClickhouseWarehouseClient (NOT exported)
  • WarehouseTypes.DATABRICKSDatabricksWarehouseClient
  • WarehouseTypes.POSTGRESPostgresWarehouseClient
  • WarehouseTypes.REDSHIFTRedshiftWarehouseClient
  • WarehouseTypes.SNOWFLAKESnowflakeWarehouseClient
  • WarehouseTypes.TRINOTrinoWarehouseClient

Note: For ClickHouse, you MUST use the factory function (class not exported).

SQL Builder Factory

TypeScript/ESM:

// Import from @lightdash/warehouses (factory function and builder classes)
// Import from @lightdash/common (enums)
import { warehouseSqlBuilderFromType } from '@lightdash/warehouses';
import { SupportedDbtAdapter, WeekDay } from '@lightdash/common';

/**
 * Creates a SQL builder instance based on adapter type
 *
 * @param adapterType - DBT adapter type string or SupportedDbtAdapter enum value
 *   - String values: 'postgres', 'bigquery', 'snowflake', 'databricks', 'redshift', 'trino', 'clickhouse'
 *   - Enum values: SupportedDbtAdapter.POSTGRES, SupportedDbtAdapter.BIGQUERY, etc.
 *   - Case-sensitive (use lowercase strings or enum values)
 *   - Used to determine which SQL builder class to instantiate
 *
 * @param startOfWeek - Optional week start day for date calculations
 *   - WeekDay enum value (0=Monday, 1=Tuesday, ..., 6=Sunday)
 *   - Used for week truncation functions and date arithmetic
 *   - If null: Uses warehouse-specific default (varies by warehouse)
 *   - If undefined: Same as null (uses warehouse default)
 *   - Affects SQL generation for date grouping and filtering
 *
 * @returns SQL builder instance for the specified adapter type
 *   - Returns concrete implementation (PostgresSqlBuilder, BigquerySqlBuilder, etc.)
 *   - All returned builders implement WarehouseSqlBuilder interface
 *   - Includes warehouse-specific SQL generation methods
 *   - Type union includes all supported builder classes
 *
 * @throws {Error} If adapter type is not recognized
 *   - Thrown when adapterType doesn't match any supported adapter
 *   - Error message includes list of supported adapter types
 */
function warehouseSqlBuilderFromType(
  adapterType: string | SupportedDbtAdapter,
  startOfWeek?: WeekDay | null
): BigquerySqlBuilder | ClickhouseSqlBuilder | DatabricksSqlBuilder
   | PostgresSqlBuilder | RedshiftSqlBuilder | SnowflakeSqlBuilder | TrinoSqlBuilder;

CommonJS:

// Import from @lightdash/warehouses and @lightdash/common
const { warehouseSqlBuilderFromType } = require('@lightdash/warehouses');
const { SupportedDbtAdapter, WeekDay } = require('@lightdash/common');

/**
 * @typedef {import('@lightdash/warehouses').PostgresSqlBuilder |
 *           import('@lightdash/warehouses').BigquerySqlBuilder |
 *           import('@lightdash/warehouses').SnowflakeSqlBuilder} SqlBuilder
 */

/**
 * Creates a SQL builder instance based on adapter type
 * @param {string | SupportedDbtAdapter} adapterType - DBT adapter type
 * @param {WeekDay | null} [startOfWeek] - Optional week start day (0=Monday, 6=Sunday)
 * @returns {SqlBuilder} SQL builder instance
 * @throws {Error} If adapter type is not recognized
 */
function warehouseSqlBuilderFromType(adapterType, startOfWeek) {
  // Implementation handled by library
}

Usage:

// By enum (recommended - type-safe)
const builder = warehouseSqlBuilderFromType(SupportedDbtAdapter.POSTGRES);

// By string (for runtime-determined types)
const builder2 = warehouseSqlBuilderFromType('postgres');

// With week start configuration (for date calculations)
const builder3 = warehouseSqlBuilderFromType(
  SupportedDbtAdapter.SNOWFLAKE,
  WeekDay.MONDAY  // 0=Monday, 6=Sunday
);

// Use the builder
const fieldQuote = builder.getFieldQuoteChar();     // '"' for Postgres
const metricSql = builder.getMetricSql('revenue', {
  type: MetricType.SUM,
  sql: 'amount'
});  // 'SUM(amount)' for Postgres

Supported Adapters:

  • BIGQUERYBigquerySqlBuilder
  • CLICKHOUSEClickhouseSqlBuilder (NOT exported)
  • DATABRICKSDatabricksSqlBuilder
  • POSTGRESPostgresSqlBuilder
  • REDSHIFTRedshiftSqlBuilder
  • SNOWFLAKESnowflakeSqlBuilder
  • TRINOTrinoSqlBuilder

Direct Class Import

Most classes are exported for direct use:

import {
  BigqueryWarehouseClient,
  // ClickhouseWarehouseClient - NOT exported
  DatabricksWarehouseClient,
  PostgresWarehouseClient,
  RedshiftWarehouseClient,
  SnowflakeWarehouseClient,
  TrinoWarehouseClient,
} from '@lightdash/warehouses';

const client = new PostgresWarehouseClient(credentials);

When to use factory vs direct:

  • Factory: Runtime warehouse type (user selection, config file)
    • User selects warehouse type in UI
    • Credentials loaded from configuration file
    • Type determined by environment variables
    • Building multi-warehouse support systems
  • Direct: Development-time known warehouse type
    • Hardcoded single warehouse integration
    • TypeScript can infer specific client methods
    • Better IDE autocomplete for warehouse-specific features

Edge Case - ClickHouse: Must use factory function (class not exported)

Databricks OAuth Functions

Additional helper functions for Databricks OAuth flows:

import {
  exchangeDatabricksOAuthCredentials,
  refreshDatabricksOAuthToken,
} from '@lightdash/warehouses';

/**
 * Exchange OAuth client credentials for access token (M2M flow)
 * Machine-to-Machine authentication for service accounts
 * @param host - Databricks workspace hostname (without https://)
 * @param clientId - OAuth client ID
 * @param clientSecret - OAuth client secret
 * @returns Promise with accessToken and optional refreshToken
 */
async function exchangeDatabricksOAuthCredentials(
  host: string,
  clientId: string,
  clientSecret: string
): Promise<{ accessToken: string; refreshToken?: string }>;

/**
 * Refresh OAuth access token using refresh token (U2M flow)
 * User-to-Machine authentication for delegated access
 * @param host - Databricks workspace hostname (without https://)
 * @param clientId - OAuth client ID
 * @param refreshToken - Valid refresh token from previous OAuth flow
 * @returns Promise with new accessToken, refreshToken, and expiresIn (seconds)
 */
async function refreshDatabricksOAuthToken(
  host: string,
  clientId: string,
  refreshToken: string
): Promise<{ accessToken: string; refreshToken: string; expiresIn: number }>;

Usage:

// M2M: Exchange client credentials for access token (service-to-service)
const tokens = await exchangeDatabricksOAuthCredentials(
  'my-workspace.cloud.databricks.com',  // No https:// prefix
  'client-id',
  'client-secret'
);
console.log('Access token:', tokens.accessToken);
// refreshToken may be undefined for M2M flow

// U2M: Refresh access token (user delegation)
const refreshed = await refreshDatabricksOAuthToken(
  'my-workspace.cloud.databricks.com',
  'client-id',
  'refresh-token'
);
console.log('New access token:', refreshed.accessToken);
console.log('Expires in:', refreshed.expiresIn, 'seconds');
// Store new refresh token for next refresh

OAuth Flow Types:

  • M2M (Machine-to-Machine): Service accounts, automated systems, no user interaction
  • U2M (User-to-Machine): User delegated access, requires initial user login flow
  • See Databricks Client for complete OAuth configuration

Type Definitions

Complete type definitions used by factory functions:

import {
  type CreateWarehouseCredentials,
  type CreateBigqueryCredentials,
  type CreateClickhouseCredentials,
  type CreateDatabricksCredentials,
  type CreatePostgresCredentials,
  type CreateRedshiftCredentials,
  type CreateSnowflakeCredentials,
  type CreateTrinoCredentials,
  WarehouseTypes,
  SupportedDbtAdapter,
  WeekDay,
} from '@lightdash/common';

/**
 * Discriminated union of all warehouse credential types
 * Type discriminator is the 'type' property
 */
type CreateWarehouseCredentials =
  | CreateBigqueryCredentials
  | CreateClickhouseCredentials
  | CreateDatabricksCredentials
  | CreatePostgresCredentials
  | CreateRedshiftCredentials
  | CreateSnowflakeCredentials
  | CreateTrinoCredentials;

/**
 * Warehouse type enum for credential type discrimination
 */
enum WarehouseTypes {
  BIGQUERY = 'bigquery',
  CLICKHOUSE = 'clickhouse',
  DATABRICKS = 'databricks',
  POSTGRES = 'postgres',
  REDSHIFT = 'redshift',
  SNOWFLAKE = 'snowflake',
  TRINO = 'trino',
}

/**
 * DBT adapter type enum for SQL builder selection
 */
enum SupportedDbtAdapter {
  BIGQUERY = 'bigquery',
  CLICKHOUSE = 'clickhouse',
  DATABRICKS = 'databricks',
  POSTGRES = 'postgres',
  REDSHIFT = 'redshift',
  SNOWFLAKE = 'snowflake',
  TRINO = 'trino',
}

/**
 * Week start day configuration for SQL builders
 */
enum WeekDay {
  MONDAY = 0,
  TUESDAY = 1,
  WEDNESDAY = 2,
  THURSDAY = 3,
  FRIDAY = 4,
  SATURDAY = 5,
  SUNDAY = 6,
}

For specific credential type details, see Credentials Reference.

Not Exported

The following are NOT exported and must use factory functions:

  • ClickhouseWarehouseClient - use warehouseClientFromCredentials()
  • ClickhouseSqlBuilder - use warehouseSqlBuilderFromType()
  • ClickhouseTypes enum - types handled internally