CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-lightdash--common

Shared TypeScript library for the Lightdash platform containing common types, utilities, and business logic for analytics workflows

Overall
score

72%

Evaluation72%

1.09x

Agent success when using this tile

Overview
Eval results
Files

jobs.mddocs/api/types/

Background Jobs

Background job types for tracking asynchronous operations like project compilation and creation.

Capabilities

Job Types

Defines the types of background jobs that can be executed.

enum JobType {
  COMPILE_PROJECT = 'COMPILE_PROJECT',
  CREATE_PROJECT = 'CREATE_PROJECT'
}

Job Status

Status values for tracking job execution state.

enum JobStatusType {
  STARTED = 'STARTED',
  DONE = 'DONE',
  RUNNING = 'RUNNING',
  ERROR = 'ERROR'
}

Job Step Status

Status values for individual steps within a job.

enum JobStepStatusType {
  DONE = 'DONE',
  RUNNING = 'RUNNING',
  ERROR = 'ERROR',
  PENDING = 'PENDING',
  SKIPPED = 'SKIPPED'
}

Job Step Types

Types of steps that can be executed within a job.

enum JobStepType {
  TESTING_ADAPTOR = 'TESTING_ADAPTOR',
  COMPILING = 'COMPILING',
  CREATING_PROJECT = 'CREATING_PROJECT',
  CACHING = 'CACHING'
}

Job Step Labels

Human-readable labels for job steps.

const JobLabels: {
  TESTING_ADAPTOR: 'Testing adaptor';
  COMPILING: 'Compiling';
  CREATING_PROJECT: 'Creating project';
  CACHING: 'Saving cache';
};

Base Job

Base structure for all job types.

interface BaseJob {
  jobUuid: string;
  projectUuid: string | undefined;
  userUuid: string | undefined;
  createdAt: Date;
  updatedAt: Date;
  jobStatus: JobStatusType;
  steps: JobStep[];
}

Job Union Type

The main exported job type is a discriminated union of different job kinds. You cannot import CompileJob or CreateProjectJob directly - instead, import the Job union type and use type guards (isCompileJob, isCreateProjectJob) to narrow the type.

type Job = CompileJob | CreateProjectJob;

Where CompileJob and CreateProjectJob are part of the union:

// Part of Job union type (not separately importable)
type CompileJob = BaseJob & {
  jobType: JobType.COMPILE_PROJECT;
  jobResults?: {
    indexCatalogJobUuid: string;
  };
};

// Part of Job union type (not separately importable)
type CreateProjectJob = BaseJob & {
  jobType: JobType.CREATE_PROJECT;
  jobResults?: {
    projectUuid: string;
  };
};

Note: Import the Job union type and use type guards to safely access job-specific properties.

Job Type Guards

Type guards for discriminating between job types at runtime. Use these to safely access job-specific properties.

/**
 * Check if a job is a CompileJob
 * @param value - Value to check
 * @returns True if value is a CompileJob
 */
function isCompileJob(value: unknown): value is CompileJob;

/**
 * Check if a job is a CreateProjectJob
 * @param value - Value to check
 * @returns True if value is a CreateProjectJob
 */
function isCreateProjectJob(value: unknown): value is CreateProjectJob;

Job Step

Individual step within a job execution.

interface JobStep {
  jobUuid: string;
  createdAt: Date;
  updatedAt: Date;
  stepStatus: JobStepStatusType;
  stepType: JobStepType;
  stepError: string | undefined;
  stepDbtLogs: DbtLog[] | undefined;
  stepLabel: string;
  startedAt: Date | undefined;
}

DBT Logs

Structured logging from dbt operations following the dbt events-logging specification.

interface DbtLog {
  code: string;
  info: {
    category: string;
    code: string;
    extra: Record<string, unknown>;
    invocation_id: string;
    level: 'debug' | 'info' | 'warn' | 'error';
    log_version: 2;
    msg: string;
    name: string;
    pid: number;
    thread_name: string;
    ts: string;
    type: 'log_line';
  };
}

/**
 * Check if a value is a valid DbtLog
 * @param value - Value to check
 * @returns True if value is a DbtLog
 */
function isDbtLog(value: unknown): value is DbtLog;

Create Job

Type for creating a new job with minimal required fields.

type CreateJob = Pick<
  Job,
  'jobUuid' | 'projectUuid' | 'jobType' | 'jobStatus' | 'userUuid'
> & {
  steps: CreateJobStep[];
};

type CreateJobStep = Pick<JobStep, 'stepType'>;

Scheduler Task List

Constants and types for defining and identifying background tasks that can be scheduled and executed by the scheduler system.

/**
 * Core scheduler task names for background jobs
 */
const SCHEDULER_TASKS: {
  HANDLE_SCHEDULED_DELIVERY: 'handleScheduledDelivery';
  SEND_SLACK_NOTIFICATION: 'sendSlackNotification';
  SEND_EMAIL_NOTIFICATION: 'sendEmailNotification';
  SEND_MSTEAMS_NOTIFICATION: 'sendMsTeamsNotification';
  UPLOAD_GSHEETS: 'uploadGsheets';
  DOWNLOAD_CSV: 'downloadCsv';
  UPLOAD_GSHEET_FROM_QUERY: 'uploadGsheetFromQuery';
  VALIDATE_PROJECT: 'validateProject';
  COMPILE_PROJECT: 'compileProject';
  CREATE_PROJECT_WITH_COMPILE: 'createProjectWithCompile';
  TEST_AND_COMPILE_PROJECT: 'testAndCompileProject';
  SQL_RUNNER: 'sqlRunner';
  SQL_RUNNER_PIVOT_QUERY: 'sqlRunnerPivotQuery';
  REPLACE_CUSTOM_FIELDS: 'replaceCustomFields';
  INDEX_CATALOG: 'indexCatalog';
  GENERATE_DAILY_JOBS: 'generateDailyJobs';
  EXPORT_CSV_DASHBOARD: 'exportCsvDashboard';
  RENAME_RESOURCES: 'renameResources';
  CLEAN_QUERY_HISTORY: 'cleanQueryHistory';
  DOWNLOAD_ASYNC_QUERY_RESULTS: 'downloadAsyncQueryResults';
  // Enterprise Edition tasks
  SLACK_AI_PROMPT: 'slackAiPrompt';
  AI_AGENT_EVAL_RESULT: 'aiAgentEvalResult';
  EMBED_ARTIFACT_VERSION: 'embedArtifactVersion';
  GENERATE_ARTIFACT_QUESTION: 'generateArtifactQuestion';
};

/**
 * Enterprise Edition scheduler task names
 */
const EE_SCHEDULER_TASKS: {
  SLACK_AI_PROMPT: 'slackAiPrompt';
  AI_AGENT_EVAL_RESULT: 'aiAgentEvalResult';
  EMBED_ARTIFACT_VERSION: 'embedArtifactVersion';
  GENERATE_ARTIFACT_QUESTION: 'generateArtifactQuestion';
};

/**
 * Union type of all valid scheduler task names
 */
type SchedulerTaskName = typeof SCHEDULER_TASKS[keyof typeof SCHEDULER_TASKS];

/**
 * Maps each scheduler task name to its payload type
 */
interface TaskPayloadMap {
  [SCHEDULER_TASKS.HANDLE_SCHEDULED_DELIVERY]: ScheduledDeliveryPayload;
  [SCHEDULER_TASKS.SEND_SLACK_NOTIFICATION]: SlackNotificationPayload;
  [SCHEDULER_TASKS.SEND_EMAIL_NOTIFICATION]: EmailNotificationPayload;
  [SCHEDULER_TASKS.SEND_MSTEAMS_NOTIFICATION]: MsTeamsNotificationPayload;
  [SCHEDULER_TASKS.UPLOAD_GSHEETS]: GsheetsNotificationPayload;
  [SCHEDULER_TASKS.DOWNLOAD_CSV]: DownloadCsvPayload;
  [SCHEDULER_TASKS.UPLOAD_GSHEET_FROM_QUERY]: UploadMetricGsheetPayload;
  [SCHEDULER_TASKS.VALIDATE_PROJECT]: ValidateProjectPayload;
  [SCHEDULER_TASKS.COMPILE_PROJECT]: CompileProjectPayload;
  [SCHEDULER_TASKS.CREATE_PROJECT_WITH_COMPILE]: SchedulerCreateProjectWithCompilePayload;
  [SCHEDULER_TASKS.TEST_AND_COMPILE_PROJECT]: CompileProjectPayload;
  [SCHEDULER_TASKS.SQL_RUNNER]: SqlRunnerPayload;
  [SCHEDULER_TASKS.SQL_RUNNER_PIVOT_QUERY]: SqlRunnerPivotQueryPayload;
  [SCHEDULER_TASKS.REPLACE_CUSTOM_FIELDS]: ReplaceCustomFieldsPayload;
  [SCHEDULER_TASKS.INDEX_CATALOG]: SchedulerIndexCatalogJobPayload;
  [SCHEDULER_TASKS.GENERATE_DAILY_JOBS]: TraceTaskBase;
  [SCHEDULER_TASKS.EXPORT_CSV_DASHBOARD]: ExportCsvDashboardPayload;
  [SCHEDULER_TASKS.SLACK_AI_PROMPT]: SlackPromptJobPayload;
  [SCHEDULER_TASKS.RENAME_RESOURCES]: RenameResourcesPayload;
  [SCHEDULER_TASKS.CLEAN_QUERY_HISTORY]: TraceTaskBase;
  [SCHEDULER_TASKS.DOWNLOAD_ASYNC_QUERY_RESULTS]: DownloadAsyncQueryResultsPayload;
  [SCHEDULER_TASKS.AI_AGENT_EVAL_RESULT]: AiAgentEvalRunJobPayload;
  [SCHEDULER_TASKS.EMBED_ARTIFACT_VERSION]: EmbedArtifactVersionJobPayload;
  [SCHEDULER_TASKS.GENERATE_ARTIFACT_QUESTION]: GenerateArtifactQuestionJobPayload;
}

/**
 * Maps Enterprise Edition task names to their payload types
 */
interface EETaskPayloadMap {
  [EE_SCHEDULER_TASKS.SLACK_AI_PROMPT]: SlackPromptJobPayload;
  [EE_SCHEDULER_TASKS.AI_AGENT_EVAL_RESULT]: AiAgentEvalRunJobPayload;
  [EE_SCHEDULER_TASKS.EMBED_ARTIFACT_VERSION]: EmbedArtifactVersionJobPayload;
  [EE_SCHEDULER_TASKS.GENERATE_ARTIFACT_QUESTION]: GenerateArtifactQuestionJobPayload;
}

/**
 * Type guard to check if a string is a valid scheduler task name
 * @param task - Task name to validate
 * @returns True if task is a valid SchedulerTaskName
 */
function isSchedulerTaskName(task: string): task is SchedulerTaskName;

Usage Examples

Monitoring Job Status

import { type Job, JobStatusType, isCompileJob, isCreateProjectJob } from '@lightdash/common';

// Job is a discriminated union - use type guards to narrow the type
function checkJobStatus(job: Job): void {
  if (job.jobStatus === JobStatusType.DONE) {
    // Use type guard to narrow Job to CompileJob
    if (isCompileJob(job)) {
      console.log('Compilation completed:', job.jobResults?.indexCatalogJobUuid);
    }
    // Use type guard to narrow Job to CreateProjectJob
    else if (isCreateProjectJob(job)) {
      console.log('Project created:', job.jobResults?.projectUuid);
    }
  } else if (job.jobStatus === JobStatusType.ERROR) {
    const errorSteps = job.steps.filter(step => step.stepError);
    console.error('Job failed with errors:', errorSteps);
  }
}

Tracking Job Progress

import { type JobStep, JobStepStatusType, JobLabels } from '@lightdash/common';

function getJobProgress(steps: JobStep[]): number {
  const completedSteps = steps.filter(
    step => step.stepStatus === JobStepStatusType.DONE
  ).length;

  return (completedSteps / steps.length) * 100;
}

function getJobStepLabel(step: JobStep): string {
  return JobLabels[step.stepType] || step.stepLabel;
}

Install with Tessl CLI

npx tessl i tessl/npm-lightdash--common

docs

api

index.md

tile.json