drizzle-cube
Version:
Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.
266 lines (265 loc) • 8.2 kB
TypeScript
import { ReactNode } from 'react';
import { ColorPalette } from './utils/colorPalettes';
export type { CubeMeta, CubeMetaCube, CubeMetaField, CubeMetaRelationship, FieldLabelMap } from './hooks/useCubeMeta';
export type { ColorPalette } from './utils/colorPalettes';
export type ChartType = 'line' | 'bar' | 'pie' | 'table' | 'area' | 'scatter' | 'radar' | 'radialBar' | 'treemap' | 'bubble' | 'activityGrid' | 'kpiNumber' | 'kpiDelta' | 'kpiText' | 'markdown';
export interface AxisFormatConfig {
label?: string;
unit?: 'currency' | 'percent' | 'number' | 'custom';
abbreviate?: boolean;
decimals?: number;
customPrefix?: string;
customSuffix?: string;
}
export interface ChartAxisConfig {
xAxis?: string[];
yAxis?: string[];
series?: string[];
sizeField?: string;
colorField?: string;
dateField?: string[];
valueField?: string[];
x?: string;
y?: string[];
yAxisAssignment?: Record<string, 'left' | 'right'>;
}
export interface ChartDisplayConfig {
showLegend?: boolean;
showGrid?: boolean;
showTooltip?: boolean;
colors?: string[];
orientation?: 'horizontal' | 'vertical';
stacked?: boolean;
stackType?: 'none' | 'normal' | 'percent';
connectNulls?: boolean;
hideHeader?: boolean;
minBubbleSize?: number;
maxBubbleSize?: number;
bubbleOpacity?: number;
showLabels?: boolean;
fitToWidth?: boolean;
pivotTimeDimension?: boolean;
target?: string;
template?: string;
prefix?: string;
suffix?: string;
decimals?: number;
formatValue?: (value: number | null | undefined) => string;
valueColor?: string;
valueColorIndex?: number;
positiveColorIndex?: number;
negativeColorIndex?: number;
showHistogram?: boolean;
useLastCompletePeriod?: boolean;
skipLastPeriod?: boolean;
content?: string;
accentColorIndex?: number;
fontSize?: 'small' | 'medium' | 'large';
alignment?: 'left' | 'center' | 'right';
xAxisFormat?: AxisFormatConfig;
leftYAxisFormat?: AxisFormatConfig;
rightYAxisFormat?: AxisFormatConfig;
/**
* How to display compared periods:
* - 'separate': Each period as distinct series with different colors (default)
* - 'overlay': Periods aligned by day-of-period index with ghost styling for prior periods
*/
comparisonMode?: 'separate' | 'overlay';
/** Line style for prior periods in overlay mode */
priorPeriodStyle?: 'solid' | 'dashed' | 'dotted';
/** Opacity for prior period lines (0-1), default: 0.5 */
priorPeriodOpacity?: number;
/** Include period labels in legend */
showPeriodLabels?: boolean;
}
export interface PortletConfig {
id: string;
title: string;
query: string;
chartType: ChartType;
chartConfig?: ChartAxisConfig;
displayConfig?: ChartDisplayConfig;
dashboardFilterMapping?: string[];
eagerLoad?: boolean;
w: number;
h: number;
x: number;
y: number;
}
export type DashboardLayoutMode = 'grid' | 'rows';
export interface DashboardGridSettings {
cols: number;
rowHeight: number;
minW: number;
minH: number;
}
export interface RowLayoutColumn {
portletId: string;
w: number;
}
export interface RowLayout {
id: string;
h: number;
columns: RowLayoutColumn[];
}
export interface DashboardConfig {
portlets: PortletConfig[];
layoutMode?: DashboardLayoutMode;
grid?: DashboardGridSettings;
rows?: RowLayout[];
layouts?: {
[key: string]: any;
};
colorPalette?: string;
filters?: DashboardFilter[];
eagerLoad?: boolean;
}
export type FilterOperator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'startsWith' | 'notStartsWith' | 'endsWith' | 'notEndsWith' | 'like' | 'notLike' | 'ilike' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'notBetween' | 'in' | 'notIn' | 'arrayContains' | 'arrayOverlaps' | 'arrayContained' | 'set' | 'notSet' | 'isEmpty' | 'isNotEmpty' | 'inDateRange' | 'beforeDate' | 'afterDate' | 'regex' | 'notRegex';
export interface SimpleFilter {
member: string;
operator: FilterOperator;
values: any[];
dateRange?: string | string[];
}
export interface GroupFilter {
type: 'and' | 'or';
filters: Filter[];
}
export type Filter = SimpleFilter | GroupFilter;
export interface DashboardFilter {
id: string;
label: string;
filter: Filter;
isUniversalTime?: boolean;
}
export interface CubeQuery {
measures?: string[];
dimensions?: string[];
timeDimensions?: Array<{
dimension: string;
granularity?: string;
dateRange?: string[] | string;
fillMissingDates?: boolean;
/**
* Array of date ranges for period-over-period comparison.
* When specified, queries are executed for each period and results are merged.
*/
compareDateRange?: (string | [string, string])[];
}>;
filters?: Filter[];
order?: {
[key: string]: 'asc' | 'desc';
};
limit?: number;
offset?: number;
segments?: string[];
}
/**
* Merge strategy for combining multiple query results
* - 'concat': Append rows with __queryIndex marker (for separate series per query)
* - 'merge': Align data by common dimension key (for combined visualization)
*/
export type QueryMergeStrategy = 'concat' | 'merge';
/**
* Configuration for multi-query portlets
* Detected by presence of 'queries' array property
*/
export interface MultiQueryConfig {
queries: CubeQuery[];
mergeStrategy: QueryMergeStrategy;
mergeKeys?: string[];
queryLabels?: string[];
}
/**
* Type guard to detect multi-query configuration
*/
export declare function isMultiQueryConfig(obj: unknown): obj is MultiQueryConfig;
export interface CubeQueryOptions {
skip?: boolean;
resetResultSetOnChange?: boolean;
subscribe?: boolean;
}
export interface CubeApiOptions {
apiUrl?: string;
token?: string;
headers?: Record<string, string>;
credentials?: 'include' | 'omit' | 'same-origin';
}
export interface CubeResultSet {
rawData(): any[];
tablePivot(): any[];
series(): any[];
annotation(): any;
loadResponse?: any;
cacheInfo?(): {
hit: true;
cachedAt: string;
ttlMs: number;
ttlRemainingMs: number;
} | undefined;
}
export interface AnalyticsPortletProps {
query: string;
chartType: ChartType;
chartConfig?: ChartAxisConfig;
displayConfig?: ChartDisplayConfig;
dashboardFilters?: DashboardFilter[];
dashboardFilterMapping?: string[];
eagerLoad?: boolean;
isVisible?: boolean;
height?: string | number;
title?: string;
colorPalette?: ColorPalette;
loadingComponent?: ReactNode;
onDebugDataReady?: (debugData: {
chartConfig: ChartAxisConfig;
displayConfig: ChartDisplayConfig;
queryObject: any;
data: any[];
chartType: ChartType;
cacheInfo?: {
hit: true;
cachedAt: string;
ttlMs: number;
ttlRemainingMs: number;
};
}) => void;
}
export interface AnalyticsDashboardProps {
config: DashboardConfig;
editable?: boolean;
dashboardFilters?: DashboardFilter[];
loadingComponent?: ReactNode;
onConfigChange?: (config: DashboardConfig) => void;
onSave?: (config: DashboardConfig) => Promise<void> | void;
onDirtyStateChange?: (isDirty: boolean) => void;
}
export interface ChartProps {
data: any[];
chartConfig?: ChartAxisConfig;
displayConfig?: ChartDisplayConfig;
queryObject?: CubeQuery;
height?: string | number;
colorPalette?: ColorPalette;
}
export interface FeaturesConfig {
enableAI?: boolean;
aiEndpoint?: string;
showSchemaDiagram?: boolean;
useAnalysisBuilder?: boolean;
editToolbar?: 'floating' | 'top' | 'both';
floatingToolbarPosition?: 'left' | 'right';
}
export interface GridLayout {
i: string;
x: number;
y: number;
w: number;
h: number;
minW?: number;
minH?: number;
}
export interface ResponsiveLayout {
[breakpoint: string]: GridLayout[];
}
export type DashboardDisplayMode = 'desktop' | 'scaled' | 'mobile';