All files / server/types query.ts

0% Statements 0/0
0% Branches 0/0
0% Functions 0/0
0% Lines 0/0

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186                                                                                                                                                                                                                                                                                                                                                                                   
/**
 * Query-related types for the semantic layer
 * Includes query definitions, filters, and time dimensions
 */
 
import type { TimeGranularity } from './core'
import type { FunnelQueryConfig } from './funnel'
import type { FlowQueryConfig } from './flow'
import type { RetentionQueryConfig } from './retention'
 
/**
 * Semantic query structure (Cube.js compatible)
 */
export interface SemanticQuery {
  measures?: string[]
  dimensions?: string[]
  filters?: Array<Filter>
  timeDimensions?: Array<TimeDimension>
  limit?: number
  offset?: number
  order?: Record<string, 'asc' | 'desc'>
  /**
   * Default value to fill missing time series gaps with.
   * Used when fillMissingDates is enabled on time dimensions.
   * Default: 0
   */
  fillMissingDatesValue?: number | null
 
  /**
   * Funnel analysis configuration for query-time funnel definition.
   * When specified, the query executes as a funnel analysis instead of
   * standard measures/dimensions aggregation.
   *
   * @example
   * ```typescript
   * {
   *   funnel: {
   *     bindingKey: 'Events.userId',
   *     timeDimension: 'Events.timestamp',
   *     steps: [
   *       { name: 'Signup', filter: { member: 'Events.eventType', operator: 'equals', values: ['signup'] } },
   *       { name: 'Activation', filter: { member: 'Events.eventType', operator: 'equals', values: ['activation'] }, timeToConvert: 'P7D' }
   *     ]
   *   }
   * }
   * ```
   */
  funnel?: FunnelQueryConfig
 
  /**
   * Flow analysis configuration for bidirectional path exploration.
   * When specified, the query executes as a flow analysis instead of
   * standard measures/dimensions aggregation.
   *
   * Flow analysis explores paths BEFORE and AFTER a defined starting step,
   * producing Sankey diagram data (nodes and links).
   *
   * @example
   * ```typescript
   * {
   *   flow: {
   *     bindingKey: 'Events.userId',
   *     timeDimension: 'Events.timestamp',
   *     eventDimension: 'Events.eventType',
   *     startingStep: {
   *       name: 'Purchase',
   *       filter: { member: 'Events.eventType', operator: 'equals', values: ['purchase'] }
   *     },
   *     stepsBefore: 3,
   *     stepsAfter: 2
   *   }
   * }
   * ```
   */
  flow?: FlowQueryConfig
 
  /**
   * Retention analysis configuration for cohort-based retention tracking.
   * When specified, the query executes as a retention analysis instead of
   * standard measures/dimensions aggregation.
   *
   * Retention analysis tracks what percentage of users from each cohort
   * return in subsequent time periods.
   *
   * @example
   * ```typescript
   * {
   *   retention: {
   *     timeDimension: 'Events.timestamp',
   *     bindingKey: 'Events.userId',
   *     dateRange: { start: '2024-01-01', end: '2024-12-31' },
   *     granularity: 'week',
   *     periods: 12,
   *     retentionType: 'classic',
   *     breakdownDimensions: ['Events.country', 'Events.plan']
   *   }
   * }
   * ```
   */
  retention?: RetentionQueryConfig
}
 
/**
 * Filter definitions with logical operators
 */
export type Filter = FilterCondition | LogicalFilter
 
export interface FilterCondition {
  member: string
  operator: FilterOperator
  values: any[]
  dateRange?: string | string[]
}
 
export interface LogicalFilter {
  and?: Filter[]
  or?: Filter[]
}
 
/**
 * Time dimension with granularity
 */
export interface TimeDimension {
  dimension: string
  granularity?: TimeGranularity
  dateRange?: string | string[]
  /**
   * Fill missing dates in time series with the fill value.
   * Requires both granularity and dateRange to be set.
   * Default: true (enabled)
   */
  fillMissingDates?: boolean
  /**
   * Array of date ranges for period-over-period comparison.
   * When specified, queries are executed for each period and results are merged
   * with period metadata (__periodIndex, __periodDayIndex) for alignment.
   *
   * Each range can be:
   * - A relative string: 'this week', 'last month', 'last 30 days'
   * - A tuple: ['2024-01-01', '2024-01-31']
   *
   * @example
   * compareDateRange: [
   *   'last 30 days',                    // Current period
   *   ['2024-01-01', '2024-01-30']       // Prior period to compare
   * ]
   */
  compareDateRange?: (string | [string, string])[]
}
 
/**
 * Supported filter operators
 */
export type FilterOperator = 
  | 'equals' 
  | 'notEquals' 
  | 'contains' 
  | 'notContains'
  | 'startsWith'
  | 'notStartsWith'
  | 'endsWith'
  | 'notEndsWith'
  | 'gt'
  | 'gte'
  | 'lt'
  | 'lte'
  | 'set'
  | 'notSet'
  | 'inDateRange'
  | 'beforeDate'
  | 'afterDate'
  | 'between'
  | 'notBetween'
  | 'in'
  | 'notIn'
  | 'like'
  | 'notLike'
  | 'ilike'
  | 'regex'
  | 'notRegex'
  | 'isEmpty'
  | 'isNotEmpty'
  // PostgreSQL array operators
  | 'arrayContains'
  | 'arrayOverlaps'
  | 'arrayContained'